From 4a3ba6b9173a6476184fe10db1cf6d475b6a3cad Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 2 Nov 2022 20:55:39 +0000 Subject: [PATCH 01/50] rework currency display --- .../TransactionRequest/TxFeeNew/index.js | 73 ++++++------------- .../TransactionRequest/TxMain/index.js | 31 ++++---- .../TxMain/style/index.styl | 3 - resources/domain/transaction/index.ts | 20 +++++ 4 files changed, 61 insertions(+), 66 deletions(-) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index d208d5569..1fe39712c 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -2,26 +2,15 @@ import React from 'react' import Restore from 'react-restore' import BigNumber from 'bignumber.js' -import { usesBaseFee, GasFeesSource } from '../../../../../../../resources/domain/transaction' +import { GasFeesSource, toUSD, toEther, usesBaseFee } from '../../../../../../../resources/domain/transaction' import link from '../../../../../../../resources/link' import { ClusterBox, Cluster, ClusterRow, ClusterColumn, ClusterValue } from '../../../../../../../resources/Components/Cluster' const FEE_WARNING_THRESHOLD_USD = 50 -function toDisplayUSD (bn) { - const usd = bn.decimalPlaces(2, BigNumber.ROUND_FLOOR) - return usd.isZero() ? '< $0.01' : `$${usd.toFormat()}` -} - -function toDisplayEther (bn) { - const ether = bn.shiftedBy(-18).decimalPlaces(6, BigNumber.ROUND_FLOOR) - - return ether.isZero() ? '< 0.000001' : ether.toFormat() -} - function toDisplayGwei (bn) { - const gwei = bn.shiftedBy(-9).decimalPlaces(3, BigNumber.ROUND_FLOOR) + const gwei = bn.shiftedBy(-9).decimalPlaces(6, BigNumber.ROUND_FLOOR) return gwei.isZero() ? '' : gwei.toFormat() } @@ -43,21 +32,13 @@ const GasDisplay = ({ maxFeePerGas }) => { ) } -const USDEstimateDisplay = ({ maxFeePerGas, maxGas, maxFeeUSD, nativeUSD, symbol }) => { - // accounts for two potential 12.5% block fee increases - const reduceFactor = BigNumber(9).dividedBy(8) - const minFeePerGas = maxFeePerGas.dividedBy(reduceFactor).dividedBy(reduceFactor) - - // accounts for the 50% padding in the gas estimate in the provider - const minGas = maxGas.dividedBy(BigNumber(1.5)) - - const minFee = minFeePerGas.multipliedBy(minGas) - const minFeeUSD = minFee.shiftedBy(-18).multipliedBy(nativeUSD) - const displayMinFeeUSD = toDisplayUSD(minFeeUSD) - const displayMaxFeeUSD = toDisplayUSD(maxFeeUSD) +const USDEstimateDisplay = ({ minFee, maxFee, nativeCurrency, isTestnet }) => { + const { displayUSD: displayMinFeeUSD } = toUSD(minFee, nativeCurrency, isTestnet) + const { usd: maxFeeUSD, displayUSD: displayMaxFeeUSD } = toUSD(maxFee, nativeCurrency, isTestnet) + const displayMaxFeeWarning = maxFeeUSD > FEE_WARNING_THRESHOLD_USD return
-
FEE_WARNING_THRESHOLD_USD ? '_txFeeValueDefault _txFeeValueDefaultWarn' : '_txFeeValueDefault'}> +
{'≈'} {displayMaxFeeUSD === '< $0.01' ? {displayMaxFeeUSD} : @@ -67,7 +48,7 @@ const USDEstimateDisplay = ({ maxFeePerGas, maxGas, maxFeeUSD, nativeUSD, symbol {displayMaxFeeUSD} } - {`in ${symbol}`} + {`in ${nativeCurrency.symbol}`}
} @@ -79,34 +60,28 @@ class TxFee extends React.Component { render () { const req = this.props.req - const chain = { type: 'ethereum', id: parseInt(req.data.chainId, 16) } - const { isTestnet } = this.store('main.networks', chain.type, chain.id) - const {nativeCurrency, nativeCurrency: {symbol}} = this.store('main.networksMeta', chain.type, chain.id,) - const nativeUSD = nativeCurrency && nativeCurrency.usd && !isTestnet ? nativeCurrency.usd.price : 0 - - let maxFeePerGas, maxFee, maxFeeUSD + const { nativeCurrency } = this.store('main.networksMeta', chain.type, chain.id) const maxGas = BigNumber(req.data.gasLimit, 16) - - if (usesBaseFee(req.data)) { - maxFeePerGas = BigNumber(req.data.maxFeePerGas, 16) - maxFee = maxFeePerGas.multipliedBy(maxGas) - maxFeeUSD = maxFee.shiftedBy(-18).multipliedBy(nativeUSD) - } else { - maxFeePerGas = BigNumber(req.data.gasPrice, 16) - maxFee = maxFeePerGas.multipliedBy(maxGas) - maxFeeUSD = maxFee.shiftedBy(-18).multipliedBy(nativeUSD) - } - - const displayEther = toDisplayEther(maxFee) - + const maxFeePerGas = BigNumber(req.data[usesBaseFee(req.data) ? 'maxFeePerGas' : 'gasPrice'], 16) + const maxFee = maxFeePerGas.multipliedBy(maxGas) + const { displayEther } = toEther(maxFee, 6) + + // accounts for two potential 12.5% block fee increases + const reduceFactor = BigNumber(9).dividedBy(8) + const minFeePerGas = maxFeePerGas.dividedBy(reduceFactor).dividedBy(reduceFactor) + + // accounts for the 50% padding in the gas estimate in the provider + const minGas = maxGas.dividedBy(BigNumber(1.5)) + const minFee = minFeePerGas.multipliedBy(minGas) + return ( - + @@ -119,12 +94,12 @@ class TxFee extends React.Component {
- {symbol} + {nativeCurrency.symbol} {displayEther}
- +
diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js index 5723c94fc..bf0972623 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js @@ -1,11 +1,12 @@ import React from 'react' import Restore from 'react-restore' -import link from '../../../../../../../resources/link' -import svg from '../../../../../../../resources/svg' -import utils from 'web3-utils' +import BigNumber from 'bignumber.js' import { getAddress } from '@ethersproject/address' +import link from '../../../../../../../resources/link' +import svg from '../../../../../../../resources/svg' import { Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' +import { toEther, toUSD } from '../../../../../../../resources/domain/transaction' class TxSending extends React.Component { constructor (...args) { @@ -14,25 +15,28 @@ class TxSending extends React.Component { copied: false } } + copyAddress (data) { link.send('tray:clipboardData', data) this.setState({ copied: true }) - setTimeout(_ => this.setState({ copied: false }), 1000) - } - hexToDisplayValue (hex) { - return (Math.round(parseFloat(utils.fromWei(hex, 'ether')) * 1000000) / 1000000).toFixed(6) + setTimeout(() => this.setState({ copied: false }), 1000) } + render () { const req = this.props.req + const value = BigNumber(req.data.value || '0x', 16) + if (value.isZero()) { + return null + } + const address = req.data.to ? getAddress(req.data.to) : '' const ensName = (req.recipient && req.recipient.length < 25) ? req.recipient : '' const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') - const {nativeCurrency, nativeCurrency:{symbol: currentSymbol = '?'}} = this.store('main.networksMeta', this.props.chain.type, this.props.chain.id) - const etherUSD = nativeCurrency && nativeCurrency.usd && !isTestnet ? nativeCurrency.usd.price : 0 - const value = req.data.value || '0x' - const displayValue = this.hexToDisplayValue(value) + const { nativeCurrency, nativeCurrency: { symbol: currentSymbol = '?' }} = this.store('main.networksMeta', this.props.chain.type, this.props.chain.id) const chainName = this.store('main.networks.ethereum', this.props.chain.id, 'name') - if (value === '0x' || parseInt(value, 16) === 0) return null + const { displayEther: displayValue } = toEther(value) + const { displayUSD } = toUSD(value, nativeCurrency, isTestnet) + return (
@@ -49,8 +53,7 @@ class TxSending extends React.Component { {'≈'} - {'$'} - {(displayValue * etherUSD).toFixed(2)} + {displayUSD} diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/style/index.styl b/app/App/Account/Account/Requests/TransactionRequest/TxMain/style/index.styl index f29a30199..2ce3d9d1e 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/style/index.styl +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/style/index.styl @@ -123,9 +123,6 @@ font-size 15px margin-left 4px - ._txMainTransferringEqSymbol - font-size 12px - ._txMainTransferringEqAmount font-size 14px diff --git a/resources/domain/transaction/index.ts b/resources/domain/transaction/index.ts index 29777f9c6..f8b30459c 100644 --- a/resources/domain/transaction/index.ts +++ b/resources/domain/transaction/index.ts @@ -1,3 +1,4 @@ +import BigNumber from 'bignumber.js' import { JsonTx } from '@ethereumjs/tx' import { getAddress as getChecksumAddress } from '@ethersproject/address' @@ -16,6 +17,25 @@ export interface TransactionData extends Omit { gasFeesSource: GasFeesSource, } +export function toUSD (bn: BigNumber, nativeCurrency: Rate, isTestnet = false) { + const nativeUSD = nativeCurrency && nativeCurrency.usd && !isTestnet ? nativeCurrency.usd.price : 0 + const usd = bn.shiftedBy(-18).multipliedBy(nativeUSD).decimalPlaces(2, BigNumber.ROUND_FLOOR) + + return { + usd, + displayUSD: usd.isZero() ? '< $0.01' : `$${usd.toFormat()}` + } +} + +export function toEther (bn: BigNumber, decimalPlaces = 18) { + const ether = bn.shiftedBy(-18).decimalPlaces(decimalPlaces, BigNumber.ROUND_FLOOR) + + return { + ether, + displayEther: ether.isZero() ? '< 0.000001' : ether.toFormat() + } +} + export function typeSupportsBaseFee (type: string) { return parseInt(type || '0') === 2 } From c56e4167853f1462347d5cb13e9142386f63dd7e Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 2 Nov 2022 21:42:09 +0000 Subject: [PATCH 02/50] update formatting for dp --- resources/domain/transaction/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/domain/transaction/index.ts b/resources/domain/transaction/index.ts index f8b30459c..ea49f340d 100644 --- a/resources/domain/transaction/index.ts +++ b/resources/domain/transaction/index.ts @@ -32,7 +32,7 @@ export function toEther (bn: BigNumber, decimalPlaces = 18) { return { ether, - displayEther: ether.isZero() ? '< 0.000001' : ether.toFormat() + displayEther: decimalPlaces < 18 && ether.isZero() ? `< ${BigNumber(`1e-${decimalPlaces}`).toFormat()}` : ether.toFormat() } } From ed136dc5101c27dc8429da032b4c928466830bf6 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 2 Nov 2022 22:19:10 +0000 Subject: [PATCH 03/50] logic tweaks --- resources/domain/transaction/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/domain/transaction/index.ts b/resources/domain/transaction/index.ts index ea49f340d..190d59e0a 100644 --- a/resources/domain/transaction/index.ts +++ b/resources/domain/transaction/index.ts @@ -17,8 +17,8 @@ export interface TransactionData extends Omit { gasFeesSource: GasFeesSource, } -export function toUSD (bn: BigNumber, nativeCurrency: Rate, isTestnet = false) { - const nativeUSD = nativeCurrency && nativeCurrency.usd && !isTestnet ? nativeCurrency.usd.price : 0 +export function toUSD (bn: BigNumber, currencyRate: Rate, isTestnet = false) { + const nativeUSD = BigNumber(isTestnet ? 0 : currencyRate.usd.price) const usd = bn.shiftedBy(-18).multipliedBy(nativeUSD).decimalPlaces(2, BigNumber.ROUND_FLOOR) return { From 5a1004e541f8b244b1b0fc84d7f55786a960dab3 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Thu, 3 Nov 2022 12:17:29 +0000 Subject: [PATCH 04/50] fix test --- .../Requests/TransactionRequest/TxFeeNew/index.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js b/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js index 9f57eacb5..86fa6da2f 100644 --- a/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js +++ b/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js @@ -51,14 +51,14 @@ describe('gas display', () => { expect(baseFeeInput.textContent).toBe('12.369Gwei') }) - it('renders a total gas price of less than 1 million wei', () => { + it('renders a total gas price of less than 1 thousand wei', () => { req.data.type = '0x0' - req.data.gasPrice = addHexPrefix(945e3.toString(16)) + req.data.gasPrice = addHexPrefix((945).toString(16)) const { getByTestId } = setupComponent() const baseFeeInput = getByTestId('gas-display') - expect(baseFeeInput.textContent).toBe('945,000Wei') + expect(baseFeeInput.textContent).toBe('945Wei') }) }) From cce7911bb7652ca2e93c7079eed9348e72c8f2e7 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 4 Nov 2022 13:41:52 +0000 Subject: [PATCH 05/50] extract to DisplayValue class --- .../TransactionRequest/TxAction/index.js | 28 ++++-------- .../TransactionRequest/TxFeeNew/index.js | 32 +++++--------- .../TransactionRequest/TxMain/index.js | 11 +++-- .../TransactionRequest/TxMainNew/overview.js | 5 ++- resources/domain/transaction/displayValue.ts | 43 +++++++++++++++++++ resources/domain/transaction/index.ts | 20 --------- 6 files changed, 70 insertions(+), 69 deletions(-) create mode 100644 resources/domain/transaction/displayValue.ts diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js index 35f898d67..6c31e4883 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js @@ -1,14 +1,11 @@ -import React, { Children } from 'react' +import React from 'react' import Restore from 'react-restore' +import utils from 'web3-utils' + import svg from '../../../../../../../resources/svg' import link from '../../../../../../../resources/link' -import utils from 'web3-utils' -import BigNumber from 'bignumber.js' -import Transfer from './erc20/transfer' -import Recipient from './recipient' -import Destination from './destination' -import Register from './ens/register' import { ClusterBox, Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' +import { DisplayValue } from '../../../../../../../resources/domain/transaction/displayValue' class TxSending extends React.Component { constructor (...args) { @@ -39,21 +36,13 @@ class TxSending extends React.Component { const { amount, decimals, name, recipient: recipientAddress, symbol, recipientType, recipientEns } = action.data || {} const address = recipientAddress const ensName = recipientEns - const value = new BigNumber(amount) - const displayValue = value.dividedBy('1e' + decimals).toFixed(6) + const value = new DisplayValue(amount) // const ensName = (recipientEns && recipientEns.length < 25) ? recipientEns : '' const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') const rate = this.store('main.rates', contract) - const rateUSD = rate && rate.usd && !isTestnet ? rate.usd.price : 0 - - const destination = recipientType && - const recipient = recipientAddress && - link.send('tray:clipboardData', copied)} - /> + const { displayEther: displayValue } = value.toEther(18, decimals) + const { displayUSD } = value.toUSD(rate, isTestnet) return ( @@ -67,8 +56,7 @@ class TxSending extends React.Component { {'≈'} - {'$'} - {(displayValue * rateUSD).toFixed(2)} + {displayUSD} {address && recipientType === 'contract' ? ( diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index 1fe39712c..c81a34698 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -2,26 +2,16 @@ import React from 'react' import Restore from 'react-restore' import BigNumber from 'bignumber.js' -import { GasFeesSource, toUSD, toEther, usesBaseFee } from '../../../../../../../resources/domain/transaction' +import { GasFeesSource, usesBaseFee } from '../../../../../../../resources/domain/transaction' +import { DisplayValue } from '../../../../../../../resources/domain/transaction/displayValue' import link from '../../../../../../../resources/link' - import { ClusterBox, Cluster, ClusterRow, ClusterColumn, ClusterValue } from '../../../../../../../resources/Components/Cluster' const FEE_WARNING_THRESHOLD_USD = 50 -function toDisplayGwei (bn) { - const gwei = bn.shiftedBy(-9).decimalPlaces(6, BigNumber.ROUND_FLOOR) - - return gwei.isZero() ? '' : gwei.toFormat() -} - -function toDisplayWei (bn) { - return bn.toFormat(0) -} - const GasDisplay = ({ maxFeePerGas }) => { - const gweiDisplayValue = toDisplayGwei(maxFeePerGas) - const displayValue = gweiDisplayValue || toDisplayWei(maxFeePerGas) + const gweiDisplayValue = maxFeePerGas.toGwei() + const displayValue = gweiDisplayValue || maxFeePerGas.toWei() const displayLabel = !!gweiDisplayValue ? 'Gwei' : 'Wei' return ( @@ -33,8 +23,8 @@ const GasDisplay = ({ maxFeePerGas }) => { } const USDEstimateDisplay = ({ minFee, maxFee, nativeCurrency, isTestnet }) => { - const { displayUSD: displayMinFeeUSD } = toUSD(minFee, nativeCurrency, isTestnet) - const { usd: maxFeeUSD, displayUSD: displayMaxFeeUSD } = toUSD(maxFee, nativeCurrency, isTestnet) + const { displayUSD: displayMinFeeUSD } = minFee.toUSD(nativeCurrency, isTestnet) + const { usd: maxFeeUSD, displayUSD: displayMaxFeeUSD } = maxFee.toUSD(nativeCurrency, isTestnet) const displayMaxFeeWarning = maxFeeUSD > FEE_WARNING_THRESHOLD_USD return
@@ -68,9 +58,9 @@ class TxFee extends React.Component { const { nativeCurrency } = this.store('main.networksMeta', chain.type, chain.id) const maxGas = BigNumber(req.data.gasLimit, 16) - const maxFeePerGas = BigNumber(req.data[usesBaseFee(req.data) ? 'maxFeePerGas' : 'gasPrice'], 16) - const maxFee = maxFeePerGas.multipliedBy(maxGas) - const { displayEther } = toEther(maxFee, 6) + const maxFeePerGas = BigNumber(req.data[usesBaseFee(req.data) ? 'maxFeePerGas' : 'gasPrice']) + const maxFee = new DisplayValue(maxFeePerGas.multipliedBy(maxGas)) + const { displayEther } = maxFee.toEther(6) // accounts for two potential 12.5% block fee increases const reduceFactor = BigNumber(9).dividedBy(8) @@ -78,7 +68,7 @@ class TxFee extends React.Component { // accounts for the 50% padding in the gas estimate in the provider const minGas = maxGas.dividedBy(BigNumber(1.5)) - const minFee = minFeePerGas.multipliedBy(minGas) + const minFee = new DisplayValue(minFeePerGas.multipliedBy(minGas)) return ( @@ -88,7 +78,7 @@ class TxFee extends React.Component { { link.send('nav:update', 'panel', { data: { step: 'adjustFee' } }) }}> - + diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js index bf0972623..27659e937 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js @@ -1,12 +1,11 @@ import React from 'react' import Restore from 'react-restore' -import BigNumber from 'bignumber.js' -import { getAddress } from '@ethersproject/address' import link from '../../../../../../../resources/link' import svg from '../../../../../../../resources/svg' import { Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' -import { toEther, toUSD } from '../../../../../../../resources/domain/transaction' +import { getAddress } from '../../../../../../../resources/domain/transaction' +import { DisplayValue } from '../../../../../../../resources/domain/transaction/displayValue' class TxSending extends React.Component { constructor (...args) { @@ -24,7 +23,7 @@ class TxSending extends React.Component { render () { const req = this.props.req - const value = BigNumber(req.data.value || '0x', 16) + const value = new DisplayValue(req.data.value || '0x') if (value.isZero()) { return null } @@ -34,8 +33,8 @@ class TxSending extends React.Component { const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') const { nativeCurrency, nativeCurrency: { symbol: currentSymbol = '?' }} = this.store('main.networksMeta', this.props.chain.type, this.props.chain.id) const chainName = this.store('main.networks.ethereum', this.props.chain.id, 'name') - const { displayEther: displayValue } = toEther(value) - const { displayUSD } = toUSD(value, nativeCurrency, isTestnet) + const { displayEther: displayValue } = value.toEther() + const { displayUSD } = value.toUSD(nativeCurrency, isTestnet) return (
diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js index ce902549f..056ac1482 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js @@ -1,8 +1,8 @@ import React from 'react' -import { utils } from 'ethers' import link from '../../../../../../../resources/link' import EnsOverview from '../../Ens' +import { DisplayValue } from '../../../../../../../resources/domain/transaction/displayValue' const isNonZeroHex = (hex) => !!hex && !['0x', '0x0'].includes(hex) @@ -32,7 +32,8 @@ const TxDescription = ({ chain, children, chainColor }) => ( ) const SendOverview = ({ amountHex, decimals, symbol }) => { - const displayAmount = utils.formatUnits(amountHex, decimals) + const display = new DisplayValue(amountHex) + const { displayEther: displayAmount } = display.toEther(18, decimals) return (
{`Send ${displayAmount} ${symbol}`}
diff --git a/resources/domain/transaction/displayValue.ts b/resources/domain/transaction/displayValue.ts new file mode 100644 index 000000000..8d0558317 --- /dev/null +++ b/resources/domain/transaction/displayValue.ts @@ -0,0 +1,43 @@ +import BigNumber from 'bignumber.js' +import { isHexString } from 'ethers/lib/utils' + +export class DisplayValue { + public bn: BigNumber + + constructor(value: string | number | BigNumber) { + this.bn = BigNumber(value, isHexString(value) ? 16 : undefined) + } + + isZero () { + return this.bn.isZero() + } + + toUSD (currencyRate: Rate, isTestnet = false) { + const nativeUSD = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate.usd.price) + const usd = this.bn.shiftedBy(-18).multipliedBy(nativeUSD).decimalPlaces(2, BigNumber.ROUND_FLOOR) + + return { + usd, + displayUSD: usd.isZero() ? '< $0.01' : `$${usd.toFormat()}` + } + } + + toEther (decimalPlaces = 18, formatDP = undefined) { + const ether = this.bn.shiftedBy(-18).decimalPlaces(decimalPlaces, BigNumber.ROUND_FLOOR) + + return { + ether, + displayEther: decimalPlaces < 18 && ether.isZero() ? `< ${BigNumber(`1e-${decimalPlaces}`).toFormat(formatDP)}` : ether.toFormat(formatDP) + } + } + + toGwei (decimalPlaces = 6) { + const gwei = this.bn.shiftedBy(-9).decimalPlaces(decimalPlaces, BigNumber.ROUND_FLOOR) + + return gwei.isZero() ? '' : gwei.toFormat() + } + + toWei () { + return this.bn.toFormat(0) + } +} \ No newline at end of file diff --git a/resources/domain/transaction/index.ts b/resources/domain/transaction/index.ts index 190d59e0a..29777f9c6 100644 --- a/resources/domain/transaction/index.ts +++ b/resources/domain/transaction/index.ts @@ -1,4 +1,3 @@ -import BigNumber from 'bignumber.js' import { JsonTx } from '@ethereumjs/tx' import { getAddress as getChecksumAddress } from '@ethersproject/address' @@ -17,25 +16,6 @@ export interface TransactionData extends Omit { gasFeesSource: GasFeesSource, } -export function toUSD (bn: BigNumber, currencyRate: Rate, isTestnet = false) { - const nativeUSD = BigNumber(isTestnet ? 0 : currencyRate.usd.price) - const usd = bn.shiftedBy(-18).multipliedBy(nativeUSD).decimalPlaces(2, BigNumber.ROUND_FLOOR) - - return { - usd, - displayUSD: usd.isZero() ? '< $0.01' : `$${usd.toFormat()}` - } -} - -export function toEther (bn: BigNumber, decimalPlaces = 18) { - const ether = bn.shiftedBy(-18).decimalPlaces(decimalPlaces, BigNumber.ROUND_FLOOR) - - return { - ether, - displayEther: decimalPlaces < 18 && ether.isZero() ? `< ${BigNumber(`1e-${decimalPlaces}`).toFormat()}` : ether.toFormat() - } -} - export function typeSupportsBaseFee (type: string) { return parseInt(type || '0') === 2 } From bc72b5d76b7147a83b5091bb25318f9128741f84 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 4 Nov 2022 14:01:43 +0000 Subject: [PATCH 06/50] revert formatDP --- .../Account/Requests/TransactionRequest/TxAction/index.js | 2 +- .../Account/Requests/TransactionRequest/TxMainNew/overview.js | 2 +- resources/domain/transaction/displayValue.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js index 6c31e4883..32bac732e 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js @@ -41,7 +41,7 @@ class TxSending extends React.Component { const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') const rate = this.store('main.rates', contract) - const { displayEther: displayValue } = value.toEther(18, decimals) + const { displayEther: displayValue } = value.toEther() const { displayUSD } = value.toUSD(rate, isTestnet) return ( diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js index 056ac1482..9c5b144ca 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js @@ -33,7 +33,7 @@ const TxDescription = ({ chain, children, chainColor }) => ( const SendOverview = ({ amountHex, decimals, symbol }) => { const display = new DisplayValue(amountHex) - const { displayEther: displayAmount } = display.toEther(18, decimals) + const { displayEther: displayAmount } = display.toEther() return (
{`Send ${displayAmount} ${symbol}`}
diff --git a/resources/domain/transaction/displayValue.ts b/resources/domain/transaction/displayValue.ts index 8d0558317..1df89b78d 100644 --- a/resources/domain/transaction/displayValue.ts +++ b/resources/domain/transaction/displayValue.ts @@ -22,12 +22,12 @@ export class DisplayValue { } } - toEther (decimalPlaces = 18, formatDP = undefined) { + toEther (decimalPlaces = 18) { const ether = this.bn.shiftedBy(-18).decimalPlaces(decimalPlaces, BigNumber.ROUND_FLOOR) return { ether, - displayEther: decimalPlaces < 18 && ether.isZero() ? `< ${BigNumber(`1e-${decimalPlaces}`).toFormat(formatDP)}` : ether.toFormat(formatDP) + displayEther: decimalPlaces < 18 && ether.isZero() ? `< ${BigNumber(`1e-${decimalPlaces}`).toFormat()}` : ether.toFormat() } } From 50df29dfff18d2ebee6512a68679754ef8083d6c Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 4 Nov 2022 14:03:45 +0000 Subject: [PATCH 07/50] add new line --- resources/domain/transaction/displayValue.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/domain/transaction/displayValue.ts b/resources/domain/transaction/displayValue.ts index 1df89b78d..8c9e499ce 100644 --- a/resources/domain/transaction/displayValue.ts +++ b/resources/domain/transaction/displayValue.ts @@ -40,4 +40,4 @@ export class DisplayValue { toWei () { return this.bn.toFormat(0) } -} \ No newline at end of file +} From a7073a1af2ce3b7a6869366396c4729af978ff18 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 4 Nov 2022 15:09:49 +0000 Subject: [PATCH 08/50] fix erc20 issue --- .../Account/Requests/TransactionRequest/TxAction/index.js | 2 +- .../Account/Requests/TransactionRequest/TxFeeNew/index.js | 2 +- .../Account/Requests/TransactionRequest/TxMainNew/overview.js | 2 +- resources/domain/transaction/displayValue.ts | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js index 32bac732e..8e7b35c0a 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js @@ -41,7 +41,7 @@ class TxSending extends React.Component { const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') const rate = this.store('main.rates', contract) - const { displayEther: displayValue } = value.toEther() + const { displayEther: displayValue } = value.toEther(decimals) const { displayUSD } = value.toUSD(rate, isTestnet) return ( diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index c81a34698..d7ce62bc6 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -60,7 +60,7 @@ class TxFee extends React.Component { const maxGas = BigNumber(req.data.gasLimit, 16) const maxFeePerGas = BigNumber(req.data[usesBaseFee(req.data) ? 'maxFeePerGas' : 'gasPrice']) const maxFee = new DisplayValue(maxFeePerGas.multipliedBy(maxGas)) - const { displayEther } = maxFee.toEther(6) + const { displayEther } = maxFee.toEther(6, -18) // accounts for two potential 12.5% block fee increases const reduceFactor = BigNumber(9).dividedBy(8) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js index 9c5b144ca..bb0a5a9ed 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js @@ -33,7 +33,7 @@ const TxDescription = ({ chain, children, chainColor }) => ( const SendOverview = ({ amountHex, decimals, symbol }) => { const display = new DisplayValue(amountHex) - const { displayEther: displayAmount } = display.toEther() + const { displayEther: displayAmount } = display.toEther(decimals) return (
{`Send ${displayAmount} ${symbol}`}
diff --git a/resources/domain/transaction/displayValue.ts b/resources/domain/transaction/displayValue.ts index 8c9e499ce..6314324ff 100644 --- a/resources/domain/transaction/displayValue.ts +++ b/resources/domain/transaction/displayValue.ts @@ -22,8 +22,8 @@ export class DisplayValue { } } - toEther (decimalPlaces = 18) { - const ether = this.bn.shiftedBy(-18).decimalPlaces(decimalPlaces, BigNumber.ROUND_FLOOR) + toEther (decimalPlaces = 18, shiftedBy?: number) { + const ether = this.bn.shiftedBy(shiftedBy !== undefined ? shiftedBy : -decimalPlaces).decimalPlaces(decimalPlaces, BigNumber.ROUND_FLOOR) return { ether, From e73fa4b03217c57893c9f8505ac096ac297f238c Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 4 Nov 2022 15:18:16 +0000 Subject: [PATCH 09/50] use bn directly for isZero --- .../Account/Requests/TransactionRequest/TxMain/index.js | 2 +- resources/domain/transaction/displayValue.ts | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js index 27659e937..107660dc2 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js @@ -24,7 +24,7 @@ class TxSending extends React.Component { render () { const req = this.props.req const value = new DisplayValue(req.data.value || '0x') - if (value.isZero()) { + if (value.bn.isZero()) { return null } diff --git a/resources/domain/transaction/displayValue.ts b/resources/domain/transaction/displayValue.ts index 6314324ff..4661e91f5 100644 --- a/resources/domain/transaction/displayValue.ts +++ b/resources/domain/transaction/displayValue.ts @@ -7,10 +7,6 @@ export class DisplayValue { constructor(value: string | number | BigNumber) { this.bn = BigNumber(value, isHexString(value) ? 16 : undefined) } - - isZero () { - return this.bn.isZero() - } toUSD (currencyRate: Rate, isTestnet = false) { const nativeUSD = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate.usd.price) From 73aac0c44f2c510b125674efed424647c452174f Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 4 Nov 2022 15:56:15 +0000 Subject: [PATCH 10/50] separate symbol from USD display value --- .../Account/Requests/TransactionRequest/TxAction/index.js | 1 + .../Account/Requests/TransactionRequest/TxFeeNew/index.js | 8 ++++---- .../Account/Requests/TransactionRequest/TxMain/index.js | 1 + .../Requests/TransactionRequest/TxMain/style/index.styl | 3 +++ resources/domain/transaction/displayValue.ts | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js index 8e7b35c0a..4cd88d646 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js @@ -56,6 +56,7 @@ class TxSending extends React.Component { {'≈'} + {'$'} {displayUSD} diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index d7ce62bc6..2ba2346c0 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -30,12 +30,12 @@ const USDEstimateDisplay = ({ minFee, maxFee, nativeCurrency, isTestnet }) => { return
{'≈'} - {displayMaxFeeUSD === '< $0.01' ? - {displayMaxFeeUSD} : + {displayMaxFeeUSD === '< 0.01' ? + {`$${displayMaxFeeUSD}`} : <> - {displayMinFeeUSD} + {`$${displayMinFeeUSD}`} {'-'} - {displayMaxFeeUSD} + {`$${displayMaxFeeUSD}`} } {`in ${nativeCurrency.symbol}`} diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js index 107660dc2..5a3d69095 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js @@ -52,6 +52,7 @@ class TxSending extends React.Component { {'≈'} + {'$'} {displayUSD} diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/style/index.styl b/app/App/Account/Account/Requests/TransactionRequest/TxMain/style/index.styl index 2ce3d9d1e..f29a30199 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/style/index.styl +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/style/index.styl @@ -123,6 +123,9 @@ font-size 15px margin-left 4px + ._txMainTransferringEqSymbol + font-size 12px + ._txMainTransferringEqAmount font-size 14px diff --git a/resources/domain/transaction/displayValue.ts b/resources/domain/transaction/displayValue.ts index 4661e91f5..581d6489d 100644 --- a/resources/domain/transaction/displayValue.ts +++ b/resources/domain/transaction/displayValue.ts @@ -14,7 +14,7 @@ export class DisplayValue { return { usd, - displayUSD: usd.isZero() ? '< $0.01' : `$${usd.toFormat()}` + displayUSD: usd.isZero() ? '< 0.01' : usd.toFormat() } } From d2a57860815e4469e97042bfbf567a412bb8c980 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 4 Nov 2022 17:57:12 +0000 Subject: [PATCH 11/50] fix tests --- .../Requests/TransactionRequest/TxFeeNew/index.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js b/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js index 86fa6da2f..8d610d49e 100644 --- a/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js +++ b/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js @@ -70,7 +70,7 @@ describe('usd estimate display', () => { const { getByTestId } = setupComponent() const baseFeeInput = getByTestId('usd-estimate-display') - expect(baseFeeInput.textContent).toBe('≈< $0.01in MATIC') + expect(baseFeeInput.textContent).toBe('≈$< 0.01in MATIC') }) it('renders an estimate for between less than a cent and one cent', () => { @@ -80,7 +80,7 @@ describe('usd estimate display', () => { const { getByTestId } = setupComponent() const baseFeeInput = getByTestId('usd-estimate-display') - expect(baseFeeInput.textContent).toBe('≈< $0.01-$0.01in MATIC') + expect(baseFeeInput.textContent).toBe('≈$< 0.01-$0.01in MATIC') }) it('renders an estimate for between > $1 values', () => { From 7b7d1cbbd823051bdcb5b9fe090cfd63bfd24791 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 03:48:21 +0000 Subject: [PATCH 12/50] rework --- .../TransactionRequest/TxAction/index.js | 13 +- .../TransactionRequest/TxFeeNew/index.js | 39 +++--- .../TransactionRequest/TxMain/index.js | 14 +- .../TransactionRequest/TxMainNew/overview.js | 7 +- resources/domain/transaction/displayValue.ts | 131 +++++++++++++++--- 5 files changed, 146 insertions(+), 58 deletions(-) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js index 4cd88d646..d7bde84f3 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js @@ -5,7 +5,7 @@ import utils from 'web3-utils' import svg from '../../../../../../../resources/svg' import link from '../../../../../../../resources/link' import { ClusterBox, Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' -import { DisplayValue } from '../../../../../../../resources/domain/transaction/displayValue' +import { displayValueData } from '../../../../../../../resources/domain/transaction/displayValue' class TxSending extends React.Component { constructor (...args) { @@ -36,13 +36,12 @@ class TxSending extends React.Component { const { amount, decimals, name, recipient: recipientAddress, symbol, recipientType, recipientEns } = action.data || {} const address = recipientAddress const ensName = recipientEns - const value = new DisplayValue(amount) + // const ensName = (recipientEns && recipientEns.length < 25) ? recipientEns : '' const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') - const rate = this.store('main.rates', contract) - const { displayEther: displayValue } = value.toEther(decimals) - const { displayUSD } = value.toUSD(rate, isTestnet) + const currencyRate = this.store('main.rates', contract) + const { ether, fiat } = displayValueData(amount, { decimals, currencyRate, currencyName: 'usd', isTestnet }) return ( @@ -51,13 +50,13 @@ class TxSending extends React.Component {
{symbol} - {displayValue} + {`${ether.displayValue}${ether.displayUnit ? ether.displayUnit.shortName : ''}`}
{'≈'} {'$'} - {displayUSD} + {`${fiat.displayValue}${fiat.displayUnit ? fiat.displayUnit.shortName : ''}`} {address && recipientType === 'contract' ? ( diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index 2ba2346c0..37d7259b3 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -3,15 +3,15 @@ import Restore from 'react-restore' import BigNumber from 'bignumber.js' import { GasFeesSource, usesBaseFee } from '../../../../../../../resources/domain/transaction' -import { DisplayValue } from '../../../../../../../resources/domain/transaction/displayValue' +import { displayValueData } from '../../../../../../../resources/domain/transaction/displayValue' import link from '../../../../../../../resources/link' import { ClusterBox, Cluster, ClusterRow, ClusterColumn, ClusterValue } from '../../../../../../../resources/Components/Cluster' const FEE_WARNING_THRESHOLD_USD = 50 const GasDisplay = ({ maxFeePerGas }) => { - const gweiDisplayValue = maxFeePerGas.toGwei() - const displayValue = gweiDisplayValue || maxFeePerGas.toWei() + const gweiDisplayValue = maxFeePerGas.gwei + const displayValue = gweiDisplayValue || maxFeePerGas.wei const displayLabel = !!gweiDisplayValue ? 'Gwei' : 'Wei' return ( @@ -22,20 +22,20 @@ const GasDisplay = ({ maxFeePerGas }) => { ) } -const USDEstimateDisplay = ({ minFee, maxFee, nativeCurrency, isTestnet }) => { - const { displayUSD: displayMinFeeUSD } = minFee.toUSD(nativeCurrency, isTestnet) - const { usd: maxFeeUSD, displayUSD: displayMaxFeeUSD } = maxFee.toUSD(nativeCurrency, isTestnet) - const displayMaxFeeWarning = maxFeeUSD > FEE_WARNING_THRESHOLD_USD +const USDEstimateDisplay = ({ minFee, maxFee, nativeCurrency }) => { + const { fiat: minFeeFiat } = minFee + const { fiat: maxFeeFiat } = maxFee + const displayMaxFeeWarning = maxFeeFiat.value > FEE_WARNING_THRESHOLD_USD return
{'≈'} - {displayMaxFeeUSD === '< 0.01' ? - {`$${displayMaxFeeUSD}`} : + {maxFeeFiat.approximationSymbol === '<' ? + {`$${maxFeeFiat.displayValue}${maxFeeFiat.displayUnit ? maxFeeFiat.displayUnit : ''}`} : <> - {`$${displayMinFeeUSD}`} + {`$${minFeeFiat.displayValue}${minFeeFiat.displayUnit ? minFeeFiat.displayUnit : ''}`} {'-'} - {`$${displayMaxFeeUSD}`} + {`$${maxFeeFiat.displayValue}${maxFeeFiat.displayUnit ? maxFeeFiat.displayUnit : ''}`} } {`in ${nativeCurrency.symbol}`} @@ -59,8 +59,10 @@ class TxFee extends React.Component { const maxGas = BigNumber(req.data.gasLimit, 16) const maxFeePerGas = BigNumber(req.data[usesBaseFee(req.data) ? 'maxFeePerGas' : 'gasPrice']) - const maxFee = new DisplayValue(maxFeePerGas.multipliedBy(maxGas)) - const { displayEther } = maxFee.toEther(6, -18) + const maxFee = displayValueData( + maxFeePerGas.multipliedBy(maxGas), + { decimalsOverride: 6, currencyName: 'usd', currencyRate: nativeCurrency, isTestnet } + ) // accounts for two potential 12.5% block fee increases const reduceFactor = BigNumber(9).dividedBy(8) @@ -68,7 +70,10 @@ class TxFee extends React.Component { // accounts for the 50% padding in the gas estimate in the provider const minGas = maxGas.dividedBy(BigNumber(1.5)) - const minFee = new DisplayValue(minFeePerGas.multipliedBy(minGas)) + const minFee = displayValueData( + minFeePerGas.multipliedBy(minGas), + { currencyName: 'usd', currencyRate: nativeCurrency, isTestnet } + ) return ( @@ -78,18 +83,18 @@ class TxFee extends React.Component { { link.send('nav:update', 'panel', { data: { step: 'adjustFee' } }) }}> - +
{nativeCurrency.symbol} - {displayEther} + {`${maxFee.ether.displayValue}${maxFee.ether.displayUnit ? maxFee.ether.displayUnit.shortName : ''}`}
- +
diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js index 5a3d69095..6ce5b291b 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js @@ -1,11 +1,12 @@ import React from 'react' import Restore from 'react-restore' +import { BigNumber } from 'bignumber.js' import link from '../../../../../../../resources/link' import svg from '../../../../../../../resources/svg' import { Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' import { getAddress } from '../../../../../../../resources/domain/transaction' -import { DisplayValue } from '../../../../../../../resources/domain/transaction/displayValue' +import { displayValueData } from '../../../../../../../resources/domain/transaction/displayValue' class TxSending extends React.Component { constructor (...args) { @@ -23,8 +24,8 @@ class TxSending extends React.Component { render () { const req = this.props.req - const value = new DisplayValue(req.data.value || '0x') - if (value.bn.isZero()) { + const value = req.data.value || '0x' + if (BigNumber(value).isZero()) { return null } @@ -33,8 +34,7 @@ class TxSending extends React.Component { const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') const { nativeCurrency, nativeCurrency: { symbol: currentSymbol = '?' }} = this.store('main.networksMeta', this.props.chain.type, this.props.chain.id) const chainName = this.store('main.networks.ethereum', this.props.chain.id, 'name') - const { displayEther: displayValue } = value.toEther() - const { displayUSD } = value.toUSD(nativeCurrency, isTestnet) + const { ether, fiat } = displayValueData(value, { currencyName: 'usd', currencyRate: nativeCurrency, isTestnet }) return (
@@ -47,13 +47,13 @@ class TxSending extends React.Component {
{currentSymbol} - {displayValue} + {`${ether.displayValue}${ether.displayUnit ? ether.displayUnit : ''}`}
{'≈'} {'$'} - {displayUSD} + `${fiat.displayValue}${fiat.displayUnit ? fiat.displayUnit : ''}` diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js index bb0a5a9ed..af969a57c 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js @@ -2,7 +2,7 @@ import React from 'react' import link from '../../../../../../../resources/link' import EnsOverview from '../../Ens' -import { DisplayValue } from '../../../../../../../resources/domain/transaction/displayValue' +import { displayValueData } from '../../../../../../../resources/domain/transaction/displayValue' const isNonZeroHex = (hex) => !!hex && !['0x', '0x0'].includes(hex) @@ -32,11 +32,10 @@ const TxDescription = ({ chain, children, chainColor }) => ( ) const SendOverview = ({ amountHex, decimals, symbol }) => { - const display = new DisplayValue(amountHex) - const { displayEther: displayAmount } = display.toEther(decimals) + const { ether } = displayValueData(amountHex, { decimals }) return ( -
{`Send ${displayAmount} ${symbol}`}
+
{`Send ${ether.displayValue}${ether.displayUnit ? ether.displayUnit.shortName : ''} ${symbol}`}
) } diff --git a/resources/domain/transaction/displayValue.ts b/resources/domain/transaction/displayValue.ts index 581d6489d..f12e03e21 100644 --- a/resources/domain/transaction/displayValue.ts +++ b/resources/domain/transaction/displayValue.ts @@ -1,39 +1,124 @@ import BigNumber from 'bignumber.js' import { isHexString } from 'ethers/lib/utils' -export class DisplayValue { - public bn: BigNumber +const displayUnitMapping = { + thousand: { + lowerBound: BigNumber(999), + upperBound: BigNumber(999999), + unitDisplay: 'k' + }, + million: { + lowerBound: BigNumber(999999), + upperBound: BigNumber(999999999), + unitDisplay: 'M' + }, + billion: { + lowerBound: BigNumber(999999999), + upperBound: BigNumber(999999999999), + unitDisplay: 'Bn' + }, + trillion: { + lowerBound: BigNumber(999999999999), + upperBound: BigNumber(999999999999999), + unitDisplay: 'Tn' + }, + quadrillion: { + lowerBound: BigNumber(999999999999999), + upperBound: BigNumber(Infinity), + unitDisplay: 'Qn' + } +} - constructor(value: string | number | BigNumber) { - this.bn = BigNumber(value, isHexString(value) ? 16 : undefined) +function getDisplayValue (bn: BigNumber) { + // large numbers + for (const [unitName, { lowerBound, upperBound, unitDisplay }] of Object.entries(displayUnitMapping)) { + if (bn.isGreaterThan(lowerBound) && bn.isLessThan(upperBound)) { + return { + displayValue: bn.shiftedBy(-(lowerBound.sd(true))).sd(3).toFormat(), + displayUnit: { + fullName: unitName, + shortName: unitDisplay + } + } + } } - - toUSD (currencyRate: Rate, isTestnet = false) { - const nativeUSD = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate.usd.price) - const usd = this.bn.shiftedBy(-18).multipliedBy(nativeUSD).decimalPlaces(2, BigNumber.ROUND_FLOOR) - - return { - usd, - displayUSD: usd.isZero() ? '< 0.01' : usd.toFormat() + + // small numbers < 1000 + return { + displayValue: bn.toFormat() + } +} + +type DisplayValueDataParams = { + currencyName?: string, + currencyRate?: Rate, + decimals: number, + decimalsOverride?: number, + isTestnet: boolean +} +type Currency = { + value: BigNumber, + displayValue: string, + approximationSymbol?: string +} + +export function displayValueData (value: string | number | BigNumber, params = {}) { + const { currencyName, currencyRate, decimals = 18, decimalsOverride, isTestnet = false } = params as DisplayValueDataParams + const bn = BigNumber(value, isHexString(value) ? 16 : undefined) + const currency: { [K: string]: Currency } = {} + + if (currencyName) { + const nativeCurrency = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate[currencyName as keyof typeof currencyRate].price) + const value = bn.shiftedBy(-18).multipliedBy(nativeCurrency).decimalPlaces(2, BigNumber.ROUND_FLOOR) + const getFiatCurrency = (): Currency => { + if (isTestnet) { + return { + value, + displayValue: '?' + } + } + if (value.isZero()) { + return { + value, + approximationSymbol: '<', + displayValue: '0.01' + } + } + + return { + value, + ...getDisplayValue(value) + } } + + currency.fiat = getFiatCurrency() } - toEther (decimalPlaces = 18, shiftedBy?: number) { - const ether = this.bn.shiftedBy(shiftedBy !== undefined ? shiftedBy : -decimalPlaces).decimalPlaces(decimalPlaces, BigNumber.ROUND_FLOOR) + const getEtherCurrency = () => { + const value = bn.shiftedBy(-decimals).decimalPlaces(decimalsOverride || decimals, BigNumber.ROUND_FLOOR) + if (decimalsOverride && value.isZero()) { + return { + value, + approximationSymbol: '<', + displayValue: BigNumber(`1e-${decimals}`).toFormat() + } + } + return { - ether, - displayEther: decimalPlaces < 18 && ether.isZero() ? `< ${BigNumber(`1e-${decimalPlaces}`).toFormat()}` : ether.toFormat() + value, + ...getDisplayValue(value) } } - toGwei (decimalPlaces = 6) { - const gwei = this.bn.shiftedBy(-9).decimalPlaces(decimalPlaces, BigNumber.ROUND_FLOOR) - - return gwei.isZero() ? '' : gwei.toFormat() - } + currency.ether = getEtherCurrency() + + const bnGwei = bn.shiftedBy(-9).decimalPlaces(6, BigNumber.ROUND_FLOOR) - toWei () { - return this.bn.toFormat(0) + return { + bn, + ...currency, + gwei: bnGwei.isZero() ? '' : bnGwei.toFormat(), + wei: bn.toFormat(0) } } From 6fe11080795b3ecc8845db1b566ab99dd2ad6636 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 14:20:30 +0000 Subject: [PATCH 13/50] rework tests --- resources/domain/transaction/displayValue.ts | 2 +- .../domain/transaction/displayValue.test.js | 171 ++++++++++++++++++ 2 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 test/resources/domain/transaction/displayValue.test.js diff --git a/resources/domain/transaction/displayValue.ts b/resources/domain/transaction/displayValue.ts index f12e03e21..8d919d8cb 100644 --- a/resources/domain/transaction/displayValue.ts +++ b/resources/domain/transaction/displayValue.ts @@ -101,7 +101,7 @@ export function displayValueData (value: string | number | BigNumber, params = { return { value, approximationSymbol: '<', - displayValue: BigNumber(`1e-${decimals}`).toFormat() + displayValue: BigNumber(`1e-${decimalsOverride}`).toFormat() } } diff --git a/test/resources/domain/transaction/displayValue.test.js b/test/resources/domain/transaction/displayValue.test.js new file mode 100644 index 000000000..848a95a7f --- /dev/null +++ b/test/resources/domain/transaction/displayValue.test.js @@ -0,0 +1,171 @@ +import { BigNumber } from 'bignumber.js' +import { displayValueData } from '../../../../resources/domain/transaction/displayValue' + +describe('wei', () => { + it('should return a wei value', () => { + const displayValue = displayValueData(356) + expect(displayValue.wei).toBe('356') + }) +}) + +describe('gwei', () => { + it('should return a gwei value', () => { + const displayValue = displayValueData(356e9) + expect(displayValue.gwei).toBe('356') + }) + + it('should not return a gwei value of more than 6dp', () => { + const displayValue = displayValueData(356e-18) + expect(displayValue.gwei).toBe('') + }) +}) + +describe('fiat currency', () => { + it('should return zero when no currency rate is provided', () => { + const value = displayValueData(356e24, { currencyName: 'usd' }) + expect(value.fiat).toStrictEqual({ + approximationSymbol: '<', + displayValue: '0.01', + value: BigNumber(0) + }) + }) + + it('should return "testnet zero" when isTestnet is true', () => { + const value = displayValueData(356e24, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1.3) }}, isTestnet: true }) + expect(value.fiat).toStrictEqual({ + displayValue: '?', + value: BigNumber(0) + }) + }) + + it('should return a value of thousands', () => { + const value = displayValueData(356e20, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1) }}}) + expect(value.fiat).toStrictEqual({ + displayUnit: { + fullName: 'thousand', + shortName: 'k', + }, + displayValue: '35.6', + value: BigNumber(35600) + }) + }) + + it('should return a value of millions', () => { + const value = displayValueData(356e23, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1) }}}) + expect(value.fiat).toStrictEqual({ + displayUnit: { + fullName: 'million', + shortName: 'M', + }, + displayValue: '35.6', + value: BigNumber(35600000) + }) + }) + + it('should return a value of billions', () => { + const value = displayValueData(356e26, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1) }}}) + expect(value.fiat).toStrictEqual({ + displayUnit: { + fullName: 'billion', + shortName: 'Bn', + }, + displayValue: '35.6', + value: BigNumber(35600000000) + }) + }) + + it('should return a value of trillions', () => { + const value = displayValueData(356e29, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1) }}}) + expect(value.fiat).toStrictEqual({ + displayUnit: { + fullName: 'trillion', + shortName: 'Tn', + }, + displayValue: '35.6', + value: BigNumber(35600000000000) + }) + }) + + it('should return a value of quadrillions', () => { + const value = displayValueData(356e32, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1) }}}) + expect(value.fiat).toStrictEqual({ + displayUnit: { + fullName: 'quadrillion', + shortName: 'Qn', + }, + displayValue: '35.6', + value: BigNumber(35600000000000000) + }) + }) +}) + +describe('ether currency', () => { + it('should handle values smaller than the number of decimals requested', () => { + const value = displayValueData(356e-8, { decimalsOverride: 6 }) + expect(value.ether).toStrictEqual({ + approximationSymbol: '<', + displayValue: '0.000001', + value: BigNumber(0) + }) + }) + + it('should return a value of thousands', () => { + const value = displayValueData(356e20) + expect(value.ether).toStrictEqual({ + displayUnit: { + fullName: 'thousand', + shortName: 'k', + }, + displayValue: '35.6', + value: BigNumber(35600) + }) + }) + + it('should return a value of millions', () => { + const value = displayValueData(356e23) + expect(value.ether).toStrictEqual({ + displayUnit: { + fullName: 'million', + shortName: 'M', + }, + displayValue: '35.6', + value: BigNumber(35600000) + }) + }) + + it('should return a value of billions', () => { + const value = displayValueData(356e26) + expect(value.ether).toStrictEqual({ + displayUnit: { + fullName: 'billion', + shortName: 'Bn', + }, + displayValue: '35.6', + value: BigNumber(35600000000) + }) + }) + + it('should return a value of trillions', () => { + const value = displayValueData(356e29) + expect(value.ether).toStrictEqual({ + displayUnit: { + fullName: 'trillion', + shortName: 'Tn', + }, + displayValue: '35.6', + value: BigNumber(35600000000000) + }) + }) + + it('should return a value of quadrillions', () => { + const value = displayValueData(356e32) + expect(value.ether).toStrictEqual({ + displayUnit: { + fullName: 'quadrillion', + shortName: 'Qn', + }, + displayValue: '35.6', + value: BigNumber(35600000000000000) + }) + }) +}) \ No newline at end of file From 0b4d9f0508d36e5324d7f940c81dca815bbb267f Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 14:26:44 +0000 Subject: [PATCH 14/50] move to utils --- .../Account/Requests/TransactionRequest/TxAction/index.js | 2 +- .../Account/Requests/TransactionRequest/TxFeeNew/index.js | 2 +- .../Account/Account/Requests/TransactionRequest/TxMain/index.js | 2 +- .../Account/Requests/TransactionRequest/TxMainNew/overview.js | 2 +- resources/{domain/transaction => utils}/displayValue.ts | 0 .../{domain/transaction => utils}/displayValue.test.js | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename resources/{domain/transaction => utils}/displayValue.ts (100%) rename test/resources/{domain/transaction => utils}/displayValue.test.js (98%) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js index f872dc30e..8586ed47e 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js @@ -5,7 +5,7 @@ import utils from 'web3-utils' import svg from '../../../../../../../resources/svg' import link from '../../../../../../../resources/link' import { ClusterBox, Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' -import { displayValueData } from '../../../../../../../resources/domain/transaction/displayValue' +import { displayValueData } from '../../../../../../../resources/utils/displayValue' import { formatDisplayInteger, isUnlimited } from '../../../../../../../resources/utils/numbers' diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index 37d7259b3..7fafb0c49 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -3,7 +3,7 @@ import Restore from 'react-restore' import BigNumber from 'bignumber.js' import { GasFeesSource, usesBaseFee } from '../../../../../../../resources/domain/transaction' -import { displayValueData } from '../../../../../../../resources/domain/transaction/displayValue' +import { displayValueData } from '../../../../../../../resources/utils/displayValue' import link from '../../../../../../../resources/link' import { ClusterBox, Cluster, ClusterRow, ClusterColumn, ClusterValue } from '../../../../../../../resources/Components/Cluster' diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js index 6ce5b291b..b4ebb76ac 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js @@ -6,7 +6,7 @@ import link from '../../../../../../../resources/link' import svg from '../../../../../../../resources/svg' import { Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' import { getAddress } from '../../../../../../../resources/domain/transaction' -import { displayValueData } from '../../../../../../../resources/domain/transaction/displayValue' +import { displayValueData } from '../../../../../../../resources/utils/displayValue' class TxSending extends React.Component { constructor (...args) { diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js index c562b621a..4b9170b66 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js @@ -2,7 +2,7 @@ import React from 'react' import link from '../../../../../../../resources/link' import EnsOverview from '../../Ens' -import { displayValueData } from '../../../../../../../resources/domain/transaction/displayValue' +import { displayValueData } from '../../../../../../../resources/utils/displayValue' import svg from '../../../../../../../resources/svg' diff --git a/resources/domain/transaction/displayValue.ts b/resources/utils/displayValue.ts similarity index 100% rename from resources/domain/transaction/displayValue.ts rename to resources/utils/displayValue.ts diff --git a/test/resources/domain/transaction/displayValue.test.js b/test/resources/utils/displayValue.test.js similarity index 98% rename from test/resources/domain/transaction/displayValue.test.js rename to test/resources/utils/displayValue.test.js index 848a95a7f..8a21dfb90 100644 --- a/test/resources/domain/transaction/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -1,5 +1,5 @@ import { BigNumber } from 'bignumber.js' -import { displayValueData } from '../../../../resources/domain/transaction/displayValue' +import { displayValueData } from '../../../../resources/utils/displayValue' describe('wei', () => { it('should return a wei value', () => { From 8dc11a08c9539406c1b526cafa672fcb17a97559 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 14:47:33 +0000 Subject: [PATCH 15/50] fix broken CI compile? --- resources/utils/displayValue.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index 8d919d8cb..80bd29fac 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -56,14 +56,17 @@ type DisplayValueDataParams = { decimalsOverride?: number, isTestnet: boolean } + type Currency = { value: BigNumber, displayValue: string, approximationSymbol?: string } -export function displayValueData (value: string | number | BigNumber, params = {}) { - const { currencyName, currencyRate, decimals = 18, decimalsOverride, isTestnet = false } = params as DisplayValueDataParams +type SourceValue = string | number | BigNumber + +export function displayValueData (value: SourceValue, params: DisplayValueDataParams) { + const { currencyName, currencyRate, decimals = 18, decimalsOverride, isTestnet = false } = params || {} as DisplayValueDataParams const bn = BigNumber(value, isHexString(value) ? 16 : undefined) const currency: { [K: string]: Currency } = {} From cb024a9afbc23e8071721a7ba7fdc1d68da586d2 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 15:05:08 +0000 Subject: [PATCH 16/50] try --- @types/frame/state.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/@types/frame/state.d.ts b/@types/frame/state.d.ts index 4ba07267e..b226d515c 100644 --- a/@types/frame/state.d.ts +++ b/@types/frame/state.d.ts @@ -110,7 +110,7 @@ interface Balance { } interface Rate { - usd: { + [K: string]: { price: BigNumber, change24hr: BigNumber } From c689772775dc9ef5c354f7b05c189bf7a4f99b1a Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 15:17:39 +0000 Subject: [PATCH 17/50] fixy --- resources/utils/displayValue.ts | 45 +++++++++++------------ test/resources/utils/displayValue.test.js | 16 ++++---- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index 80bd29fac..9a1f7745d 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -50,7 +50,6 @@ function getDisplayValue (bn: BigNumber) { } type DisplayValueDataParams = { - currencyName?: string, currencyRate?: Rate, decimals: number, decimalsOverride?: number, @@ -65,38 +64,38 @@ type Currency = { type SourceValue = string | number | BigNumber -export function displayValueData (value: SourceValue, params: DisplayValueDataParams) { - const { currencyName, currencyRate, decimals = 18, decimalsOverride, isTestnet = false } = params || {} as DisplayValueDataParams - const bn = BigNumber(value, isHexString(value) ? 16 : undefined) +export function displayValueData (sourceValue: SourceValue, params: DisplayValueDataParams) { + const { currencyRate, decimals = 18, decimalsOverride, isTestnet = false } = params || {} as DisplayValueDataParams + const bn = BigNumber(sourceValue, isHexString(sourceValue) ? 16 : undefined) const currency: { [K: string]: Currency } = {} - if (currencyName) { - const nativeCurrency = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate[currencyName as keyof typeof currencyRate].price) + const getFiatCurrency = (): Currency => { + const nativeCurrency = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate.price) const value = bn.shiftedBy(-18).multipliedBy(nativeCurrency).decimalPlaces(2, BigNumber.ROUND_FLOOR) - const getFiatCurrency = (): Currency => { - if (isTestnet) { - return { - value, - displayValue: '?' - } - } - if (value.isZero()) { - return { - value, - approximationSymbol: '<', - displayValue: '0.01' - } - } + if (isTestnet) { return { - value, - ...getDisplayValue(value) + value, + displayValue: '?' } } - currency.fiat = getFiatCurrency() + if (value.isZero()) { + return { + value, + approximationSymbol: '<', + displayValue: '0.01' + } + } + + return { + value, + ...getDisplayValue(value) + } } + currency.fiat = getFiatCurrency() + const getEtherCurrency = () => { const value = bn.shiftedBy(-decimals).decimalPlaces(decimalsOverride || decimals, BigNumber.ROUND_FLOOR) diff --git a/test/resources/utils/displayValue.test.js b/test/resources/utils/displayValue.test.js index 8a21dfb90..f33f5992d 100644 --- a/test/resources/utils/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -1,5 +1,5 @@ import { BigNumber } from 'bignumber.js' -import { displayValueData } from '../../../../resources/utils/displayValue' +import { displayValueData } from '../../../resources/utils/displayValue' describe('wei', () => { it('should return a wei value', () => { @@ -22,7 +22,7 @@ describe('gwei', () => { describe('fiat currency', () => { it('should return zero when no currency rate is provided', () => { - const value = displayValueData(356e24, { currencyName: 'usd' }) + const value = displayValueData(356e24) expect(value.fiat).toStrictEqual({ approximationSymbol: '<', displayValue: '0.01', @@ -31,7 +31,7 @@ describe('fiat currency', () => { }) it('should return "testnet zero" when isTestnet is true', () => { - const value = displayValueData(356e24, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1.3) }}, isTestnet: true }) + const value = displayValueData(356e24, { currencyRate: { price: BigNumber(1.3) }, isTestnet: true }) expect(value.fiat).toStrictEqual({ displayValue: '?', value: BigNumber(0) @@ -39,7 +39,7 @@ describe('fiat currency', () => { }) it('should return a value of thousands', () => { - const value = displayValueData(356e20, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1) }}}) + const value = displayValueData(356e20, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat).toStrictEqual({ displayUnit: { fullName: 'thousand', @@ -51,7 +51,7 @@ describe('fiat currency', () => { }) it('should return a value of millions', () => { - const value = displayValueData(356e23, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1) }}}) + const value = displayValueData(356e23, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat).toStrictEqual({ displayUnit: { fullName: 'million', @@ -63,7 +63,7 @@ describe('fiat currency', () => { }) it('should return a value of billions', () => { - const value = displayValueData(356e26, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1) }}}) + const value = displayValueData(356e26, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat).toStrictEqual({ displayUnit: { fullName: 'billion', @@ -75,7 +75,7 @@ describe('fiat currency', () => { }) it('should return a value of trillions', () => { - const value = displayValueData(356e29, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1) }}}) + const value = displayValueData(356e29, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat).toStrictEqual({ displayUnit: { fullName: 'trillion', @@ -87,7 +87,7 @@ describe('fiat currency', () => { }) it('should return a value of quadrillions', () => { - const value = displayValueData(356e32, { currencyName: 'usd', currencyRate: { usd: { price: BigNumber(1) }}}) + const value = displayValueData(356e32, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat).toStrictEqual({ displayUnit: { fullName: 'quadrillion', From e9ef9054e95dec8c346a9a91b67bf02c9f6c8262 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 16:54:38 +0000 Subject: [PATCH 18/50] new component, use in USD Estimate --- .../TransactionRequest/TxFeeNew/index.js | 24 +++++++++---------- resources/Components/DisplayValue/index.js | 16 +++++++++++++ 2 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 resources/Components/DisplayValue/index.js diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index 7fafb0c49..3cc822c03 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -2,6 +2,7 @@ import React from 'react' import Restore from 'react-restore' import BigNumber from 'bignumber.js' +import { DisplayValue } from '../../../../../../../resources/Components/DisplayValue' import { GasFeesSource, usesBaseFee } from '../../../../../../../resources/domain/transaction' import { displayValueData } from '../../../../../../../resources/utils/displayValue' import link from '../../../../../../../resources/link' @@ -23,20 +24,19 @@ const GasDisplay = ({ maxFeePerGas }) => { } const USDEstimateDisplay = ({ minFee, maxFee, nativeCurrency }) => { - const { fiat: minFeeFiat } = minFee - const { fiat: maxFeeFiat } = maxFee - const displayMaxFeeWarning = maxFeeFiat.value > FEE_WARNING_THRESHOLD_USD + const { fiat: { value: maxFeeValue, approximationSymbol: maxFeeApproximation } } = maxFee + const displayMaxFeeWarning = maxFeeValue > FEE_WARNING_THRESHOLD_USD return
{'≈'} - {maxFeeFiat.approximationSymbol === '<' ? - {`$${maxFeeFiat.displayValue}${maxFeeFiat.displayUnit ? maxFeeFiat.displayUnit : ''}`} : - <> - {`$${minFeeFiat.displayValue}${minFeeFiat.displayUnit ? minFeeFiat.displayUnit : ''}`} - {'-'} - {`$${maxFeeFiat.displayValue}${maxFeeFiat.displayUnit ? maxFeeFiat.displayUnit : ''}`} - + {maxFeeApproximation === '<' ? + : + <> + + {'-'} + + } {`in ${nativeCurrency.symbol}`}
@@ -61,7 +61,7 @@ class TxFee extends React.Component { const maxFeePerGas = BigNumber(req.data[usesBaseFee(req.data) ? 'maxFeePerGas' : 'gasPrice']) const maxFee = displayValueData( maxFeePerGas.multipliedBy(maxGas), - { decimalsOverride: 6, currencyName: 'usd', currencyRate: nativeCurrency, isTestnet } + { decimalsOverride: 6, currencyRate: nativeCurrency, isTestnet } ) // accounts for two potential 12.5% block fee increases @@ -72,7 +72,7 @@ class TxFee extends React.Component { const minGas = maxGas.dividedBy(BigNumber(1.5)) const minFee = displayValueData( minFeePerGas.multipliedBy(minGas), - { currencyName: 'usd', currencyRate: nativeCurrency, isTestnet } + { currencyRate: nativeCurrency, isTestnet } ) return ( diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js new file mode 100644 index 000000000..314f3f4c2 --- /dev/null +++ b/resources/Components/DisplayValue/index.js @@ -0,0 +1,16 @@ +import React from 'react' +import { displayValueData } from '../../utils/displayValue' + +export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol, type = 'ether', currencySymbolPosition = 'first' }) => { + const data = valueData || displayValueData(value, valueDataParams) + const { approximationSymbol = '', displayValue, displayUnit } = data[type] + const CurrencySymbol = () => {currencySymbol} + + return
+ {approximationSymbol} + {currencySymbolPosition === 'first' && } + {displayValue} + {displayUnit ? displayUnit.shortName : ''} + {currencySymbolPosition === 'last' && } +
+} From 0d0e31a83fe0ff0f0dd97a9b1c02b568d1e73d72 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 16:55:02 +0000 Subject: [PATCH 19/50] fix data invocation --- .../Account/Requests/TransactionRequest/TxAction/index.js | 2 +- .../Account/Account/Requests/TransactionRequest/TxMain/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js index 8586ed47e..12994b08d 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js @@ -43,7 +43,7 @@ class TxSending extends React.Component { const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') const currencyRate = this.store('main.rates', contract) - const { ether, fiat } = displayValueData(amount, { decimals, currencyRate, currencyName: 'usd', isTestnet }) + const { ether, fiat } = displayValueData(amount, { decimals, currencyRate, isTestnet }) return ( diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js index b4ebb76ac..f49b1635a 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js @@ -34,7 +34,7 @@ class TxSending extends React.Component { const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') const { nativeCurrency, nativeCurrency: { symbol: currentSymbol = '?' }} = this.store('main.networksMeta', this.props.chain.type, this.props.chain.id) const chainName = this.store('main.networks.ethereum', this.props.chain.id, 'name') - const { ether, fiat } = displayValueData(value, { currencyName: 'usd', currencyRate: nativeCurrency, isTestnet }) + const { ether, fiat } = displayValueData(value, { currencyRate: nativeCurrency, isTestnet }) return (
From 05f771d841c6ca453630f5ecdb7c295c33bcafdc Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 16:55:10 +0000 Subject: [PATCH 20/50] fix tests --- .../Requests/TransactionRequest/TxFeeNew/index.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js b/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js index 6ef239058..39013c9ce 100644 --- a/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js +++ b/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js @@ -14,7 +14,7 @@ const TxFee = Restore.connect(TxFeeComponent, store) let req beforeEach(() => { - store.setNativeCurrencyData('ethereum', 137, { symbol:"MATIC", usd: { price: 0.86 } }) + store.setNativeCurrencyData('ethereum', 137, { symbol: 'MATIC', price: 0.86 }) req = { feesUpdatedByUser: false, @@ -80,7 +80,7 @@ describe('usd estimate display', () => { const { getByTestId } = setupComponent() const baseFeeInput = getByTestId('usd-estimate-display') - expect(baseFeeInput.textContent).toBe('≈$< 0.01in MATIC') + expect(baseFeeInput.textContent).toBe('≈<$0.01in MATIC') }) it('renders an estimate for between less than a cent and one cent', () => { @@ -90,7 +90,7 @@ describe('usd estimate display', () => { const { getByTestId } = setupComponent() const baseFeeInput = getByTestId('usd-estimate-display') - expect(baseFeeInput.textContent).toBe('≈$< 0.01-$0.01in MATIC') + expect(baseFeeInput.textContent).toBe('≈<$0.01-$0.01in MATIC') }) it('renders an estimate for between > $1 values', () => { From 9dea189fa144a3c85964a2d2f5c182060d10ce84 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 17:12:50 +0000 Subject: [PATCH 21/50] update existing tx usage with component --- .../Requests/TransactionRequest/TxAction/index.js | 9 +++------ .../Requests/TransactionRequest/TxFeeNew/index.js | 3 +-- .../Requests/TransactionRequest/TxMain/index.js | 9 +++------ .../Requests/TransactionRequest/TxMainNew/overview.js | 11 ++++++----- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js index 12994b08d..1d0428665 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js @@ -5,9 +5,9 @@ import utils from 'web3-utils' import svg from '../../../../../../../resources/svg' import link from '../../../../../../../resources/link' import { ClusterBox, Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' -import { displayValueData } from '../../../../../../../resources/utils/displayValue' import { formatDisplayInteger, isUnlimited } from '../../../../../../../resources/utils/numbers' +import { DisplayValue } from '../../../../../../../resources/Components/DisplayValue' class TxSending extends React.Component { constructor (...args) { @@ -43,7 +43,6 @@ class TxSending extends React.Component { const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') const currencyRate = this.store('main.rates', contract) - const { ether, fiat } = displayValueData(amount, { decimals, currencyRate, isTestnet }) return ( @@ -51,14 +50,12 @@ class TxSending extends React.Component {
- {symbol} - {`${ether.displayValue}${ether.displayUnit ? ether.displayUnit.shortName : ''}`} +
{'≈'} - {'$'} - {`${fiat.displayValue}${fiat.displayUnit ? fiat.displayUnit.shortName : ''}`} +
{address && recipientType === 'contract' ? ( diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index 3cc822c03..8f7e8ebb0 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -89,8 +89,7 @@ class TxFee extends React.Component {
- {nativeCurrency.symbol} - {`${maxFee.ether.displayValue}${maxFee.ether.displayUnit ? maxFee.ether.displayUnit.shortName : ''}`} +
diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js index f49b1635a..f09e7b5d8 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js @@ -6,7 +6,7 @@ import link from '../../../../../../../resources/link' import svg from '../../../../../../../resources/svg' import { Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' import { getAddress } from '../../../../../../../resources/domain/transaction' -import { displayValueData } from '../../../../../../../resources/utils/displayValue' +import { DisplayValue } from '../../../../../../../resources/Components/DisplayValue' class TxSending extends React.Component { constructor (...args) { @@ -34,7 +34,6 @@ class TxSending extends React.Component { const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') const { nativeCurrency, nativeCurrency: { symbol: currentSymbol = '?' }} = this.store('main.networksMeta', this.props.chain.type, this.props.chain.id) const chainName = this.store('main.networks.ethereum', this.props.chain.id, 'name') - const { ether, fiat } = displayValueData(value, { currencyRate: nativeCurrency, isTestnet }) return (
@@ -46,14 +45,12 @@ class TxSending extends React.Component {
- {currentSymbol} - {`${ether.displayValue}${ether.displayUnit ? ether.displayUnit : ''}`} +
{'≈'} - {'$'} - `${fiat.displayValue}${fiat.displayUnit ? fiat.displayUnit : ''}` +
diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js index 8edec2b47..95e26d952 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMainNew/overview.js @@ -2,11 +2,11 @@ import React from 'react' import link from '../../../../../../../resources/link' import EnsOverview from '../../Ens' -import { displayValueData } from '../../../../../../../resources/utils/displayValue' import svg from '../../../../../../../resources/svg' -import { ClusterBox, Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' +import { Cluster, ClusterRow, ClusterValue } from '../../../../../../../resources/Components/Cluster' +import { DisplayValue } from '../../../../../../../resources/Components/DisplayValue' const isNonZeroHex = (hex) => !!hex && !['0x', '0x0'].includes(hex) @@ -44,10 +44,11 @@ const TxDescription = ({ chain, children, chainColor }) => ( ) const SendOverview = ({ amountHex, decimals, symbol }) => { - const { ether } = displayValueData(amountHex, { decimals }) - return ( -
{`Send ${ether.displayValue}${ether.displayUnit ? ether.displayUnit.shortName : ''} ${symbol}`}
+
+ {'Send'} + +
) } From a7a8eb4b9ae75bf6d5ba2be332f0e168906b9f92 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 17:17:50 +0000 Subject: [PATCH 22/50] fix parcel error --- resources/domain/balance/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/domain/balance/index.ts b/resources/domain/balance/index.ts index 397fa6606..a16b8bafa 100644 --- a/resources/domain/balance/index.ts +++ b/resources/domain/balance/index.ts @@ -32,8 +32,8 @@ export function formatUsdRate (rate:BigNumber, decimals = 2) { export function createBalance (rawBalance: Balance, quote?: Rate): DisplayedBalance { const balance = BigNumber(rawBalance.balance || 0).shiftedBy(-rawBalance.decimals) - const usdRate = new BigNumber(quote?.price || NaN) - const change24hr = new BigNumber(quote?.['change24hr'] || 0) + const usdRate = new BigNumber(quote && quote.price || NaN) + const change24hr = new BigNumber(quote && quote['change24hr'] || 0) const totalValue = balance.times(usdRate) const balanceDecimals = Math.max(2, usdRate.shiftedBy(1).toFixed(0, BigNumber.ROUND_DOWN).length) From d78bc9cac06e0bb1f69742338ad32856d2af7f6d Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 17:21:15 +0000 Subject: [PATCH 23/50] extract CurrencySymbol --- resources/Components/DisplayValue/index.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js index 314f3f4c2..b5e9b6fab 100644 --- a/resources/Components/DisplayValue/index.js +++ b/resources/Components/DisplayValue/index.js @@ -1,16 +1,17 @@ import React from 'react' import { displayValueData } from '../../utils/displayValue' +const CurrencySymbol = ({ symbol }) => {symbol} + export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol, type = 'ether', currencySymbolPosition = 'first' }) => { const data = valueData || displayValueData(value, valueDataParams) const { approximationSymbol = '', displayValue, displayUnit } = data[type] - const CurrencySymbol = () => {currencySymbol} - + return
{approximationSymbol} - {currencySymbolPosition === 'first' && } + {currencySymbolPosition === 'first' && } {displayValue} {displayUnit ? displayUnit.shortName : ''} - {currencySymbolPosition === 'last' && } + {currencySymbolPosition === 'last' && }
} From 3f177b76146b32c14b958052c345cca213ba5714 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 19:50:01 +0000 Subject: [PATCH 24/50] balances using ether display --- .../Account/Account/Balances/Balance/index.js | 6 +++-- .../TransactionRequest/TxAction/index.js | 24 ++++--------------- .../TransactionRequest/TxFeeNew/index.js | 4 ++-- .../TransactionRequest/TxMain/index.js | 2 +- 4 files changed, 11 insertions(+), 25 deletions(-) diff --git a/app/App/Account/Account/Balances/Balance/index.js b/app/App/Account/Account/Balances/Balance/index.js index a8e0e4e35..33b5b702b 100644 --- a/app/App/Account/Account/Balances/Balance/index.js +++ b/app/App/Account/Account/Balances/Balance/index.js @@ -1,6 +1,7 @@ import React from 'react' import Restore from 'react-restore' +import { DisplayValue } from '../../../../../../resources/Components/DisplayValue' import RingIcon from '../../../../../../resources/Components/RingIcon' import svg from '../../../../../../resources/svg' @@ -65,7 +66,7 @@ class Balance extends React.Component { {name}
= 12 ? { fontSize: '15px', top: '10px' } : {}}> - {symbol.toUpperCase()} @@ -74,7 +75,8 @@ class Balance extends React.Component { style={(balance.displayBalance || '0').length >= 12 ? { marginTop: '-3px' } : {}} > {balance.displayBalance} - + */} +
diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js index 1d0428665..0a85c21a7 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxAction/index.js @@ -42,7 +42,7 @@ class TxSending extends React.Component { // const ensName = (recipientEns && recipientEns.length < 25) ? recipientEns : '' const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') - const currencyRate = this.store('main.rates', contract) + const rate = this.store('main.rates', contract) return ( @@ -55,7 +55,7 @@ class TxSending extends React.Component { {'≈'} - + {address && recipientType === 'contract' ? ( @@ -101,26 +101,10 @@ class TxSending extends React.Component { ) } else if (actionType === 'approve') { - const { amount, decimals, name, spender: recipientAddress, symbol, spenderType, spenderEns } = action.data || {} + const { amount, decimals, spender: recipientAddress, symbol, spenderEns } = action.data || {} const address = recipientAddress const ensName = spenderEns - const value = new BigNumber(amount) - const displayValue = value.dividedBy('1e' + decimals).toFixed(6) - // const ensName = (recipientEns && recipientEns.length < 25) ? recipientEns : '' - - const isTestnet = this.store('main.networks', this.props.chain.type, this.props.chain.id, 'isTestnet') - const rate = this.store('main.rates', contract) - const rateUSD = rate && rate.usd && !isTestnet ? rate.usd.price : 0 - - const destination = spenderType && - const recipient = recipientAddress && - link.send('tray:clipboardData', copied)} - /> - - + const value = new BigNumber(amount) const revoke = value.eq(0) const displayAmount = isUnlimited(this.state.amount) ? 'unlimited' : formatDisplayInteger(amount, decimals) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index 8f7e8ebb0..a68ad2e12 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -61,7 +61,7 @@ class TxFee extends React.Component { const maxFeePerGas = BigNumber(req.data[usesBaseFee(req.data) ? 'maxFeePerGas' : 'gasPrice']) const maxFee = displayValueData( maxFeePerGas.multipliedBy(maxGas), - { decimalsOverride: 6, currencyRate: nativeCurrency, isTestnet } + { decimalsOverride: 6, currencyRate: nativeCurrency.usd, isTestnet } ) // accounts for two potential 12.5% block fee increases @@ -72,7 +72,7 @@ class TxFee extends React.Component { const minGas = maxGas.dividedBy(BigNumber(1.5)) const minFee = displayValueData( minFeePerGas.multipliedBy(minGas), - { currencyRate: nativeCurrency, isTestnet } + { currencyRate: nativeCurrency.usd, isTestnet } ) return ( diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js index f09e7b5d8..5d1c3c692 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js @@ -50,7 +50,7 @@ class TxSending extends React.Component { {'≈'} - + From 93d6baccdc68acb32dcb0678f9a42846ef437f0f Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 20:05:10 +0000 Subject: [PATCH 25/50] fix tests --- .../Account/Requests/TransactionRequest/TxFeeNew/index.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js b/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js index 39013c9ce..4c7f6dc1a 100644 --- a/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js +++ b/test/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.test.js @@ -14,7 +14,7 @@ const TxFee = Restore.connect(TxFeeComponent, store) let req beforeEach(() => { - store.setNativeCurrencyData('ethereum', 137, { symbol: 'MATIC', price: 0.86 }) + store.setNativeCurrencyData('ethereum', 137, { usd: { symbol: 'MATIC', price: 0.86 }}) req = { feesUpdatedByUser: false, From b024308006e43c6ff9cc99e50137b62aae3884b0 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Fri, 11 Nov 2022 20:36:26 +0000 Subject: [PATCH 26/50] update shorthand values --- resources/utils/displayValue.ts | 8 ++++---- test/resources/utils/displayValue.test.js | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index 9a1f7745d..fd08bb398 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -5,7 +5,7 @@ const displayUnitMapping = { thousand: { lowerBound: BigNumber(999), upperBound: BigNumber(999999), - unitDisplay: 'k' + unitDisplay: 'K' }, million: { lowerBound: BigNumber(999999), @@ -15,17 +15,17 @@ const displayUnitMapping = { billion: { lowerBound: BigNumber(999999999), upperBound: BigNumber(999999999999), - unitDisplay: 'Bn' + unitDisplay: 'B' }, trillion: { lowerBound: BigNumber(999999999999), upperBound: BigNumber(999999999999999), - unitDisplay: 'Tn' + unitDisplay: 'T' }, quadrillion: { lowerBound: BigNumber(999999999999999), upperBound: BigNumber(Infinity), - unitDisplay: 'Qn' + unitDisplay: 'Q' } } diff --git a/test/resources/utils/displayValue.test.js b/test/resources/utils/displayValue.test.js index f33f5992d..c78a354cf 100644 --- a/test/resources/utils/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -43,7 +43,7 @@ describe('fiat currency', () => { expect(value.fiat).toStrictEqual({ displayUnit: { fullName: 'thousand', - shortName: 'k', + shortName: 'K', }, displayValue: '35.6', value: BigNumber(35600) @@ -67,7 +67,7 @@ describe('fiat currency', () => { expect(value.fiat).toStrictEqual({ displayUnit: { fullName: 'billion', - shortName: 'Bn', + shortName: 'B', }, displayValue: '35.6', value: BigNumber(35600000000) @@ -79,7 +79,7 @@ describe('fiat currency', () => { expect(value.fiat).toStrictEqual({ displayUnit: { fullName: 'trillion', - shortName: 'Tn', + shortName: 'T', }, displayValue: '35.6', value: BigNumber(35600000000000) @@ -91,7 +91,7 @@ describe('fiat currency', () => { expect(value.fiat).toStrictEqual({ displayUnit: { fullName: 'quadrillion', - shortName: 'Qn', + shortName: 'Q', }, displayValue: '35.6', value: BigNumber(35600000000000000) @@ -114,7 +114,7 @@ describe('ether currency', () => { expect(value.ether).toStrictEqual({ displayUnit: { fullName: 'thousand', - shortName: 'k', + shortName: 'K', }, displayValue: '35.6', value: BigNumber(35600) @@ -138,7 +138,7 @@ describe('ether currency', () => { expect(value.ether).toStrictEqual({ displayUnit: { fullName: 'billion', - shortName: 'Bn', + shortName: 'B', }, displayValue: '35.6', value: BigNumber(35600000000) @@ -150,7 +150,7 @@ describe('ether currency', () => { expect(value.ether).toStrictEqual({ displayUnit: { fullName: 'trillion', - shortName: 'Tn', + shortName: 'T', }, displayValue: '35.6', value: BigNumber(35600000000000) @@ -162,7 +162,7 @@ describe('ether currency', () => { expect(value.ether).toStrictEqual({ displayUnit: { fullName: 'quadrillion', - shortName: 'Qn', + shortName: 'Q', }, displayValue: '35.6', value: BigNumber(35600000000000000) From 35bb181303dd8c1cdb45a7b7a2b1115f6f4fd45d Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Mon, 14 Nov 2022 14:28:48 +0000 Subject: [PATCH 27/50] rework displayValueData for functions, fix tests & bugs --- .../Account/Account/Balances/Balance/index.js | 1 + .../TransactionRequest/TxFeeNew/index.js | 9 +- .../TransactionRequest/TxMain/index.js | 2 +- resources/Components/DisplayValue/index.js | 2 +- resources/domain/balance/index.ts | 2 + resources/utils/displayValue.ts | 90 +++++++++---------- test/resources/utils/displayValue.test.js | 32 +++---- 7 files changed, 70 insertions(+), 68 deletions(-) diff --git a/app/App/Account/Account/Balances/Balance/index.js b/app/App/Account/Account/Balances/Balance/index.js index 33b5b702b..48ddb5c95 100644 --- a/app/App/Account/Account/Balances/Balance/index.js +++ b/app/App/Account/Account/Balances/Balance/index.js @@ -90,6 +90,7 @@ class Balance extends React.Component {
{svg.usd(10)}{balance.displayValue}
+
diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index a68ad2e12..4c9a19009 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -11,9 +11,10 @@ import { ClusterBox, Cluster, ClusterRow, ClusterColumn, ClusterValue } from '.. const FEE_WARNING_THRESHOLD_USD = 50 const GasDisplay = ({ maxFeePerGas }) => { - const gweiDisplayValue = maxFeePerGas.gwei - const displayValue = gweiDisplayValue || maxFeePerGas.wei - const displayLabel = !!gweiDisplayValue ? 'Gwei' : 'Wei' + const { displayValue: gweiDisplayValue } = maxFeePerGas.gwei() + const shouldDisplayWei = gweiDisplayValue === '0' + const displayValue = shouldDisplayWei ? maxFeePerGas.wei().displayValue : gweiDisplayValue + const displayLabel = shouldDisplayWei ? 'Wei' : 'Gwei' return (
@@ -24,7 +25,7 @@ const GasDisplay = ({ maxFeePerGas }) => { } const USDEstimateDisplay = ({ minFee, maxFee, nativeCurrency }) => { - const { fiat: { value: maxFeeValue, approximationSymbol: maxFeeApproximation } } = maxFee + const { value: maxFeeValue, approximationSymbol: maxFeeApproximation } = maxFee.fiat() const displayMaxFeeWarning = maxFeeValue > FEE_WARNING_THRESHOLD_USD return
diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js index 5d1c3c692..aa1d46878 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxMain/index.js @@ -50,7 +50,7 @@ class TxSending extends React.Component { {'≈'} - + diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js index b5e9b6fab..e3c8845a3 100644 --- a/resources/Components/DisplayValue/index.js +++ b/resources/Components/DisplayValue/index.js @@ -5,7 +5,7 @@ const CurrencySymbol = ({ symbol }) => {symbol} export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol, type = 'ether', currencySymbolPosition = 'first' }) => { const data = valueData || displayValueData(value, valueDataParams) - const { approximationSymbol = '', displayValue, displayUnit } = data[type] + const { approximationSymbol = '', displayValue, displayUnit } = data[type]() return
{approximationSymbol} diff --git a/resources/domain/balance/index.ts b/resources/domain/balance/index.ts index a16b8bafa..4a0764eeb 100644 --- a/resources/domain/balance/index.ts +++ b/resources/domain/balance/index.ts @@ -5,6 +5,7 @@ interface DisplayedBalance extends Balance { displayBalance: string price: string priceChange: string | false + usdRate: BigNumber totalValue: BigNumber displayValue: string } @@ -40,6 +41,7 @@ export function createBalance (rawBalance: Balance, quote?: Rate): DisplayedBala return { ...rawBalance, + usdRate, displayBalance: formatBalance(balance, totalValue, balanceDecimals), price: formatUsdRate(usdRate), priceChange: !usdRate.isZero() && !usdRate.isNaN() && change24hr.toFixed(2), diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index fd08bb398..9325e406e 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -56,71 +56,69 @@ type DisplayValueDataParams = { isTestnet: boolean } -type Currency = { - value: BigNumber, - displayValue: string, - approximationSymbol?: string -} - type SourceValue = string | number | BigNumber export function displayValueData (sourceValue: SourceValue, params: DisplayValueDataParams) { const { currencyRate, decimals = 18, decimalsOverride, isTestnet = false } = params || {} as DisplayValueDataParams const bn = BigNumber(sourceValue, isHexString(sourceValue) ? 16 : undefined) - const currency: { [K: string]: Currency } = {} + const currencyHelperMap = { + fiat: () => { + const nativeCurrency = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate.price) + const value = bn.shiftedBy(-18).multipliedBy(nativeCurrency).decimalPlaces(2, BigNumber.ROUND_FLOOR) + + if (isTestnet || value.isNaN()) { + return { + value, + displayValue: '?' + } + } - const getFiatCurrency = (): Currency => { - const nativeCurrency = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate.price) - const value = bn.shiftedBy(-18).multipliedBy(nativeCurrency).decimalPlaces(2, BigNumber.ROUND_FLOOR) + if (value.isZero()) { + return { + value, + approximationSymbol: '<', + displayValue: '0.01' + } + } - if (isTestnet) { return { - value, - displayValue: '?' + value, + ...getDisplayValue(value) } - } - - if (value.isZero()) { + }, + ether: () => { + const value = bn.shiftedBy(-decimals).decimalPlaces(decimalsOverride || decimals, BigNumber.ROUND_FLOOR) + + if (decimalsOverride && value.isZero()) { + return { + value, + approximationSymbol: '<', + displayValue: BigNumber(`1e-${decimalsOverride}`).toFormat() + } + } + return { value, - approximationSymbol: '<', - displayValue: '0.01' + ...getDisplayValue(value) } - } - - return { - value, - ...getDisplayValue(value) - } - } - - currency.fiat = getFiatCurrency() + }, + gwei: () => { + const value = bn.shiftedBy(-9).decimalPlaces(6, BigNumber.ROUND_FLOOR) - const getEtherCurrency = () => { - const value = bn.shiftedBy(-decimals).decimalPlaces(decimalsOverride || decimals, BigNumber.ROUND_FLOOR) - - if (decimalsOverride && value.isZero()) { + // return bnGwei.isZero() ? '' : bnGwei.toFormat() return { value, - approximationSymbol: '<', - displayValue: BigNumber(`1e-${decimalsOverride}`).toFormat() + ...getDisplayValue(value) } - } - - return { - value, - ...getDisplayValue(value) - } + }, + wei: () => ({ + value: bn, + displayValue: bn.toFormat(0) + }) } - - currency.ether = getEtherCurrency() - - const bnGwei = bn.shiftedBy(-9).decimalPlaces(6, BigNumber.ROUND_FLOOR) return { bn, - ...currency, - gwei: bnGwei.isZero() ? '' : bnGwei.toFormat(), - wei: bn.toFormat(0) + ...currencyHelperMap } } diff --git a/test/resources/utils/displayValue.test.js b/test/resources/utils/displayValue.test.js index c78a354cf..aeb2415b5 100644 --- a/test/resources/utils/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -4,26 +4,26 @@ import { displayValueData } from '../../../resources/utils/displayValue' describe('wei', () => { it('should return a wei value', () => { const displayValue = displayValueData(356) - expect(displayValue.wei).toBe('356') + expect(displayValue.wei()).toStrictEqual({ displayValue: '356', value: BigNumber('356') }) }) }) describe('gwei', () => { it('should return a gwei value', () => { const displayValue = displayValueData(356e9) - expect(displayValue.gwei).toBe('356') + expect(displayValue.gwei()).toStrictEqual({ displayValue: '356', value: BigNumber('356') }) }) it('should not return a gwei value of more than 6dp', () => { const displayValue = displayValueData(356e-18) - expect(displayValue.gwei).toBe('') + expect(displayValue.gwei()).toStrictEqual({ displayValue: '0', value: BigNumber('0') }) }) }) describe('fiat currency', () => { it('should return zero when no currency rate is provided', () => { const value = displayValueData(356e24) - expect(value.fiat).toStrictEqual({ + expect(value.fiat()).toStrictEqual({ approximationSymbol: '<', displayValue: '0.01', value: BigNumber(0) @@ -32,7 +32,7 @@ describe('fiat currency', () => { it('should return "testnet zero" when isTestnet is true', () => { const value = displayValueData(356e24, { currencyRate: { price: BigNumber(1.3) }, isTestnet: true }) - expect(value.fiat).toStrictEqual({ + expect(value.fiat()).toStrictEqual({ displayValue: '?', value: BigNumber(0) }) @@ -40,7 +40,7 @@ describe('fiat currency', () => { it('should return a value of thousands', () => { const value = displayValueData(356e20, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat).toStrictEqual({ + expect(value.fiat()).toStrictEqual({ displayUnit: { fullName: 'thousand', shortName: 'K', @@ -52,7 +52,7 @@ describe('fiat currency', () => { it('should return a value of millions', () => { const value = displayValueData(356e23, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat).toStrictEqual({ + expect(value.fiat()).toStrictEqual({ displayUnit: { fullName: 'million', shortName: 'M', @@ -64,7 +64,7 @@ describe('fiat currency', () => { it('should return a value of billions', () => { const value = displayValueData(356e26, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat).toStrictEqual({ + expect(value.fiat()).toStrictEqual({ displayUnit: { fullName: 'billion', shortName: 'B', @@ -76,7 +76,7 @@ describe('fiat currency', () => { it('should return a value of trillions', () => { const value = displayValueData(356e29, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat).toStrictEqual({ + expect(value.fiat()).toStrictEqual({ displayUnit: { fullName: 'trillion', shortName: 'T', @@ -88,7 +88,7 @@ describe('fiat currency', () => { it('should return a value of quadrillions', () => { const value = displayValueData(356e32, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat).toStrictEqual({ + expect(value.fiat()).toStrictEqual({ displayUnit: { fullName: 'quadrillion', shortName: 'Q', @@ -102,7 +102,7 @@ describe('fiat currency', () => { describe('ether currency', () => { it('should handle values smaller than the number of decimals requested', () => { const value = displayValueData(356e-8, { decimalsOverride: 6 }) - expect(value.ether).toStrictEqual({ + expect(value.ether()).toStrictEqual({ approximationSymbol: '<', displayValue: '0.000001', value: BigNumber(0) @@ -111,7 +111,7 @@ describe('ether currency', () => { it('should return a value of thousands', () => { const value = displayValueData(356e20) - expect(value.ether).toStrictEqual({ + expect(value.ether()).toStrictEqual({ displayUnit: { fullName: 'thousand', shortName: 'K', @@ -123,7 +123,7 @@ describe('ether currency', () => { it('should return a value of millions', () => { const value = displayValueData(356e23) - expect(value.ether).toStrictEqual({ + expect(value.ether()).toStrictEqual({ displayUnit: { fullName: 'million', shortName: 'M', @@ -135,7 +135,7 @@ describe('ether currency', () => { it('should return a value of billions', () => { const value = displayValueData(356e26) - expect(value.ether).toStrictEqual({ + expect(value.ether()).toStrictEqual({ displayUnit: { fullName: 'billion', shortName: 'B', @@ -147,7 +147,7 @@ describe('ether currency', () => { it('should return a value of trillions', () => { const value = displayValueData(356e29) - expect(value.ether).toStrictEqual({ + expect(value.ether()).toStrictEqual({ displayUnit: { fullName: 'trillion', shortName: 'T', @@ -159,7 +159,7 @@ describe('ether currency', () => { it('should return a value of quadrillions', () => { const value = displayValueData(356e32) - expect(value.ether).toStrictEqual({ + expect(value.ether()).toStrictEqual({ displayUnit: { fullName: 'quadrillion', shortName: 'Q', From a1e18a5972ffbeb9718ce00e2da7d5f2a5bc37f3 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Mon, 14 Nov 2022 16:50:57 +0000 Subject: [PATCH 28/50] fix usd balances --- .../Account/Account/Balances/Balance/index.js | 18 ++---------------- .../Account/Balances/BalancesPreview/index.js | 6 +++--- resources/domain/balance/index.ts | 4 ++-- resources/utils/displayValue.ts | 2 +- 4 files changed, 8 insertions(+), 22 deletions(-) diff --git a/app/App/Account/Account/Balances/Balance/index.js b/app/App/Account/Account/Balances/Balance/index.js index 48ddb5c95..77049a6e9 100644 --- a/app/App/Account/Account/Balances/Balance/index.js +++ b/app/App/Account/Account/Balances/Balance/index.js @@ -3,8 +3,8 @@ import Restore from 'react-restore' import { DisplayValue } from '../../../../../../resources/Components/DisplayValue' import RingIcon from '../../../../../../resources/Components/RingIcon' - import svg from '../../../../../../resources/svg' + class Balance extends React.Component { // constructor (...args) { // super(...args) @@ -34,7 +34,6 @@ class Balance extends React.Component { let name = balance.name if (name.length > 19) name = name.substr(0, 17) + '..' - const chainHex = '0x' + chainId.toString(16) const priceChange = () => { if (!balance.priceChange) { return '' @@ -66,16 +65,6 @@ class Balance extends React.Component { {name}
= 12 ? { fontSize: '15px', top: '10px' } : {}}> - {/* - {symbol.toUpperCase()} - - = 12 ? { marginTop: '-3px' } : {}} - > - {balance.displayBalance} - */}
@@ -87,10 +76,7 @@ class Balance extends React.Component { {priceChange()}
-
- {svg.usd(10)}{balance.displayValue} -
- +
diff --git a/app/App/Account/Account/Balances/BalancesPreview/index.js b/app/App/Account/Account/Balances/BalancesPreview/index.js index 93f5f5349..91cd22c18 100644 --- a/app/App/Account/Account/Balances/BalancesPreview/index.js +++ b/app/App/Account/Account/Balances/BalancesPreview/index.js @@ -72,7 +72,7 @@ class BalancesPreview extends React.Component { const decimals = isNative ? nativeCurrencyInfo.decimals || 18 : rawBalance.decimals const symbol = (isNative && nativeCurrencyInfo.symbol) || rawBalance.symbol - return createBalance({ ...rawBalance, logoURI, name, decimals, symbol }, networks[rawBalance.chainId].isTestnet ? { price: 0 } : rate.usd) + return createBalance({ ...rawBalance, logoURI, name, decimals, symbol }, rate.usd) }) .sort(byTotalValue) @@ -89,8 +89,8 @@ class BalancesPreview extends React.Component { const { balances: allBalances, totalDisplayValue, totalValue } = this.getBalances(storedBalances, rates) // if filter only show balances that match filter - const filteredBlanaces = allBalances.filter(rawBalance => this.isFilterMatch(rawBalance)) - const balances = filteredBlanaces.slice(0, 4) + const filteredBalances = allBalances.filter(rawBalance => this.isFilterMatch(rawBalance)) + const balances = filteredBalances.slice(0, 4) const lastBalanceUpdate = this.store('main.accounts', address, 'balances.lastUpdated') diff --git a/resources/domain/balance/index.ts b/resources/domain/balance/index.ts index 4a0764eeb..490d31312 100644 --- a/resources/domain/balance/index.ts +++ b/resources/domain/balance/index.ts @@ -5,7 +5,7 @@ interface DisplayedBalance extends Balance { displayBalance: string price: string priceChange: string | false - usdRate: BigNumber + usdRate: Rate totalValue: BigNumber displayValue: string } @@ -41,7 +41,7 @@ export function createBalance (rawBalance: Balance, quote?: Rate): DisplayedBala return { ...rawBalance, - usdRate, + usdRate: quote as Rate, displayBalance: formatBalance(balance, totalValue, balanceDecimals), price: formatUsdRate(usdRate), priceChange: !usdRate.isZero() && !usdRate.isNaN() && change24hr.toFixed(2), diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index 9325e406e..3b8f52ed3 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -64,7 +64,7 @@ export function displayValueData (sourceValue: SourceValue, params: DisplayValue const currencyHelperMap = { fiat: () => { const nativeCurrency = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate.price) - const value = bn.shiftedBy(-18).multipliedBy(nativeCurrency).decimalPlaces(2, BigNumber.ROUND_FLOOR) + const value = bn.shiftedBy(-decimals).multipliedBy(nativeCurrency).decimalPlaces(decimalsOverride !== undefined ? decimalsOverride : 2, BigNumber.ROUND_FLOOR) if (isTestnet || value.isNaN()) { return { From 573ddac4bb9a0224ed5d872096b11b03403dd064 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Mon, 14 Nov 2022 22:58:53 +0000 Subject: [PATCH 29/50] rework decimalsOverride, balances, add fullValue exemption --- .../Account/Account/Balances/Balance/index.js | 23 +++++----- .../Account/Balances/BalancesPreview/index.js | 2 +- .../TransactionRequest/TxFeeNew/index.js | 4 +- resources/Components/DisplayValue/index.js | 8 +++- resources/domain/balance/index.ts | 2 +- resources/utils/displayValue.ts | 42 ++++++++++--------- 6 files changed, 44 insertions(+), 37 deletions(-) diff --git a/app/App/Account/Account/Balances/Balance/index.js b/app/App/Account/Account/Balances/Balance/index.js index 77049a6e9..7b3e326fe 100644 --- a/app/App/Account/Account/Balances/Balance/index.js +++ b/app/App/Account/Account/Balances/Balance/index.js @@ -21,7 +21,8 @@ class Balance extends React.Component { render () { const { symbol, balance, i, scanning, chainId } = this.props - const change = parseFloat(balance.priceChange) + const { priceChange, decimals, balance: balanceValue, usdRate: currencyRate, logoURI, price, displayBalance = '0' } = balance + const change = parseFloat(priceChange) const direction = change < 0 ? -1 : change > 0 ? 1 : 0 let priceChangeClass = 'signerBalanceCurrentPriceChange' if (direction !== 0) { @@ -34,14 +35,14 @@ class Balance extends React.Component { let name = balance.name if (name.length > 19) name = name.substr(0, 17) + '..' - const priceChange = () => { - if (!balance.priceChange) { + const displayPriceChange = () => { + if (!priceChange) { return '' } - return `(${direction === 1 ? '+' : ''}${balance.priceChange}%)` + return `(${direction === 1 ? '+' : ''}${priceChange}%)` } const chain = this.store('main.networks.ethereum', chainId) - const chainName = chain ? chain.name : '' + const { name: chainName = '', isTestnet = false } = chain const chainColor = this.store('main.networksMeta.ethereum', chainId, 'primaryColor') return ( @@ -50,7 +51,7 @@ class Balance extends React.Component {
@@ -64,19 +65,19 @@ class Balance extends React.Component {
{name}
-
= 12 ? { fontSize: '15px', top: '10px' } : {}}> - +
= 12 ? { fontSize: '15px', top: '10px' } : {}}> +
- {svg.usd(10)}{balance.price} + - {priceChange()} + {displayPriceChange()}
- +
diff --git a/app/App/Account/Account/Balances/BalancesPreview/index.js b/app/App/Account/Account/Balances/BalancesPreview/index.js index 91cd22c18..80ad5ad7f 100644 --- a/app/App/Account/Account/Balances/BalancesPreview/index.js +++ b/app/App/Account/Account/Balances/BalancesPreview/index.js @@ -72,7 +72,7 @@ class BalancesPreview extends React.Component { const decimals = isNative ? nativeCurrencyInfo.decimals || 18 : rawBalance.decimals const symbol = (isNative && nativeCurrencyInfo.symbol) || rawBalance.symbol - return createBalance({ ...rawBalance, logoURI, name, decimals, symbol }, rate.usd) + return createBalance({ ...rawBalance, logoURI, name, decimals, symbol }, networks[rawBalance.chainId].isTestnet ? { price: 0 } : rate.usd) }) .sort(byTotalValue) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index 4c9a19009..1082f2e6b 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -25,7 +25,7 @@ const GasDisplay = ({ maxFeePerGas }) => { } const USDEstimateDisplay = ({ minFee, maxFee, nativeCurrency }) => { - const { value: maxFeeValue, approximationSymbol: maxFeeApproximation } = maxFee.fiat() + const { value: maxFeeValue, approximationSymbol: maxFeeApproximation } = maxFee.fiat(2) const displayMaxFeeWarning = maxFeeValue > FEE_WARNING_THRESHOLD_USD return
@@ -62,7 +62,7 @@ class TxFee extends React.Component { const maxFeePerGas = BigNumber(req.data[usesBaseFee(req.data) ? 'maxFeePerGas' : 'gasPrice']) const maxFee = displayValueData( maxFeePerGas.multipliedBy(maxGas), - { decimalsOverride: 6, currencyRate: nativeCurrency.usd, isTestnet } + { currencyRate: nativeCurrency.usd, isTestnet } ) // accounts for two potential 12.5% block fee increases diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js index e3c8845a3..4eab0fa03 100644 --- a/resources/Components/DisplayValue/index.js +++ b/resources/Components/DisplayValue/index.js @@ -3,9 +3,13 @@ import { displayValueData } from '../../utils/displayValue' const CurrencySymbol = ({ symbol }) => {symbol} -export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol, type = 'ether', currencySymbolPosition = 'first' }) => { +export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol, type = 'ether', decimalsOverride, currencySymbolPosition = 'first' }) => { const data = valueData || displayValueData(value, valueDataParams) - const { approximationSymbol = '', displayValue, displayUnit } = data[type]() + const defaultDecimals = { + ether: 6, + fiat: 2 + } + const { approximationSymbol = '', displayValue, displayUnit } = data[type](decimalsOverride === undefined ? defaultDecimals[type] : decimalsOverride) return
{approximationSymbol} diff --git a/resources/domain/balance/index.ts b/resources/domain/balance/index.ts index 490d31312..f34644241 100644 --- a/resources/domain/balance/index.ts +++ b/resources/domain/balance/index.ts @@ -22,7 +22,7 @@ export function formatBalance (balance: BigNumber, totalValue: BigNumber, decima }).format(Number(balance.toFixed(decimals, BigNumber.ROUND_FLOOR))) } -export function formatUsdRate (rate:BigNumber, decimals = 2) { +export function formatUsdRate (rate: BigNumber, decimals = 2) { return rate.isNaN() ? UNKNOWN : new Intl.NumberFormat('us-US', { diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index 3b8f52ed3..144c924ad 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -29,42 +29,44 @@ const displayUnitMapping = { } } -function getDisplayValue (bn: BigNumber) { - // large numbers - for (const [unitName, { lowerBound, upperBound, unitDisplay }] of Object.entries(displayUnitMapping)) { - if (bn.isGreaterThan(lowerBound) && bn.isLessThan(upperBound)) { - return { - displayValue: bn.shiftedBy(-(lowerBound.sd(true))).sd(3).toFormat(), - displayUnit: { - fullName: unitName, - shortName: unitDisplay +function getDisplayValue (bn: BigNumber, decimalsOverride?: number, displayFullValue?: boolean) { + if (!displayFullValue) { + // shorthand display of large numbers + for (const [unitName, { lowerBound, upperBound, unitDisplay }] of Object.entries(displayUnitMapping)) { + if (bn.isGreaterThan(lowerBound) && bn.isLessThan(upperBound)) { + return { + displayValue: bn.shiftedBy(-(lowerBound.sd(true))).sd(3).toFormat(), + displayUnit: { + fullName: unitName, + shortName: unitDisplay + } } } } } - // small numbers < 1000 + // display small numbers or full values return { - displayValue: bn.toFormat() + displayValue: bn.toFormat(decimalsOverride) } } type DisplayValueDataParams = { - currencyRate?: Rate, - decimals: number, - decimalsOverride?: number, - isTestnet: boolean + currencyRate?: Rate + displayFullValue?: boolean + decimals: number + isTestnet: boolean } type SourceValue = string | number | BigNumber export function displayValueData (sourceValue: SourceValue, params: DisplayValueDataParams) { - const { currencyRate, decimals = 18, decimalsOverride, isTestnet = false } = params || {} as DisplayValueDataParams + const { currencyRate, decimals = 18, isTestnet = false, displayFullValue = false } = params || {} as DisplayValueDataParams const bn = BigNumber(sourceValue, isHexString(sourceValue) ? 16 : undefined) const currencyHelperMap = { - fiat: () => { + fiat: (decimalsOverride: number) => { const nativeCurrency = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate.price) - const value = bn.shiftedBy(-decimals).multipliedBy(nativeCurrency).decimalPlaces(decimalsOverride !== undefined ? decimalsOverride : 2, BigNumber.ROUND_FLOOR) + const value = bn.shiftedBy(-decimals).multipliedBy(nativeCurrency).decimalPlaces(decimalsOverride, BigNumber.ROUND_FLOOR) if (isTestnet || value.isNaN()) { return { @@ -83,10 +85,10 @@ export function displayValueData (sourceValue: SourceValue, params: DisplayValue return { value, - ...getDisplayValue(value) + ...getDisplayValue(value, decimalsOverride, displayFullValue) } }, - ether: () => { + ether: (decimalsOverride: number) => { const value = bn.shiftedBy(-decimals).decimalPlaces(decimalsOverride || decimals, BigNumber.ROUND_FLOOR) if (decimalsOverride && value.isZero()) { From a596bc033d9cacab050df3748167d02aa5b5f856 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Tue, 15 Nov 2022 01:29:16 +0000 Subject: [PATCH 30/50] more cleanup, maximum values --- resources/Components/DisplayValue/index.js | 6 +-- resources/utils/displayValue.ts | 45 ++++++++++------------ test/resources/utils/displayValue.test.js | 36 +++++++++++++++++ 3 files changed, 57 insertions(+), 30 deletions(-) diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js index 4eab0fa03..c276c860c 100644 --- a/resources/Components/DisplayValue/index.js +++ b/resources/Components/DisplayValue/index.js @@ -5,11 +5,7 @@ const CurrencySymbol = ({ symbol }) => {symbol} export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol, type = 'ether', decimalsOverride, currencySymbolPosition = 'first' }) => { const data = valueData || displayValueData(value, valueDataParams) - const defaultDecimals = { - ether: 6, - fiat: 2 - } - const { approximationSymbol = '', displayValue, displayUnit } = data[type](decimalsOverride === undefined ? defaultDecimals[type] : decimalsOverride) + const { approximationSymbol = '', displayValue, displayUnit } = data[type](decimalsOverride) return
{approximationSymbol} diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index 144c924ad..5512b0a6c 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -28,14 +28,26 @@ const displayUnitMapping = { unitDisplay: 'Q' } } +const maxDisplayValue = BigNumber(999999999999999999999) + +function getDisplayValue (bn: BigNumber, context: string, decimalsOverride?: number, displayFullValue?: boolean) { + if (bn.isZero()) { + return { + approximationSymbol: '<', + displayValue: BigNumber(`1e-${decimalsOverride}`).toFormat() + } + } -function getDisplayValue (bn: BigNumber, decimalsOverride?: number, displayFullValue?: boolean) { if (!displayFullValue) { // shorthand display of large numbers for (const [unitName, { lowerBound, upperBound, unitDisplay }] of Object.entries(displayUnitMapping)) { if (bn.isGreaterThan(lowerBound) && bn.isLessThan(upperBound)) { + const displayMax = bn.isGreaterThan(maxDisplayValue) + + // maximum display value is hard coded because maxDisplayValue is above the bignumber 15sd limit return { - displayValue: bn.shiftedBy(-(lowerBound.sd(true))).sd(3).toFormat(), + approximationSymbol: displayMax ? '>' : '', + displayValue: displayMax ? '999,999' : bn.shiftedBy(-(lowerBound.sd(true))).sd(3).toFormat(), displayUnit: { fullName: unitName, shortName: unitDisplay @@ -47,7 +59,7 @@ function getDisplayValue (bn: BigNumber, decimalsOverride?: number, displayFullV // display small numbers or full values return { - displayValue: bn.toFormat(decimalsOverride) + displayValue: bn.toFormat(context === 'fiat' ? decimalsOverride : undefined) } } @@ -64,7 +76,7 @@ export function displayValueData (sourceValue: SourceValue, params: DisplayValue const { currencyRate, decimals = 18, isTestnet = false, displayFullValue = false } = params || {} as DisplayValueDataParams const bn = BigNumber(sourceValue, isHexString(sourceValue) ? 16 : undefined) const currencyHelperMap = { - fiat: (decimalsOverride: number) => { + fiat: (decimalsOverride = 2) => { const nativeCurrency = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate.price) const value = bn.shiftedBy(-decimals).multipliedBy(nativeCurrency).decimalPlaces(decimalsOverride, BigNumber.ROUND_FLOOR) @@ -74,43 +86,26 @@ export function displayValueData (sourceValue: SourceValue, params: DisplayValue displayValue: '?' } } - - if (value.isZero()) { - return { - value, - approximationSymbol: '<', - displayValue: '0.01' - } - } return { value, - ...getDisplayValue(value, decimalsOverride, displayFullValue) + ...getDisplayValue(value, 'fiat', decimalsOverride, displayFullValue) } }, - ether: (decimalsOverride: number) => { + ether: (decimalsOverride = 6) => { const value = bn.shiftedBy(-decimals).decimalPlaces(decimalsOverride || decimals, BigNumber.ROUND_FLOOR) - - if (decimalsOverride && value.isZero()) { - return { - value, - approximationSymbol: '<', - displayValue: BigNumber(`1e-${decimalsOverride}`).toFormat() - } - } return { value, - ...getDisplayValue(value) + ...getDisplayValue(value, 'ether', decimalsOverride) } }, gwei: () => { const value = bn.shiftedBy(-9).decimalPlaces(6, BigNumber.ROUND_FLOOR) - // return bnGwei.isZero() ? '' : bnGwei.toFormat() return { value, - ...getDisplayValue(value) + displayValue: value.isZero() ? '0' : value.toFormat() } }, wei: () => ({ diff --git a/test/resources/utils/displayValue.test.js b/test/resources/utils/displayValue.test.js index aeb2415b5..e48a62f40 100644 --- a/test/resources/utils/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -41,6 +41,7 @@ describe('fiat currency', () => { it('should return a value of thousands', () => { const value = displayValueData(356e20, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', displayUnit: { fullName: 'thousand', shortName: 'K', @@ -53,6 +54,7 @@ describe('fiat currency', () => { it('should return a value of millions', () => { const value = displayValueData(356e23, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', displayUnit: { fullName: 'million', shortName: 'M', @@ -65,6 +67,7 @@ describe('fiat currency', () => { it('should return a value of billions', () => { const value = displayValueData(356e26, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', @@ -77,6 +80,7 @@ describe('fiat currency', () => { it('should return a value of trillions', () => { const value = displayValueData(356e29, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', @@ -89,6 +93,7 @@ describe('fiat currency', () => { it('should return a value of quadrillions', () => { const value = displayValueData(356e32, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', @@ -97,6 +102,19 @@ describe('fiat currency', () => { value: BigNumber(35600000000000000) }) }) + + it('should return a maximum value', () => { + const value = displayValueData(356e50, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '>', + displayUnit: { + fullName: 'quadrillion', + shortName: 'Q', + }, + displayValue: '999,999', + value: BigNumber(3.56e+34) + }) + }) }) describe('ether currency', () => { @@ -112,6 +130,7 @@ describe('ether currency', () => { it('should return a value of thousands', () => { const value = displayValueData(356e20) expect(value.ether()).toStrictEqual({ + approximationSymbol: '', displayUnit: { fullName: 'thousand', shortName: 'K', @@ -124,6 +143,7 @@ describe('ether currency', () => { it('should return a value of millions', () => { const value = displayValueData(356e23) expect(value.ether()).toStrictEqual({ + approximationSymbol: '', displayUnit: { fullName: 'million', shortName: 'M', @@ -136,6 +156,7 @@ describe('ether currency', () => { it('should return a value of billions', () => { const value = displayValueData(356e26) expect(value.ether()).toStrictEqual({ + approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', @@ -148,6 +169,7 @@ describe('ether currency', () => { it('should return a value of trillions', () => { const value = displayValueData(356e29) expect(value.ether()).toStrictEqual({ + approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', @@ -160,6 +182,7 @@ describe('ether currency', () => { it('should return a value of quadrillions', () => { const value = displayValueData(356e32) expect(value.ether()).toStrictEqual({ + approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', @@ -168,4 +191,17 @@ describe('ether currency', () => { value: BigNumber(35600000000000000) }) }) + + it('should return a maximum value', () => { + const value = displayValueData(356e50) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '>', + displayUnit: { + fullName: 'quadrillion', + shortName: 'Q', + }, + displayValue: '999,999', + value: BigNumber(3.56e+34) + }) + }) }) \ No newline at end of file From 7a075398fa696d9048ec818680a9eba860541e31 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Tue, 15 Nov 2022 01:36:38 +0000 Subject: [PATCH 31/50] add new line --- test/resources/utils/displayValue.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/resources/utils/displayValue.test.js b/test/resources/utils/displayValue.test.js index e48a62f40..6e51c2030 100644 --- a/test/resources/utils/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -204,4 +204,4 @@ describe('ether currency', () => { value: BigNumber(3.56e+34) }) }) -}) \ No newline at end of file +}) From 09943b4baea3a4e1727bbca0122793f290999853 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Tue, 15 Nov 2022 15:14:01 +0000 Subject: [PATCH 32/50] conditional display of currencySymbol, add test-id --- app/App/Account/Account/Balances/Balance/index.js | 2 +- resources/Components/DisplayValue/index.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/App/Account/Account/Balances/Balance/index.js b/app/App/Account/Account/Balances/Balance/index.js index 7b3e326fe..85cbcdd29 100644 --- a/app/App/Account/Account/Balances/Balance/index.js +++ b/app/App/Account/Account/Balances/Balance/index.js @@ -66,7 +66,7 @@ class Balance extends React.Component { {name}
= 12 ? { fontSize: '15px', top: '10px' } : {}}> - +
diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js index c276c860c..a2148c32d 100644 --- a/resources/Components/DisplayValue/index.js +++ b/resources/Components/DisplayValue/index.js @@ -7,11 +7,11 @@ export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol const data = valueData || displayValueData(value, valueDataParams) const { approximationSymbol = '', displayValue, displayUnit } = data[type](decimalsOverride) - return
+ return
{approximationSymbol} - {currencySymbolPosition === 'first' && } + {currencySymbol && currencySymbolPosition === 'first' && } {displayValue} {displayUnit ? displayUnit.shortName : ''} - {currencySymbolPosition === 'last' && } + {currencySymbol && currencySymbolPosition === 'last' && }
} From b204451a207e3e59de4dec47bd68440cb6d63e08 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Tue, 15 Nov 2022 19:04:36 +0000 Subject: [PATCH 33/50] component tests and some fixes --- resources/Components/DisplayValue/index.js | 6 +- resources/utils/displayValue.ts | 18 ++++- .../Components/DisplayValue/index.test.js | 77 +++++++++++++++++++ 3 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 test/resources/Components/DisplayValue/index.test.js diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js index a2148c32d..97ce3e2dc 100644 --- a/resources/Components/DisplayValue/index.js +++ b/resources/Components/DisplayValue/index.js @@ -7,11 +7,11 @@ export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol const data = valueData || displayValueData(value, valueDataParams) const { approximationSymbol = '', displayValue, displayUnit } = data[type](decimalsOverride) - return
- {approximationSymbol} + return
+ {approximationSymbol && {approximationSymbol}} {currencySymbol && currencySymbolPosition === 'first' && } {displayValue} - {displayUnit ? displayUnit.shortName : ''} + {displayUnit && {displayUnit.shortName}} {currencySymbol && currencySymbolPosition === 'last' && }
} diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index 5512b0a6c..087284b72 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -30,7 +30,17 @@ const displayUnitMapping = { } const maxDisplayValue = BigNumber(999999999999999999999) -function getDisplayValue (bn: BigNumber, context: string, decimalsOverride?: number, displayFullValue?: boolean) { +function getShorthandDisplayValue (bn: BigNumber, shiftedBy: number, decimalPlaces: number) { + const value = bn.shiftedBy(shiftedBy) + + if (decimalPlaces !== 2) { + return value.decimalPlaces(decimalPlaces).toFormat() + } + + return value.sd(3).toFormat() +} + +function getDisplay (bn: BigNumber, context: string, decimalsOverride: number, displayFullValue?: boolean) { if (bn.isZero()) { return { approximationSymbol: '<', @@ -47,7 +57,7 @@ function getDisplayValue (bn: BigNumber, context: string, decimalsOverride?: num // maximum display value is hard coded because maxDisplayValue is above the bignumber 15sd limit return { approximationSymbol: displayMax ? '>' : '', - displayValue: displayMax ? '999,999' : bn.shiftedBy(-(lowerBound.sd(true))).sd(3).toFormat(), + displayValue: displayMax ? '999,999' : getShorthandDisplayValue(bn, -(lowerBound.sd(true)), decimalsOverride), displayUnit: { fullName: unitName, shortName: unitDisplay @@ -89,7 +99,7 @@ export function displayValueData (sourceValue: SourceValue, params: DisplayValue return { value, - ...getDisplayValue(value, 'fiat', decimalsOverride, displayFullValue) + ...getDisplay(value, 'fiat', decimalsOverride, displayFullValue) } }, ether: (decimalsOverride = 6) => { @@ -97,7 +107,7 @@ export function displayValueData (sourceValue: SourceValue, params: DisplayValue return { value, - ...getDisplayValue(value, 'ether', decimalsOverride) + ...getDisplay(value, 'ether', decimalsOverride, displayFullValue) } }, gwei: () => { diff --git a/test/resources/Components/DisplayValue/index.test.js b/test/resources/Components/DisplayValue/index.test.js new file mode 100644 index 000000000..3594de5f4 --- /dev/null +++ b/test/resources/Components/DisplayValue/index.test.js @@ -0,0 +1,77 @@ +import React from 'react' + +import { setupComponent } from '../../../componentSetup' +import { DisplayValue } from '../../../../resources/Components/DisplayValue' +import { displayValueData } from '../../../../resources/utils/displayValue' + + +it('should render the expected content when provided with valueData', () => { + const valueData = new displayValueData(356e28) + const { getByTestId } = setupComponent() + const displayValue = getByTestId('display-value') + + expect(displayValue.textContent).toBe('3.56T') +}) + +it('should render the expected content when provided with a value and valueDataParams', () => { + const { getByTestId } = setupComponent() + const displayValue = getByTestId('display-value') + + expect(displayValue.textContent).toBe('356T') +}) + +it('should render a currency symbol before the value when specified', () => { + const { getByTestId } = setupComponent() + const displayValue = getByTestId('display-value') + + expect(displayValue.textContent).toBe('MYTOKEN356') +}) + +it('should render a currency symbol after the value when specified with currencySymbolPosition', () => { + const { getByTestId } = setupComponent() + const displayValue = getByTestId('display-value') + + expect(displayValue.textContent).toBe('356MYTOKEN') +}) + +it('should render a fiat value', () => { + const { getByTestId } = setupComponent() + const displayValue = getByTestId('display-value') + + expect(displayValue.textContent).toBe('$5.34T') +}) + +it('should override decimals on a fiat value', () => { + const { getByTestId } = setupComponent() + const displayValue = getByTestId('display-value') + + expect(displayValue.textContent).toBe('$5.3T') +}) + +it('should not render a shorthand unit when displayFullValue is specified on a fiat value', () => { + const { getByTestId } = setupComponent() + const displayValue = getByTestId('display-value') + + expect(displayValue.textContent).toBe('$5,340,000,000,000.00') +}) + +it('should render an ether value', () => { + const { getByTestId } = setupComponent() + const displayValue = getByTestId('display-value') + + expect(displayValue.textContent).toBe('ETH3.56T') +}) + +it('should override decimals on an ether value', () => { + const { getByTestId } = setupComponent() + const displayValue = getByTestId('display-value') + + expect(displayValue.textContent).toBe('ETH3.5673B') +}) + +it('should not render a shorthand unit when displayFullValue is specified on an ether value', () => { + const { getByTestId } = setupComponent() + const displayValue = getByTestId('display-value') + + expect(displayValue.textContent).toBe('ETH3,560,000,000,000') +}) \ No newline at end of file From fe71e9ebf14e5f9f2b43d0f31e0b795b1839e7a7 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 16 Nov 2022 01:54:03 +0000 Subject: [PATCH 34/50] more fiat tests, decimals updates --- .../Account/Account/Balances/Balance/index.js | 4 +- resources/Components/DisplayValue/index.js | 4 +- resources/utils/displayValue.ts | 57 +-- test/resources/utils/displayValue.test.js | 456 ++++++++++++------ 4 files changed, 347 insertions(+), 174 deletions(-) diff --git a/app/App/Account/Account/Balances/Balance/index.js b/app/App/Account/Account/Balances/Balance/index.js index 85cbcdd29..57ce23cda 100644 --- a/app/App/Account/Account/Balances/Balance/index.js +++ b/app/App/Account/Account/Balances/Balance/index.js @@ -71,13 +71,13 @@ class Balance extends React.Component {
- + {displayPriceChange()}
- +
diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js index 97ce3e2dc..95e6867c4 100644 --- a/resources/Components/DisplayValue/index.js +++ b/resources/Components/DisplayValue/index.js @@ -3,9 +3,9 @@ import { displayValueData } from '../../utils/displayValue' const CurrencySymbol = ({ symbol }) => {symbol} -export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol, type = 'ether', decimalsOverride, currencySymbolPosition = 'first' }) => { +export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol, type = 'ether', displayDecimals = true, currencySymbolPosition = 'first' }) => { const data = valueData || displayValueData(value, valueDataParams) - const { approximationSymbol = '', displayValue, displayUnit } = data[type](decimalsOverride) + const { approximationSymbol = '', displayValue, displayUnit } = data[type]({ displayDecimals }) return
{approximationSymbol && {approximationSymbol}} diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index 087284b72..e1041476e 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -3,61 +3,52 @@ import { isHexString } from 'ethers/lib/utils' const displayUnitMapping = { thousand: { - lowerBound: BigNumber(999), - upperBound: BigNumber(999999), + lowerBound: BigNumber(999.99), + upperBound: BigNumber(999999.99), unitDisplay: 'K' }, million: { - lowerBound: BigNumber(999999), - upperBound: BigNumber(999999999), + lowerBound: BigNumber(999999.99), + upperBound: BigNumber(999999999.99), unitDisplay: 'M' }, billion: { - lowerBound: BigNumber(999999999), - upperBound: BigNumber(999999999999), + lowerBound: BigNumber(999999999.99), + upperBound: BigNumber(999999999999.99), unitDisplay: 'B' }, trillion: { - lowerBound: BigNumber(999999999999), - upperBound: BigNumber(999999999999999), + lowerBound: BigNumber(999999999999.99), + upperBound: BigNumber(999999999999999).plus(0.99), // working around the 15sd limit unitDisplay: 'T' }, quadrillion: { - lowerBound: BigNumber(999999999999999), + lowerBound: BigNumber(999999999999999).plus(0.99), // working around the 15sd limit upperBound: BigNumber(Infinity), unitDisplay: 'Q' } } const maxDisplayValue = BigNumber(999999999999999999999) -function getShorthandDisplayValue (bn: BigNumber, shiftedBy: number, decimalPlaces: number) { - const value = bn.shiftedBy(shiftedBy) - - if (decimalPlaces !== 2) { - return value.decimalPlaces(decimalPlaces).toFormat() - } - - return value.sd(3).toFormat() -} - -function getDisplay (bn: BigNumber, context: string, decimalsOverride: number, displayFullValue?: boolean) { - if (bn.isZero()) { +function getDisplay (bn: BigNumber, context: string, decimals: number, displayFullValue?: boolean) { + const value = bn.decimalPlaces(decimals, BigNumber.ROUND_FLOOR) + if (value.isZero()) { return { approximationSymbol: '<', - displayValue: BigNumber(`1e-${decimalsOverride}`).toFormat() + displayValue: BigNumber(`1e-${decimals}`).toFormat() } } if (!displayFullValue) { // shorthand display of large numbers for (const [unitName, { lowerBound, upperBound, unitDisplay }] of Object.entries(displayUnitMapping)) { - if (bn.isGreaterThan(lowerBound) && bn.isLessThan(upperBound)) { - const displayMax = bn.isGreaterThan(maxDisplayValue) + if (value.isGreaterThan(lowerBound) && value.isLessThan(upperBound)) { + const displayMax = value.isGreaterThan(maxDisplayValue) // maximum display value is hard coded because maxDisplayValue is above the bignumber 15sd limit return { approximationSymbol: displayMax ? '>' : '', - displayValue: displayMax ? '999,999' : getShorthandDisplayValue(bn, -(lowerBound.sd(true)), decimalsOverride), + displayValue: displayMax ? '999,999' : value.shiftedBy(-(lowerBound.sd(true) - 2)).decimalPlaces(3, BigNumber.ROUND_FLOOR).toFormat(), displayUnit: { fullName: unitName, shortName: unitDisplay @@ -69,7 +60,7 @@ function getDisplay (bn: BigNumber, context: string, decimalsOverride: number, d // display small numbers or full values return { - displayValue: bn.toFormat(context === 'fiat' ? decimalsOverride : undefined) + displayValue: value.toFormat(context === 'fiat' ? decimals : undefined) } } @@ -86,9 +77,10 @@ export function displayValueData (sourceValue: SourceValue, params: DisplayValue const { currencyRate, decimals = 18, isTestnet = false, displayFullValue = false } = params || {} as DisplayValueDataParams const bn = BigNumber(sourceValue, isHexString(sourceValue) ? 16 : undefined) const currencyHelperMap = { - fiat: (decimalsOverride = 2) => { + fiat: ({ displayDecimals } = { displayDecimals: true }) => { const nativeCurrency = BigNumber(isTestnet || !currencyRate ? 0 : currencyRate.price) - const value = bn.shiftedBy(-decimals).multipliedBy(nativeCurrency).decimalPlaces(decimalsOverride, BigNumber.ROUND_FLOOR) + const displayedDecimals = displayDecimals ? 2 : 0 + const value = bn.shiftedBy(-decimals).multipliedBy(nativeCurrency) if (isTestnet || value.isNaN()) { return { @@ -99,15 +91,16 @@ export function displayValueData (sourceValue: SourceValue, params: DisplayValue return { value, - ...getDisplay(value, 'fiat', decimalsOverride, displayFullValue) + ...getDisplay(value, 'fiat', displayedDecimals, displayFullValue) } }, - ether: (decimalsOverride = 6) => { - const value = bn.shiftedBy(-decimals).decimalPlaces(decimalsOverride || decimals, BigNumber.ROUND_FLOOR) + ether: (decimalsOverride?: number) => { + const displayDecimals = decimalsOverride === undefined ? 6 : decimalsOverride + const value = bn.shiftedBy(-decimals) //|| decimals return { value, - ...getDisplay(value, 'ether', decimalsOverride, displayFullValue) + ...getDisplay(value, 'ether', displayDecimals, displayFullValue) } }, gwei: () => { diff --git a/test/resources/utils/displayValue.test.js b/test/resources/utils/displayValue.test.js index 6e51c2030..f69e7f584 100644 --- a/test/resources/utils/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -38,170 +38,350 @@ describe('fiat currency', () => { }) }) - it('should return a value of thousands', () => { - const value = displayValueData(356e20, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'thousand', - shortName: 'K', - }, - displayValue: '35.6', - value: BigNumber(35600) + describe('when displaying decimals', () => { + it('should return a value of less than a cent', () => { + const value = displayValueData(356e12, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '<', + displayValue: '0.01', + value: BigNumber(0.000356) + }) }) - }) - it('should return a value of millions', () => { - const value = displayValueData(356e23, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'million', - shortName: 'M', - }, - displayValue: '35.6', - value: BigNumber(35600000) + it('should return a value less than 1000 with a fixed 2dp', () => { + const value = displayValueData(999999e15, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + displayValue: '999.99', + value: BigNumber(999.999) + }) }) }) - it('should return a value of billions', () => { - const value = displayValueData(356e26, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'billion', - shortName: 'B', - }, - displayValue: '35.6', - value: BigNumber(35600000000) + describe('when not displaying decimals', () => { + it('should return a value of less than a dollar', () => { + const value = displayValueData(356e12, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat({ displayDecimals: false })).toStrictEqual({ + approximationSymbol: '<', + displayValue: '1', + value: BigNumber(0.000356) + }) }) - }) - it('should return a value of trillions', () => { - const value = displayValueData(356e29, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'trillion', - shortName: 'T', - }, - displayValue: '35.6', - value: BigNumber(35600000000000) + it('should return a value less than 1000 without decimals', () => { + const value = displayValueData(999999e15, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat({ displayDecimals: false })).toStrictEqual({ + displayValue: '999', + value: BigNumber(999.999) + }) }) }) - it('should return a value of quadrillions', () => { - const value = displayValueData(356e32, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'quadrillion', - shortName: 'Q', - }, - displayValue: '35.6', - value: BigNumber(35600000000000000) + describe('shorthand large values', () => { + it('should return a value of thousands to 3dp', () => { + const value = displayValueData(356253e17, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'thousand', + shortName: 'K', + }, + displayValue: '35.625', + value: BigNumber(35625.3) + }) }) - }) - it('should return a maximum value', () => { - const value = displayValueData(356e50, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat()).toStrictEqual({ - approximationSymbol: '>', - displayUnit: { - fullName: 'quadrillion', - shortName: 'Q', - }, - displayValue: '999,999', - value: BigNumber(3.56e+34) + it('should round down a value of thousands to 3dp', () => { + const value = displayValueData(356259e17, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'thousand', + shortName: 'K', + }, + displayValue: '35.625', + value: BigNumber(35625.9) + }) }) - }) -}) -describe('ether currency', () => { - it('should handle values smaller than the number of decimals requested', () => { - const value = displayValueData(356e-8, { decimalsOverride: 6 }) - expect(value.ether()).toStrictEqual({ - approximationSymbol: '<', - displayValue: '0.000001', - value: BigNumber(0) + it('should return an exact value of thousands', () => { + const value = displayValueData(35e21, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'thousand', + shortName: 'K', + }, + displayValue: '35', + value: BigNumber(35000) + }) }) - }) - it('should return a value of thousands', () => { - const value = displayValueData(356e20) - expect(value.ether()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'thousand', - shortName: 'K', - }, - displayValue: '35.6', - value: BigNumber(35600) + it('should return a value of millions to 3dp', () => { + const value = displayValueData(356253e20, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'million', + shortName: 'M', + }, + displayValue: '35.625', + value: BigNumber(35625300) + }) }) - }) - it('should return a value of millions', () => { - const value = displayValueData(356e23) - expect(value.ether()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'million', - shortName: 'M', - }, - displayValue: '35.6', - value: BigNumber(35600000) + it('should round down a value of millions to 3dp', () => { + const value = displayValueData(356259e20, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'million', + shortName: 'M', + }, + displayValue: '35.625', + value: BigNumber(35625900) + }) }) - }) - it('should return a value of billions', () => { - const value = displayValueData(356e26) - expect(value.ether()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'billion', - shortName: 'B', - }, - displayValue: '35.6', - value: BigNumber(35600000000) + it('should return an exact value of millions', () => { + const value = displayValueData(35e24, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'million', + shortName: 'M', + }, + displayValue: '35', + value: BigNumber(35000000) + }) }) - }) - it('should return a value of trillions', () => { - const value = displayValueData(356e29) - expect(value.ether()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'trillion', - shortName: 'T', - }, - displayValue: '35.6', - value: BigNumber(35600000000000) + it('should return a value of billions to 3dp', () => { + const value = displayValueData(356253e23, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'billion', + shortName: 'B', + }, + displayValue: '35.625', + value: BigNumber(35625300000) + }) }) - }) - it('should return a value of quadrillions', () => { - const value = displayValueData(356e32) - expect(value.ether()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'quadrillion', - shortName: 'Q', - }, - displayValue: '35.6', - value: BigNumber(35600000000000000) + it('should round down a value of billions to 3dp', () => { + const value = displayValueData(356259e23, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'billion', + shortName: 'B', + }, + displayValue: '35.625', + value: BigNumber(35625900000) + }) + }) + + it('should return an exact value of billions', () => { + const value = displayValueData(35e27, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'billion', + shortName: 'B', + }, + displayValue: '35', + value: BigNumber(35000000000) + }) }) - }) - it('should return a maximum value', () => { - const value = displayValueData(356e50) - expect(value.ether()).toStrictEqual({ - approximationSymbol: '>', - displayUnit: { - fullName: 'quadrillion', - shortName: 'Q', - }, - displayValue: '999,999', - value: BigNumber(3.56e+34) + it('should return a value of trillions to 3dp', () => { + const value = displayValueData(356253e26, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'trillion', + shortName: 'T', + }, + displayValue: '35.625', + value: BigNumber(35625300000000) + }) + }) + + it('should round down a value of trillions to 3dp', () => { + const value = displayValueData(356259e26, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'trillion', + shortName: 'T', + }, + displayValue: '35.625', + value: BigNumber(35625900000000) + }) + }) + + it('should return an exact value of trillions', () => { + const value = displayValueData(35e30, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'trillion', + shortName: 'T', + }, + displayValue: '35', + value: BigNumber(35000000000000) + }) + }) + + it('should return a value of quadrillions to 3dp', () => { + const value = displayValueData(356253e29, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'quadrillion', + shortName: 'Q', + }, + displayValue: '35.625', + value: BigNumber(35625300000000000) + }) + }) + + it('should round down a value of quadrillions to 3dp', () => { + const value = displayValueData(356259e29, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'quadrillion', + shortName: 'Q', + }, + displayValue: '35.625', + value: BigNumber(35625900000000000) + }) + }) + + it('should return an exact value of quadrillions', () => { + const value = displayValueData(35e33, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'quadrillion', + shortName: 'Q', + }, + displayValue: '35', + value: BigNumber(35000000000000000) + }) + }) + + it('should return a maximum value', () => { + const value = displayValueData(356e50, { currencyRate: { price: BigNumber(1) }}) + expect(value.fiat()).toStrictEqual({ + approximationSymbol: '>', + displayUnit: { + fullName: 'quadrillion', + shortName: 'Q', + }, + displayValue: '999,999', + value: BigNumber(3.56e+34) + }) }) }) }) + + +// describe('ether currency', () => { +// it('should handle values smaller than the number of decimals requested', () => { +// const value = displayValueData(356e-8, { decimalsOverride: 6 }) +// expect(value.ether()).toStrictEqual({ +// approximationSymbol: '<', +// displayValue: '0.000001', +// value: BigNumber(0) +// }) +// }) // 999.0000111111 1203.0002231223 + +// it('should handle values smaller than the number of decimals requested', () => { +// const value = displayValueData((998.0000111111 * 1e18)) +// expect(value.ether()).toStrictEqual({ +// approximationSymbol: '<', +// displayValue: '0.000001', +// value: BigNumber(0) +// }) +// }) + +// it('should return a value of thousands', () => { +// const value = displayValueData(356e20) +// expect(value.ether()).toStrictEqual({ +// approximationSymbol: '', +// displayUnit: { +// fullName: 'thousand', +// shortName: 'K', +// }, +// displayValue: '35.6', +// value: BigNumber(35600) +// }) +// }) + +// it('should return a value of millions', () => { +// const value = displayValueData(356e23) +// expect(value.ether()).toStrictEqual({ +// approximationSymbol: '', +// displayUnit: { +// fullName: 'million', +// shortName: 'M', +// }, +// displayValue: '35.6', +// value: BigNumber(35600000) +// }) +// }) + +// it('should return a value of billions', () => { +// const value = displayValueData(356e26) +// expect(value.ether()).toStrictEqual({ +// approximationSymbol: '', +// displayUnit: { +// fullName: 'billion', +// shortName: 'B', +// }, +// displayValue: '35.6', +// value: BigNumber(35600000000) +// }) +// }) + +// it('should return a value of trillions', () => { +// const value = displayValueData(356e29) +// expect(value.ether()).toStrictEqual({ +// approximationSymbol: '', +// displayUnit: { +// fullName: 'trillion', +// shortName: 'T', +// }, +// displayValue: '35.6', +// value: BigNumber(35600000000000) +// }) +// }) + +// it('should return a value of quadrillions', () => { +// const value = displayValueData(356e32) +// expect(value.ether()).toStrictEqual({ +// approximationSymbol: '', +// displayUnit: { +// fullName: 'quadrillion', +// shortName: 'Q', +// }, +// displayValue: '35.6', +// value: BigNumber(35600000000000000) +// }) +// }) + +// it('should return a maximum value', () => { +// const value = displayValueData(356e50) +// expect(value.ether()).toStrictEqual({ +// approximationSymbol: '>', +// displayUnit: { +// fullName: 'quadrillion', +// shortName: 'Q', +// }, +// displayValue: '999,999', +// value: BigNumber(3.56e+34) +// }) +// }) +// }) From 52ec8502071f2146b5dc81828806e00a53650c70 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 16 Nov 2022 04:01:59 +0000 Subject: [PATCH 35/50] scaled decimals & tests --- resources/utils/displayValue.ts | 15 +- test/resources/utils/displayValue.test.js | 394 +++++++++++++++++----- 2 files changed, 325 insertions(+), 84 deletions(-) diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index e1041476e..a0d65b45a 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -94,13 +94,20 @@ export function displayValueData (sourceValue: SourceValue, params: DisplayValue ...getDisplay(value, 'fiat', displayedDecimals, displayFullValue) } }, - ether: (decimalsOverride?: number) => { - const displayDecimals = decimalsOverride === undefined ? 6 : decimalsOverride - const value = bn.shiftedBy(-decimals) //|| decimals + ether: ({ displayDecimals } = { displayDecimals: true }) => { + const value = bn.shiftedBy(-decimals) + const getDisplayedDecimals = () => { + if (!displayDecimals) { + return 0 + } + const preDecimalStr = value.toFixed(1, BigNumber.ROUND_FLOOR).split('.')[0] + const numNonDecimals = preDecimalStr === '0' ? 0 : preDecimalStr.length + return BigNumber(6).minus(BigNumber.min(3, BigNumber.min(6, numNonDecimals))).toNumber() + } return { value, - ...getDisplay(value, 'ether', displayDecimals, displayFullValue) + ...getDisplay(value, 'ether', getDisplayedDecimals(), displayFullValue) } }, gwei: () => { diff --git a/test/resources/utils/displayValue.test.js b/test/resources/utils/displayValue.test.js index f69e7f584..283faf5ce 100644 --- a/test/resources/utils/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -288,7 +288,320 @@ describe('fiat currency', () => { }) -// describe('ether currency', () => { +describe('ether currency', () => { + describe('when displaying decimals', () => { + it('should return a value of less than 1000 gwei', () => { + const value = displayValueData(356e8) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '<', + displayValue: '0.000001', + value: BigNumber(3.56e-8) + }) + }) + + it('should return a value less than 1000 with a fixed 3dp', () => { + const value = displayValueData(998.5678111111e18) + expect(value.ether()).toStrictEqual({ + displayValue: '998.567', + value: BigNumber(998.5678111111) + }) + }) + + it('should return a value less than 100 with a fixed 4dp', () => { + const value = displayValueData(99.85678111111e18) + expect(value.ether()).toStrictEqual({ + displayValue: '99.8567', + value: BigNumber(99.85678111111) + }) + }) + + it('should return a value less than 10 with a fixed 5dp', () => { + const value = displayValueData(9.985678111111e18) + expect(value.ether()).toStrictEqual({ + displayValue: '9.98567', + value: BigNumber(9.985678111111) + }) + }) + + it('should return a value less than 1 with a fixed 6dp', () => { + const value = displayValueData(0.9985678111111e18) + expect(value.ether()).toStrictEqual({ + displayValue: '0.998567', + value: BigNumber(0.9985678111111) + }) + }) + + it('should return a value less than 0.1 with a fixed 6dp', () => { + const value = displayValueData(0.09985678111111e18) + expect(value.ether()).toStrictEqual({ + displayValue: '0.099856', + value: BigNumber(0.09985678111111) + }) + }) + + it('should return a value less than 0.01 with a fixed 6dp', () => { + const value = displayValueData(0.009985678111111e18) + expect(value.ether()).toStrictEqual({ + displayValue: '0.009985', + value: BigNumber(0.009985678111111) + }) + }) + + it('should return a value less than 0.001 with a fixed 6dp', () => { + const value = displayValueData(0.0009985678111111e18) + expect(value.ether()).toStrictEqual({ + displayValue: '0.000998', + value: BigNumber(0.0009985678111111) + }) + }) + + it('should return a value less than 0.0001 with a fixed 6dp', () => { + const value = displayValueData(0.00009985678111111e18) + expect(value.ether()).toStrictEqual({ + displayValue: '0.000099', + value: BigNumber(0.00009985678111111) + }) + }) + + it('should return a value less than 0.00001 with a fixed 6dp', () => { + const value = displayValueData(0.000009985678111111e18) + expect(value.ether()).toStrictEqual({ + displayValue: '0.000009', + value: BigNumber(0.000009985678111111) + }) + }) + }) + + describe('when not displaying decimals', () => { + it('should return a value of less than a dollar', () => { + const value = displayValueData(356e12, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether({ displayDecimals: false })).toStrictEqual({ + approximationSymbol: '<', + displayValue: '1', + value: BigNumber(0.000356) + }) + }) + + it('should return a value less than 1000 without decimals', () => { + const value = displayValueData(999999e15, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether({ displayDecimals: false })).toStrictEqual({ + displayValue: '999', + value: BigNumber(999.999) + }) + }) + }) + + describe('shorthand large values', () => { + it('should return a value of thousands to 3dp', () => { + const value = displayValueData(356253e17, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'thousand', + shortName: 'K', + }, + displayValue: '35.625', + value: BigNumber(35625.3) + }) + }) + + it('should round down a value of thousands to 3dp', () => { + const value = displayValueData(356259e17, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'thousand', + shortName: 'K', + }, + displayValue: '35.625', + value: BigNumber(35625.9) + }) + }) + + it('should return an exact value of thousands', () => { + const value = displayValueData(35e21, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'thousand', + shortName: 'K', + }, + displayValue: '35', + value: BigNumber(35000) + }) + }) + + it('should return a value of millions to 3dp', () => { + const value = displayValueData(356253e20, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'million', + shortName: 'M', + }, + displayValue: '35.625', + value: BigNumber(35625300) + }) + }) + + it('should round down a value of millions to 3dp', () => { + const value = displayValueData(356259e20, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'million', + shortName: 'M', + }, + displayValue: '35.625', + value: BigNumber(35625900) + }) + }) + + it('should return an exact value of millions', () => { + const value = displayValueData(35e24, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'million', + shortName: 'M', + }, + displayValue: '35', + value: BigNumber(35000000) + }) + }) + + it('should return a value of billions to 3dp', () => { + const value = displayValueData(356253e23, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'billion', + shortName: 'B', + }, + displayValue: '35.625', + value: BigNumber(35625300000) + }) + }) + + it('should round down a value of billions to 3dp', () => { + const value = displayValueData(356259e23, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'billion', + shortName: 'B', + }, + displayValue: '35.625', + value: BigNumber(35625900000) + }) + }) + + it('should return an exact value of billions', () => { + const value = displayValueData(35e27, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'billion', + shortName: 'B', + }, + displayValue: '35', + value: BigNumber(35000000000) + }) + }) + + it('should return a value of trillions to 3dp', () => { + const value = displayValueData(356253e26, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'trillion', + shortName: 'T', + }, + displayValue: '35.625', + value: BigNumber(35625300000000) + }) + }) + + it('should round down a value of trillions to 3dp', () => { + const value = displayValueData(356259e26, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'trillion', + shortName: 'T', + }, + displayValue: '35.625', + value: BigNumber(35625900000000) + }) + }) + + it('should return an exact value of trillions', () => { + const value = displayValueData(35e30, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'trillion', + shortName: 'T', + }, + displayValue: '35', + value: BigNumber(35000000000000) + }) + }) + + it('should return a value of quadrillions to 3dp', () => { + const value = displayValueData(356253e29, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'quadrillion', + shortName: 'Q', + }, + displayValue: '35.625', + value: BigNumber(35625300000000000) + }) + }) + + it('should round down a value of quadrillions to 3dp', () => { + const value = displayValueData(356259e29, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'quadrillion', + shortName: 'Q', + }, + displayValue: '35.625', + value: BigNumber(35625900000000000) + }) + }) + + it('should return an exact value of quadrillions', () => { + const value = displayValueData(35e33, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '', + displayUnit: { + fullName: 'quadrillion', + shortName: 'Q', + }, + displayValue: '35', + value: BigNumber(35000000000000000) + }) + }) + + it('should return a maximum value', () => { + const value = displayValueData(356e50, { currencyRate: { price: BigNumber(1) }}) + expect(value.ether()).toStrictEqual({ + approximationSymbol: '>', + displayUnit: { + fullName: 'quadrillion', + shortName: 'Q', + }, + displayValue: '999,999', + value: BigNumber(3.56e+34) + }) + }) + }) +}) + // it('should handle values smaller than the number of decimals requested', () => { // const value = displayValueData(356e-8, { decimalsOverride: 6 }) // expect(value.ether()).toStrictEqual({ @@ -306,82 +619,3 @@ describe('fiat currency', () => { // value: BigNumber(0) // }) // }) - -// it('should return a value of thousands', () => { -// const value = displayValueData(356e20) -// expect(value.ether()).toStrictEqual({ -// approximationSymbol: '', -// displayUnit: { -// fullName: 'thousand', -// shortName: 'K', -// }, -// displayValue: '35.6', -// value: BigNumber(35600) -// }) -// }) - -// it('should return a value of millions', () => { -// const value = displayValueData(356e23) -// expect(value.ether()).toStrictEqual({ -// approximationSymbol: '', -// displayUnit: { -// fullName: 'million', -// shortName: 'M', -// }, -// displayValue: '35.6', -// value: BigNumber(35600000) -// }) -// }) - -// it('should return a value of billions', () => { -// const value = displayValueData(356e26) -// expect(value.ether()).toStrictEqual({ -// approximationSymbol: '', -// displayUnit: { -// fullName: 'billion', -// shortName: 'B', -// }, -// displayValue: '35.6', -// value: BigNumber(35600000000) -// }) -// }) - -// it('should return a value of trillions', () => { -// const value = displayValueData(356e29) -// expect(value.ether()).toStrictEqual({ -// approximationSymbol: '', -// displayUnit: { -// fullName: 'trillion', -// shortName: 'T', -// }, -// displayValue: '35.6', -// value: BigNumber(35600000000000) -// }) -// }) - -// it('should return a value of quadrillions', () => { -// const value = displayValueData(356e32) -// expect(value.ether()).toStrictEqual({ -// approximationSymbol: '', -// displayUnit: { -// fullName: 'quadrillion', -// shortName: 'Q', -// }, -// displayValue: '35.6', -// value: BigNumber(35600000000000000) -// }) -// }) - -// it('should return a maximum value', () => { -// const value = displayValueData(356e50) -// expect(value.ether()).toStrictEqual({ -// approximationSymbol: '>', -// displayUnit: { -// fullName: 'quadrillion', -// shortName: 'Q', -// }, -// displayValue: '999,999', -// value: BigNumber(3.56e+34) -// }) -// }) -// }) From ee9556b7994a19413cbc7cf6755e3d5302bcdbe7 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 16 Nov 2022 04:06:22 +0000 Subject: [PATCH 36/50] remove currencyRates from ether tests --- test/resources/utils/displayValue.test.js | 56 ++++++++--------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/test/resources/utils/displayValue.test.js b/test/resources/utils/displayValue.test.js index 283faf5ce..58daebd52 100644 --- a/test/resources/utils/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -373,8 +373,8 @@ describe('ether currency', () => { }) describe('when not displaying decimals', () => { - it('should return a value of less than a dollar', () => { - const value = displayValueData(356e12, { currencyRate: { price: BigNumber(1) }}) + it('should return a value of less than 1', () => { + const value = displayValueData(356e12) expect(value.ether({ displayDecimals: false })).toStrictEqual({ approximationSymbol: '<', displayValue: '1', @@ -383,7 +383,7 @@ describe('ether currency', () => { }) it('should return a value less than 1000 without decimals', () => { - const value = displayValueData(999999e15, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(999999e15) expect(value.ether({ displayDecimals: false })).toStrictEqual({ displayValue: '999', value: BigNumber(999.999) @@ -393,7 +393,7 @@ describe('ether currency', () => { describe('shorthand large values', () => { it('should return a value of thousands to 3dp', () => { - const value = displayValueData(356253e17, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356253e17) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -406,7 +406,7 @@ describe('ether currency', () => { }) it('should round down a value of thousands to 3dp', () => { - const value = displayValueData(356259e17, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356259e17) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -419,7 +419,7 @@ describe('ether currency', () => { }) it('should return an exact value of thousands', () => { - const value = displayValueData(35e21, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(35e21) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -432,7 +432,7 @@ describe('ether currency', () => { }) it('should return a value of millions to 3dp', () => { - const value = displayValueData(356253e20, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356253e20) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -445,7 +445,7 @@ describe('ether currency', () => { }) it('should round down a value of millions to 3dp', () => { - const value = displayValueData(356259e20, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356259e20) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -458,7 +458,7 @@ describe('ether currency', () => { }) it('should return an exact value of millions', () => { - const value = displayValueData(35e24, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(35e24) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -471,7 +471,7 @@ describe('ether currency', () => { }) it('should return a value of billions to 3dp', () => { - const value = displayValueData(356253e23, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356253e23) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -484,7 +484,7 @@ describe('ether currency', () => { }) it('should round down a value of billions to 3dp', () => { - const value = displayValueData(356259e23, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356259e23) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -497,7 +497,7 @@ describe('ether currency', () => { }) it('should return an exact value of billions', () => { - const value = displayValueData(35e27, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(35e27) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -510,7 +510,7 @@ describe('ether currency', () => { }) it('should return a value of trillions to 3dp', () => { - const value = displayValueData(356253e26, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356253e26) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -523,7 +523,7 @@ describe('ether currency', () => { }) it('should round down a value of trillions to 3dp', () => { - const value = displayValueData(356259e26, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356259e26) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -536,7 +536,7 @@ describe('ether currency', () => { }) it('should return an exact value of trillions', () => { - const value = displayValueData(35e30, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(35e30) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -549,7 +549,7 @@ describe('ether currency', () => { }) it('should return a value of quadrillions to 3dp', () => { - const value = displayValueData(356253e29, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356253e29) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -562,7 +562,7 @@ describe('ether currency', () => { }) it('should round down a value of quadrillions to 3dp', () => { - const value = displayValueData(356259e29, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356259e29) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -575,7 +575,7 @@ describe('ether currency', () => { }) it('should return an exact value of quadrillions', () => { - const value = displayValueData(35e33, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(35e33) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { @@ -588,7 +588,7 @@ describe('ether currency', () => { }) it('should return a maximum value', () => { - const value = displayValueData(356e50, { currencyRate: { price: BigNumber(1) }}) + const value = displayValueData(356e50) expect(value.ether()).toStrictEqual({ approximationSymbol: '>', displayUnit: { @@ -601,21 +601,3 @@ describe('ether currency', () => { }) }) }) - -// it('should handle values smaller than the number of decimals requested', () => { -// const value = displayValueData(356e-8, { decimalsOverride: 6 }) -// expect(value.ether()).toStrictEqual({ -// approximationSymbol: '<', -// displayValue: '0.000001', -// value: BigNumber(0) -// }) -// }) // 999.0000111111 1203.0002231223 - -// it('should handle values smaller than the number of decimals requested', () => { -// const value = displayValueData((998.0000111111 * 1e18)) -// expect(value.ether()).toStrictEqual({ -// approximationSymbol: '<', -// displayValue: '0.000001', -// value: BigNumber(0) -// }) -// }) From 1d5f36ae6b016ba54c634b7cffc50a0328f11bd7 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 16 Nov 2022 12:04:30 +0000 Subject: [PATCH 37/50] fix decimals tests --- test/resources/Components/DisplayValue/index.test.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/resources/Components/DisplayValue/index.test.js b/test/resources/Components/DisplayValue/index.test.js index 3594de5f4..2f1e3e6ef 100644 --- a/test/resources/Components/DisplayValue/index.test.js +++ b/test/resources/Components/DisplayValue/index.test.js @@ -41,11 +41,11 @@ it('should render a fiat value', () => { expect(displayValue.textContent).toBe('$5.34T') }) -it('should override decimals on a fiat value', () => { - const { getByTestId } = setupComponent() +it('should not display decimals on a small fiat value when displayDecimals is set to false', () => { + const { getByTestId } = setupComponent() const displayValue = getByTestId('display-value') - expect(displayValue.textContent).toBe('$5.3T') + expect(displayValue.textContent).toBe('$5') }) it('should not render a shorthand unit when displayFullValue is specified on a fiat value', () => { @@ -62,11 +62,11 @@ it('should render an ether value', () => { expect(displayValue.textContent).toBe('ETH3.56T') }) -it('should override decimals on an ether value', () => { - const { getByTestId } = setupComponent() +it('should not display decimals on a small ether value when displayDecimals is set to false', () => { + const { getByTestId } = setupComponent() const displayValue = getByTestId('display-value') - expect(displayValue.textContent).toBe('ETH3.5673B') + expect(displayValue.textContent).toBe('ETH3') }) it('should not render a shorthand unit when displayFullValue is specified on an ether value', () => { From e45c19d4ed1d2800f9446b2084830a2561f5297c Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 16 Nov 2022 12:19:53 +0000 Subject: [PATCH 38/50] fix test --- .../Account/Requests/TransactionRequest/TxFeeNew/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js index 1082f2e6b..127236c66 100644 --- a/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js +++ b/app/App/Account/Account/Requests/TransactionRequest/TxFeeNew/index.js @@ -25,7 +25,7 @@ const GasDisplay = ({ maxFeePerGas }) => { } const USDEstimateDisplay = ({ minFee, maxFee, nativeCurrency }) => { - const { value: maxFeeValue, approximationSymbol: maxFeeApproximation } = maxFee.fiat(2) + const { value: maxFeeValue, approximationSymbol: maxFeeApproximation } = maxFee.fiat() const displayMaxFeeWarning = maxFeeValue > FEE_WARNING_THRESHOLD_USD return
From c86a870f2b0e054e85b3a721ce3a9613ea2ea9df Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 16 Nov 2022 13:26:43 +0000 Subject: [PATCH 39/50] try some updates --- package-lock.json | 1589 ++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 766 insertions(+), 829 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0437ae2b9..b016106c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -80,7 +80,7 @@ "@nomiclabs/hardhat-ethers": "^2.1.1", "@nomiclabs/hardhat-waffle": "2.0.3", "@sentry/types": "7.14.0", - "@testing-library/dom": "8.18.1", + "@testing-library/dom": "8.19.0", "@testing-library/react": "13.4.0", "@testing-library/user-event": "14.4.3", "@types/cookie": "0.5.1", @@ -100,8 +100,8 @@ "ethereum-waffle": "3.4.4", "ethers": "5.7.1", "hardhat": "2.11.2", - "jest": "29.1.1", - "jest-environment-jsdom": "29.1.1", + "jest": "29.3.1", + "jest-environment-jsdom": "29.3.1", "nock": "13.2.9", "node-abi": "3.25.0", "node-gyp": "9.1.0", @@ -4023,16 +4023,16 @@ } }, "node_modules/@jest/console": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.1.2.tgz", - "integrity": "sha512-ujEBCcYs82BTmRxqfHMQggSlkUZP63AE5YEaTPj7eFyJOzukkTorstOUC7L6nE3w5SYadGVAnTsQ/ZjTGL0qYQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.3.1.tgz", + "integrity": "sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==", "dev": true, "dependencies": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.1.2", - "jest-util": "^29.1.2", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", "slash": "^3.0.0" }, "engines": { @@ -4110,37 +4110,37 @@ } }, "node_modules/@jest/core": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.1.2.tgz", - "integrity": "sha512-sCO2Va1gikvQU2ynDN8V4+6wB7iVrD2CvT0zaRst4rglf56yLly0NQ9nuRRAWFeimRf+tCdFsb1Vk1N9LrrMPA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.3.1.tgz", + "integrity": "sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==", "dev": true, "dependencies": { - "@jest/console": "^29.1.2", - "@jest/reporters": "^29.1.2", - "@jest/test-result": "^29.1.2", - "@jest/transform": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/console": "^29.3.1", + "@jest/reporters": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.0.0", - "jest-config": "^29.1.2", - "jest-haste-map": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-regex-util": "^29.0.0", - "jest-resolve": "^29.1.2", - "jest-resolve-dependencies": "^29.1.2", - "jest-runner": "^29.1.2", - "jest-runtime": "^29.1.2", - "jest-snapshot": "^29.1.2", - "jest-util": "^29.1.2", - "jest-validate": "^29.1.2", - "jest-watcher": "^29.1.2", + "jest-changed-files": "^29.2.0", + "jest-config": "^29.3.1", + "jest-haste-map": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-resolve-dependencies": "^29.3.1", + "jest-runner": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", + "jest-watcher": "^29.3.1", "micromatch": "^4.0.4", - "pretty-format": "^29.1.2", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -4188,10 +4188,13 @@ } }, "node_modules/@jest/core/node_modules/ci-info": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", - "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", - "dev": true + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", + "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", + "dev": true, + "engines": { + "node": ">=8" + } }, "node_modules/@jest/core/node_modules/color-convert": { "version": "2.0.1", @@ -4221,9 +4224,9 @@ } }, "node_modules/@jest/core/node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -4265,88 +4268,88 @@ } }, "node_modules/@jest/environment": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.1.2.tgz", - "integrity": "sha512-rG7xZ2UeOfvOVzoLIJ0ZmvPl4tBEQ2n73CZJSlzUjPw4or1oSWC0s0Rk0ZX+pIBJ04aVr6hLWFn1DFtrnf8MhQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz", + "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", - "jest-mock": "^29.1.2" + "jest-mock": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.1.2.tgz", - "integrity": "sha512-FXw/UmaZsyfRyvZw3M6POgSNqwmuOXJuzdNiMWW9LCYo0GRoRDhg+R5iq5higmRTHQY7hx32+j7WHwinRmoILQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz", + "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==", "dev": true, "dependencies": { - "expect": "^29.1.2", - "jest-snapshot": "^29.1.2" + "expect": "^29.3.1", + "jest-snapshot": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.1.2.tgz", - "integrity": "sha512-4a48bhKfGj/KAH39u0ppzNTABXQ8QPccWAFUFobWBaEMSMp+sB31Z2fK/l47c4a/Mu1po2ffmfAIPxXbVTXdtg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz", + "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==", "dev": true, "dependencies": { - "jest-get-type": "^29.0.0" + "jest-get-type": "^29.2.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.1.2.tgz", - "integrity": "sha512-GppaEqS+QQYegedxVMpCe2xCXxxeYwQ7RsNx55zc8f+1q1qevkZGKequfTASI7ejmg9WwI+SJCrHe9X11bLL9Q==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz", + "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==", "dev": true, "dependencies": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", - "jest-message-util": "^29.1.2", - "jest-mock": "^29.1.2", - "jest-util": "^29.1.2" + "jest-message-util": "^29.3.1", + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.1.2.tgz", - "integrity": "sha512-uMgfERpJYoQmykAd0ffyMq8wignN4SvLUG6orJQRe9WAlTRc9cdpCaE/29qurXixYJVZWUqIBXhSk8v5xN1V9g==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz", + "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==", "dev": true, "dependencies": { - "@jest/environment": "^29.1.2", - "@jest/expect": "^29.1.2", - "@jest/types": "^29.1.2", - "jest-mock": "^29.1.2" + "@jest/environment": "^29.3.1", + "@jest/expect": "^29.3.1", + "@jest/types": "^29.3.1", + "jest-mock": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.1.2.tgz", - "integrity": "sha512-X4fiwwyxy9mnfpxL0g9DD0KcTmEIqP0jUdnc2cfa9riHy+I6Gwwp5vOZiwyg0vZxfSDxrOlK9S4+340W4d+DAA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.3.1.tgz", + "integrity": "sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.1.2", - "@jest/test-result": "^29.1.2", - "@jest/transform": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/console": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", @@ -4359,13 +4362,12 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.1.2", - "jest-util": "^29.1.2", - "jest-worker": "^29.1.2", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", + "jest-worker": "^29.3.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", - "terminal-link": "^2.0.0", "v8-to-istanbul": "^9.0.1" }, "engines": { @@ -4463,9 +4465,9 @@ } }, "node_modules/@jest/source-map": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.0.0.tgz", - "integrity": "sha512-nOr+0EM8GiHf34mq2GcJyz/gYFyLQ2INDhAylrZJ9mMWoW21mLBfZa0BUVPPMxVYrLjeiRe2Z7kWXOGnS0TFhQ==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz", + "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.15", @@ -4477,13 +4479,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.1.2.tgz", - "integrity": "sha512-jjYYjjumCJjH9hHCoMhA8PCl1OxNeGgAoZ7yuGYILRJX9NjgzTN0pCT5qAoYR4jfOP8htIByvAlz9vfNSSBoVg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.3.1.tgz", + "integrity": "sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==", "dev": true, "dependencies": { - "@jest/console": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/console": "^29.3.1", + "@jest/types": "^29.3.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -4492,14 +4494,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.1.2.tgz", - "integrity": "sha512-fU6dsUqqm8sA+cd85BmeF7Gu9DsXVWFdGn9taxM6xN1cKdcP/ivSgXh5QucFRFz1oZxKv3/9DYYbq0ULly3P/Q==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz", + "integrity": "sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==", "dev": true, "dependencies": { - "@jest/test-result": "^29.1.2", + "@jest/test-result": "^29.3.1", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.1.2", + "jest-haste-map": "^29.3.1", "slash": "^3.0.0" }, "engines": { @@ -4507,22 +4509,22 @@ } }, "node_modules/@jest/transform": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.1.2.tgz", - "integrity": "sha512-2uaUuVHTitmkx1tHF+eBjb4p7UuzBG7SXIaA/hNIkaMP6K+gXYGxP38ZcrofzqN0HeZ7A90oqsOa97WU7WZkSw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", + "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", + "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.1.2", - "jest-regex-util": "^29.0.0", - "jest-util": "^29.1.2", + "jest-haste-map": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-util": "^29.3.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -4581,6 +4583,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/@jest/transform/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -4603,9 +4611,9 @@ } }, "node_modules/@jest/types": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", - "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", + "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -7118,9 +7126,9 @@ } }, "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.5.tgz", + "integrity": "sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==", "dev": true, "dependencies": { "type-detect": "4.0.8" @@ -7161,9 +7169,9 @@ } }, "node_modules/@testing-library/dom": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.18.1.tgz", - "integrity": "sha512-oEvsm2B/WtcHKE+IcEeeCqNU/ltFGaVyGbpcm4g/2ytuT49jrlH9x5qRKL/H3A6yfM4YAbSbC0ceT5+9CEXnLg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz", + "integrity": "sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==", "dev": true, "dependencies": { "@babel/code-frame": "^7.10.4", @@ -7748,9 +7756,9 @@ "dev": true }, "node_modules/@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", + "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -9406,15 +9414,15 @@ } }, "node_modules/babel-jest": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.1.2.tgz", - "integrity": "sha512-IuG+F3HTHryJb7gacC7SQ59A9kO56BctUsT67uJHp1mMCHUOMXpDwOHWGifWqdWVknN2WNkCVQELPjXx0aLJ9Q==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz", + "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==", "dev": true, "dependencies": { - "@jest/transform": "^29.1.2", + "@jest/transform": "^29.3.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.0.2", + "babel-preset-jest": "^29.2.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -9530,9 +9538,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.0.2", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.0.2.tgz", - "integrity": "sha512-eBr2ynAEFjcebVvu8Ktx580BD1QKCrBG1XwEUTXJe285p9HA/4hOhfWCFRQhTKSyBV0VzjhG7H91Eifz9s29hg==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz", + "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -9634,12 +9642,12 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.0.2", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.0.2.tgz", - "integrity": "sha512-BeVXp7rH5TK96ofyEnHjznjLMQ2nAeDJ+QzxKnHAAMs0RgrQsCywjAN8m4mOm5Di0pxU//3AoEeJJrerMH5UeA==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz", + "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.0.2", + "babel-plugin-jest-hoist": "^29.2.0", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -12940,9 +12948,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.0.0.tgz", - "integrity": "sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", + "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -13645,9 +13653,9 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "node_modules/emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "engines": { "node": ">=12" @@ -15458,16 +15466,16 @@ } }, "node_modules/expect": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.1.2.tgz", - "integrity": "sha512-AuAGn1uxva5YBbBlXb+2JPxJRuemZsmlGcapPXWNSBNsQtAULfjioREGBWuI0EOvYUKjDnrCy8PW5Zlr1md5mw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz", + "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.1.2", - "jest-get-type": "^29.0.0", - "jest-matcher-utils": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-util": "^29.1.2" + "@jest/expect-utils": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -28539,15 +28547,15 @@ } }, "node_modules/jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.1.1.tgz", - "integrity": "sha512-Doe41PZ8MvGLtOZIW2RIVu94wa7jm/N775BBloVXk/G/vV6VYnDCOxBwrqekEgrd3Pn/bv8b5UdB2x0pAoQpwQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz", + "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==", "dev": true, "dependencies": { - "@jest/core": "^29.1.1", - "@jest/types": "^29.1.0", + "@jest/core": "^29.3.1", + "@jest/types": "^29.3.1", "import-local": "^3.0.2", - "jest-cli": "^29.1.1" + "jest-cli": "^29.3.1" }, "bin": { "jest": "bin/jest.js" @@ -28565,9 +28573,9 @@ } }, "node_modules/jest-changed-files": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.0.0.tgz", - "integrity": "sha512-28/iDMDrUpGoCitTURuDqUzWQoWmOmOKOFST1mi2lwh62X4BFf6khgH3uSuo1e49X/UDjuApAj3w0wLOex4VPQ==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz", + "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==", "dev": true, "dependencies": { "execa": "^5.0.0", @@ -28578,28 +28586,28 @@ } }, "node_modules/jest-circus": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.1.2.tgz", - "integrity": "sha512-ajQOdxY6mT9GtnfJRZBRYS7toNIJayiiyjDyoZcnvPRUPwJ58JX0ci0PKAKUo2C1RyzlHw0jabjLGKksO42JGA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.3.1.tgz", + "integrity": "sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==", "dev": true, "dependencies": { - "@jest/environment": "^29.1.2", - "@jest/expect": "^29.1.2", - "@jest/test-result": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/environment": "^29.3.1", + "@jest/expect": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.1.2", - "jest-matcher-utils": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-runtime": "^29.1.2", - "jest-snapshot": "^29.1.2", - "jest-util": "^29.1.2", + "jest-each": "^29.3.1", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", "p-limit": "^3.1.0", - "pretty-format": "^29.1.2", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -28666,9 +28674,9 @@ } }, "node_modules/jest-circus/node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -28710,21 +28718,21 @@ } }, "node_modules/jest-cli": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.1.2.tgz", - "integrity": "sha512-vsvBfQ7oS2o4MJdAH+4u9z76Vw5Q8WBQF5MchDbkylNknZdrPTX1Ix7YRJyTlOWqRaS7ue/cEAn+E4V1MWyMzw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.3.1.tgz", + "integrity": "sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==", "dev": true, "dependencies": { - "@jest/core": "^29.1.2", - "@jest/test-result": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/core": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.1.2", - "jest-util": "^29.1.2", - "jest-validate": "^29.1.2", + "jest-config": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -28828,9 +28836,9 @@ } }, "node_modules/jest-cli/node_modules/yargs": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", - "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", "dev": true, "dependencies": { "cliui": "^8.0.1", @@ -28839,7 +28847,7 @@ "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" @@ -28855,31 +28863,31 @@ } }, "node_modules/jest-config": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.1.2.tgz", - "integrity": "sha512-EC3Zi86HJUOz+2YWQcJYQXlf0zuBhJoeyxLM6vb6qJsVmpP7KcCP1JnyF0iaqTaXdBP8Rlwsvs7hnKWQWWLwwA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz", + "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.1.2", - "@jest/types": "^29.1.2", - "babel-jest": "^29.1.2", + "@jest/test-sequencer": "^29.3.1", + "@jest/types": "^29.3.1", + "babel-jest": "^29.3.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.1.2", - "jest-environment-node": "^29.1.2", - "jest-get-type": "^29.0.0", - "jest-regex-util": "^29.0.0", - "jest-resolve": "^29.1.2", - "jest-runner": "^29.1.2", - "jest-util": "^29.1.2", - "jest-validate": "^29.1.2", + "jest-circus": "^29.3.1", + "jest-environment-node": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-runner": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.1.2", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -28931,10 +28939,13 @@ } }, "node_modules/jest-config/node_modules/ci-info": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", - "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", - "dev": true + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", + "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", + "dev": true, + "engines": { + "node": ">=8" + } }, "node_modules/jest-config/node_modules/color-convert": { "version": "2.0.1", @@ -28964,9 +28975,9 @@ } }, "node_modules/jest-config/node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -29008,15 +29019,15 @@ } }, "node_modules/jest-diff": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.1.2.tgz", - "integrity": "sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", + "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.0.0", - "jest-get-type": "^29.0.0", - "pretty-format": "^29.1.2" + "diff-sequences": "^29.3.1", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -29081,9 +29092,9 @@ } }, "node_modules/jest-diff/node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -29125,9 +29136,9 @@ } }, "node_modules/jest-docblock": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.0.0.tgz", - "integrity": "sha512-s5Kpra/kLzbqu9dEjov30kj1n4tfu3e7Pl8v+f8jOkeWNqM6Ds8jRaJfZow3ducoQUrf2Z4rs2N5S3zXnb83gw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz", + "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" @@ -29137,16 +29148,16 @@ } }, "node_modules/jest-each": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.1.2.tgz", - "integrity": "sha512-AmTQp9b2etNeEwMyr4jc0Ql/LIX/dhbgP21gHAizya2X6rUspHn2gysMXaj6iwWuOJ2sYRgP8c1P4cXswgvS1A==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.3.1.tgz", + "integrity": "sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==", "dev": true, "dependencies": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "chalk": "^4.0.0", - "jest-get-type": "^29.0.0", - "jest-util": "^29.1.2", - "pretty-format": "^29.1.2" + "jest-get-type": "^29.2.0", + "jest-util": "^29.3.1", + "pretty-format": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -29211,9 +29222,9 @@ } }, "node_modules/jest-each/node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -29255,65 +29266,73 @@ } }, "node_modules/jest-environment-jsdom": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.1.1.tgz", - "integrity": "sha512-bXmOu26O4W/pszWgaUNCfFBMy8hqSz/SOcGKhqJ2ICYlNEUAXBk77eYkO57/Pmn9kNXVG18A8xwVQlZAzZzJ7Q==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.3.1.tgz", + "integrity": "sha512-G46nKgiez2Gy4zvYNhayfMEAFlVHhWfncqvqS6yCd0i+a4NsSUD2WtrKSaYQrYiLQaupHXxCRi8xxVL2M9PbhA==", "dev": true, "dependencies": { - "@jest/environment": "^29.1.1", - "@jest/fake-timers": "^29.1.1", - "@jest/types": "^29.1.0", + "@jest/environment": "^29.3.1", + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", "@types/jsdom": "^20.0.0", "@types/node": "*", - "jest-mock": "^29.1.1", - "jest-util": "^29.1.0", + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1", "jsdom": "^20.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, "node_modules/jest-environment-node": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.1.2.tgz", - "integrity": "sha512-C59yVbdpY8682u6k/lh8SUMDJPbOyCHOTgLVVi1USWFxtNV+J8fyIwzkg+RJIVI30EKhKiAGNxYaFr3z6eyNhQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.3.1.tgz", + "integrity": "sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==", "dev": true, "dependencies": { - "@jest/environment": "^29.1.2", - "@jest/fake-timers": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/environment": "^29.3.1", + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", - "jest-mock": "^29.1.2", - "jest-util": "^29.1.2" + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", - "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", + "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", - "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", + "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", "dev": true, "dependencies": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.0.0", - "jest-util": "^29.1.2", - "jest-worker": "^29.1.2", + "jest-regex-util": "^29.2.0", + "jest-util": "^29.3.1", + "jest-worker": "^29.3.1", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -29325,13 +29344,13 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.1.2.tgz", - "integrity": "sha512-TG5gAZJpgmZtjb6oWxBLf2N6CfQ73iwCe6cofu/Uqv9iiAm6g502CAnGtxQaTfpHECBdVEMRBhomSXeLnoKjiQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz", + "integrity": "sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==", "dev": true, "dependencies": { - "jest-get-type": "^29.0.0", - "pretty-format": "^29.1.2" + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -29350,9 +29369,9 @@ } }, "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -29370,15 +29389,15 @@ "dev": true }, "node_modules/jest-matcher-utils": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.1.2.tgz", - "integrity": "sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz", + "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.1.2", - "jest-get-type": "^29.0.0", - "pretty-format": "^29.1.2" + "jest-diff": "^29.3.1", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -29443,9 +29462,9 @@ } }, "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -29487,18 +29506,18 @@ } }, "node_modules/jest-message-util": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.1.2.tgz", - "integrity": "sha512-9oJ2Os+Qh6IlxLpmvshVbGUiSkZVc2FK+uGOm6tghafnB2RyjKAxMZhtxThRMxfX1J1SOMhTn9oK3/MutRWQJQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", + "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.1.2", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -29565,9 +29584,9 @@ } }, "node_modules/jest-message-util/node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -29609,23 +29628,23 @@ } }, "node_modules/jest-mock": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.1.2.tgz", - "integrity": "sha512-PFDAdjjWbjPUtQPkQufvniXIS3N9Tv7tbibePEjIIprzjgo0qQlyUiVMrT4vL8FaSJo1QXifQUOuPH3HQC/aMA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", "dev": true, "dependencies": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@types/node": "*", - "jest-util": "^29.1.2" + "jest-util": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "engines": { "node": ">=6" @@ -29640,26 +29659,26 @@ } }, "node_modules/jest-regex-util": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", - "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", + "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.1.2.tgz", - "integrity": "sha512-7fcOr+k7UYSVRJYhSmJHIid3AnDBcLQX3VmT9OSbPWsWz1MfT7bcoerMhADKGvKCoMpOHUQaDHtQoNp/P9JMGg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz", + "integrity": "sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.1.2", + "jest-haste-map": "^29.3.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.1.2", - "jest-validate": "^29.1.2", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" @@ -29669,13 +29688,13 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.1.2.tgz", - "integrity": "sha512-44yYi+yHqNmH3OoWZvPgmeeiwKxhKV/0CfrzaKLSkZG9gT973PX8i+m8j6pDrTYhhHoiKfF3YUFg/6AeuHw4HQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz", + "integrity": "sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==", "dev": true, "dependencies": { - "jest-regex-util": "^29.0.0", - "jest-snapshot": "^29.1.2" + "jest-regex-util": "^29.2.0", + "jest-snapshot": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -29752,30 +29771,30 @@ } }, "node_modules/jest-runner": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.1.2.tgz", - "integrity": "sha512-yy3LEWw8KuBCmg7sCGDIqKwJlULBuNIQa2eFSVgVASWdXbMYZ9H/X0tnXt70XFoGf92W2sOQDOIFAA6f2BG04Q==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.3.1.tgz", + "integrity": "sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==", "dev": true, "dependencies": { - "@jest/console": "^29.1.2", - "@jest/environment": "^29.1.2", - "@jest/test-result": "^29.1.2", - "@jest/transform": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/console": "^29.3.1", + "@jest/environment": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", - "emittery": "^0.10.2", + "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.0.0", - "jest-environment-node": "^29.1.2", - "jest-haste-map": "^29.1.2", - "jest-leak-detector": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-resolve": "^29.1.2", - "jest-runtime": "^29.1.2", - "jest-util": "^29.1.2", - "jest-watcher": "^29.1.2", - "jest-worker": "^29.1.2", + "jest-docblock": "^29.2.0", + "jest-environment-node": "^29.3.1", + "jest-haste-map": "^29.3.1", + "jest-leak-detector": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-resolve": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-util": "^29.3.1", + "jest-watcher": "^29.3.1", + "jest-worker": "^29.3.1", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -29864,31 +29883,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.1.2.tgz", - "integrity": "sha512-jr8VJLIf+cYc+8hbrpt412n5jX3tiXmpPSYTGnwcvNemY+EOuLNiYnHJ3Kp25rkaAcTWOEI4ZdOIQcwYcXIAZw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.1.2", - "@jest/fake-timers": "^29.1.2", - "@jest/globals": "^29.1.2", - "@jest/source-map": "^29.0.0", - "@jest/test-result": "^29.1.2", - "@jest/transform": "^29.1.2", - "@jest/types": "^29.1.2", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.3.1.tgz", + "integrity": "sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.3.1", + "@jest/fake-timers": "^29.3.1", + "@jest/globals": "^29.3.1", + "@jest/source-map": "^29.2.0", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-mock": "^29.1.2", - "jest-regex-util": "^29.0.0", - "jest-resolve": "^29.1.2", - "jest-snapshot": "^29.1.2", - "jest-util": "^29.1.2", + "jest-haste-map": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-mock": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -29967,9 +29986,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.1.2.tgz", - "integrity": "sha512-rYFomGpVMdBlfwTYxkUp3sjD6usptvZcONFYNqVlaz4EpHPnDvlWjvmOQ9OCSNKqYZqLM2aS3wq01tWujLg7gg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz", + "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -29978,23 +29997,23 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.1.2", - "@jest/transform": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/expect-utils": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.1.2", + "expect": "^29.3.1", "graceful-fs": "^4.2.9", - "jest-diff": "^29.1.2", - "jest-get-type": "^29.0.0", - "jest-haste-map": "^29.1.2", - "jest-matcher-utils": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-util": "^29.1.2", + "jest-diff": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-haste-map": "^29.3.1", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", "natural-compare": "^1.4.0", - "pretty-format": "^29.1.2", + "pretty-format": "^29.3.1", "semver": "^7.3.5" }, "engines": { @@ -30060,9 +30079,9 @@ } }, "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -30104,12 +30123,12 @@ } }, "node_modules/jest-util": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", - "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", + "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", "dev": true, "dependencies": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -30197,17 +30216,17 @@ } }, "node_modules/jest-validate": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", - "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.3.1.tgz", + "integrity": "sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==", "dev": true, "dependencies": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.0.0", + "jest-get-type": "^29.2.0", "leven": "^3.1.0", - "pretty-format": "^29.1.2" + "pretty-format": "^29.3.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -30284,9 +30303,9 @@ } }, "node_modules/jest-validate/node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -30328,18 +30347,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.1.2.tgz", - "integrity": "sha512-6JUIUKVdAvcxC6bM8/dMgqY2N4lbT+jZVsxh0hCJRbwkIEnbr/aPjMQ28fNDI5lB51Klh00MWZZeVf27KBUj5w==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.3.1.tgz", + "integrity": "sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==", "dev": true, "dependencies": { - "@jest/test-result": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^29.1.2", + "emittery": "^0.13.1", + "jest-util": "^29.3.1", "string-length": "^4.0.1" }, "engines": { @@ -30417,13 +30436,13 @@ } }, "node_modules/jest-worker": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", - "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", + "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.1.2", + "jest-util": "^29.3.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -39312,40 +39331,6 @@ "node": ">=4" } }, - "node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -39899,22 +39884,6 @@ "fs-extra": "^10.0.0" } }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/terser": { "version": "3.17.0", "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", @@ -45850,16 +45819,16 @@ "dev": true }, "@jest/console": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.1.2.tgz", - "integrity": "sha512-ujEBCcYs82BTmRxqfHMQggSlkUZP63AE5YEaTPj7eFyJOzukkTorstOUC7L6nE3w5SYadGVAnTsQ/ZjTGL0qYQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.3.1.tgz", + "integrity": "sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==", "dev": true, "requires": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.1.2", - "jest-util": "^29.1.2", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", "slash": "^3.0.0" }, "dependencies": { @@ -45915,37 +45884,37 @@ } }, "@jest/core": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.1.2.tgz", - "integrity": "sha512-sCO2Va1gikvQU2ynDN8V4+6wB7iVrD2CvT0zaRst4rglf56yLly0NQ9nuRRAWFeimRf+tCdFsb1Vk1N9LrrMPA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.3.1.tgz", + "integrity": "sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==", "dev": true, "requires": { - "@jest/console": "^29.1.2", - "@jest/reporters": "^29.1.2", - "@jest/test-result": "^29.1.2", - "@jest/transform": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/console": "^29.3.1", + "@jest/reporters": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.0.0", - "jest-config": "^29.1.2", - "jest-haste-map": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-regex-util": "^29.0.0", - "jest-resolve": "^29.1.2", - "jest-resolve-dependencies": "^29.1.2", - "jest-runner": "^29.1.2", - "jest-runtime": "^29.1.2", - "jest-snapshot": "^29.1.2", - "jest-util": "^29.1.2", - "jest-validate": "^29.1.2", - "jest-watcher": "^29.1.2", + "jest-changed-files": "^29.2.0", + "jest-config": "^29.3.1", + "jest-haste-map": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-resolve-dependencies": "^29.3.1", + "jest-runner": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", + "jest-watcher": "^29.3.1", "micromatch": "^4.0.4", - "pretty-format": "^29.1.2", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -45970,9 +45939,9 @@ } }, "ci-info": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", - "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", + "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", "dev": true }, "color-convert": { @@ -45997,9 +45966,9 @@ "dev": true }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -46033,73 +46002,73 @@ } }, "@jest/environment": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.1.2.tgz", - "integrity": "sha512-rG7xZ2UeOfvOVzoLIJ0ZmvPl4tBEQ2n73CZJSlzUjPw4or1oSWC0s0Rk0ZX+pIBJ04aVr6hLWFn1DFtrnf8MhQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz", + "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==", "dev": true, "requires": { - "@jest/fake-timers": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", - "jest-mock": "^29.1.2" + "jest-mock": "^29.3.1" } }, "@jest/expect": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.1.2.tgz", - "integrity": "sha512-FXw/UmaZsyfRyvZw3M6POgSNqwmuOXJuzdNiMWW9LCYo0GRoRDhg+R5iq5higmRTHQY7hx32+j7WHwinRmoILQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz", + "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==", "dev": true, "requires": { - "expect": "^29.1.2", - "jest-snapshot": "^29.1.2" + "expect": "^29.3.1", + "jest-snapshot": "^29.3.1" } }, "@jest/expect-utils": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.1.2.tgz", - "integrity": "sha512-4a48bhKfGj/KAH39u0ppzNTABXQ8QPccWAFUFobWBaEMSMp+sB31Z2fK/l47c4a/Mu1po2ffmfAIPxXbVTXdtg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz", + "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==", "dev": true, "requires": { - "jest-get-type": "^29.0.0" + "jest-get-type": "^29.2.0" } }, "@jest/fake-timers": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.1.2.tgz", - "integrity": "sha512-GppaEqS+QQYegedxVMpCe2xCXxxeYwQ7RsNx55zc8f+1q1qevkZGKequfTASI7ejmg9WwI+SJCrHe9X11bLL9Q==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz", + "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==", "dev": true, "requires": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", - "jest-message-util": "^29.1.2", - "jest-mock": "^29.1.2", - "jest-util": "^29.1.2" + "jest-message-util": "^29.3.1", + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1" } }, "@jest/globals": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.1.2.tgz", - "integrity": "sha512-uMgfERpJYoQmykAd0ffyMq8wignN4SvLUG6orJQRe9WAlTRc9cdpCaE/29qurXixYJVZWUqIBXhSk8v5xN1V9g==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz", + "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==", "dev": true, "requires": { - "@jest/environment": "^29.1.2", - "@jest/expect": "^29.1.2", - "@jest/types": "^29.1.2", - "jest-mock": "^29.1.2" + "@jest/environment": "^29.3.1", + "@jest/expect": "^29.3.1", + "@jest/types": "^29.3.1", + "jest-mock": "^29.3.1" } }, "@jest/reporters": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.1.2.tgz", - "integrity": "sha512-X4fiwwyxy9mnfpxL0g9DD0KcTmEIqP0jUdnc2cfa9riHy+I6Gwwp5vOZiwyg0vZxfSDxrOlK9S4+340W4d+DAA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.3.1.tgz", + "integrity": "sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.1.2", - "@jest/test-result": "^29.1.2", - "@jest/transform": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/console": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", @@ -46112,13 +46081,12 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.1.2", - "jest-util": "^29.1.2", - "jest-worker": "^29.1.2", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", + "jest-worker": "^29.3.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", - "terminal-link": "^2.0.0", "v8-to-istanbul": "^9.0.1" }, "dependencies": { @@ -46183,9 +46151,9 @@ } }, "@jest/source-map": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.0.0.tgz", - "integrity": "sha512-nOr+0EM8GiHf34mq2GcJyz/gYFyLQ2INDhAylrZJ9mMWoW21mLBfZa0BUVPPMxVYrLjeiRe2Z7kWXOGnS0TFhQ==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz", + "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.15", @@ -46194,46 +46162,46 @@ } }, "@jest/test-result": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.1.2.tgz", - "integrity": "sha512-jjYYjjumCJjH9hHCoMhA8PCl1OxNeGgAoZ7yuGYILRJX9NjgzTN0pCT5qAoYR4jfOP8htIByvAlz9vfNSSBoVg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.3.1.tgz", + "integrity": "sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==", "dev": true, "requires": { - "@jest/console": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/console": "^29.3.1", + "@jest/types": "^29.3.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.1.2.tgz", - "integrity": "sha512-fU6dsUqqm8sA+cd85BmeF7Gu9DsXVWFdGn9taxM6xN1cKdcP/ivSgXh5QucFRFz1oZxKv3/9DYYbq0ULly3P/Q==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz", + "integrity": "sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==", "dev": true, "requires": { - "@jest/test-result": "^29.1.2", + "@jest/test-result": "^29.3.1", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.1.2", + "jest-haste-map": "^29.3.1", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.1.2.tgz", - "integrity": "sha512-2uaUuVHTitmkx1tHF+eBjb4p7UuzBG7SXIaA/hNIkaMP6K+gXYGxP38ZcrofzqN0HeZ7A90oqsOa97WU7WZkSw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", + "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", + "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.1.2", - "jest-regex-util": "^29.0.0", - "jest-util": "^29.1.2", + "jest-haste-map": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-util": "^29.3.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -46274,6 +46242,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -46292,9 +46266,9 @@ } }, "@jest/types": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", - "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", + "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -48360,9 +48334,9 @@ "dev": true }, "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.5.tgz", + "integrity": "sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -48400,9 +48374,9 @@ } }, "@testing-library/dom": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.18.1.tgz", - "integrity": "sha512-oEvsm2B/WtcHKE+IcEeeCqNU/ltFGaVyGbpcm4g/2ytuT49jrlH9x5qRKL/H3A6yfM4YAbSbC0ceT5+9CEXnLg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz", + "integrity": "sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", @@ -48944,9 +48918,9 @@ "dev": true }, "@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", + "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -50381,15 +50355,15 @@ } }, "babel-jest": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.1.2.tgz", - "integrity": "sha512-IuG+F3HTHryJb7gacC7SQ59A9kO56BctUsT67uJHp1mMCHUOMXpDwOHWGifWqdWVknN2WNkCVQELPjXx0aLJ9Q==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz", + "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==", "dev": true, "requires": { - "@jest/transform": "^29.1.2", + "@jest/transform": "^29.3.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.0.2", + "babel-preset-jest": "^29.2.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -50477,9 +50451,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "29.0.2", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.0.2.tgz", - "integrity": "sha512-eBr2ynAEFjcebVvu8Ktx580BD1QKCrBG1XwEUTXJe285p9HA/4hOhfWCFRQhTKSyBV0VzjhG7H91Eifz9s29hg==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz", + "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -50565,12 +50539,12 @@ } }, "babel-preset-jest": { - "version": "29.0.2", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.0.2.tgz", - "integrity": "sha512-BeVXp7rH5TK96ofyEnHjznjLMQ2nAeDJ+QzxKnHAAMs0RgrQsCywjAN8m4mOm5Di0pxU//3AoEeJJrerMH5UeA==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz", + "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^29.0.2", + "babel-plugin-jest-hoist": "^29.2.0", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -53193,9 +53167,9 @@ "dev": true }, "diff-sequences": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.0.0.tgz", - "integrity": "sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", + "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", "dev": true }, "diffie-hellman": { @@ -53761,9 +53735,9 @@ } }, "emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true }, "emoji-regex": { @@ -55289,16 +55263,16 @@ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" }, "expect": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.1.2.tgz", - "integrity": "sha512-AuAGn1uxva5YBbBlXb+2JPxJRuemZsmlGcapPXWNSBNsQtAULfjioREGBWuI0EOvYUKjDnrCy8PW5Zlr1md5mw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz", + "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==", "dev": true, "requires": { - "@jest/expect-utils": "^29.1.2", - "jest-get-type": "^29.0.0", - "jest-matcher-utils": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-util": "^29.1.2" + "@jest/expect-utils": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1" } }, "express": { @@ -65333,21 +65307,21 @@ } }, "jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.1.1.tgz", - "integrity": "sha512-Doe41PZ8MvGLtOZIW2RIVu94wa7jm/N775BBloVXk/G/vV6VYnDCOxBwrqekEgrd3Pn/bv8b5UdB2x0pAoQpwQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz", + "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==", "dev": true, "requires": { - "@jest/core": "^29.1.1", - "@jest/types": "^29.1.0", + "@jest/core": "^29.3.1", + "@jest/types": "^29.3.1", "import-local": "^3.0.2", - "jest-cli": "^29.1.1" + "jest-cli": "^29.3.1" } }, "jest-changed-files": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.0.0.tgz", - "integrity": "sha512-28/iDMDrUpGoCitTURuDqUzWQoWmOmOKOFST1mi2lwh62X4BFf6khgH3uSuo1e49X/UDjuApAj3w0wLOex4VPQ==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz", + "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==", "dev": true, "requires": { "execa": "^5.0.0", @@ -65355,28 +65329,28 @@ } }, "jest-circus": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.1.2.tgz", - "integrity": "sha512-ajQOdxY6mT9GtnfJRZBRYS7toNIJayiiyjDyoZcnvPRUPwJ58JX0ci0PKAKUo2C1RyzlHw0jabjLGKksO42JGA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.3.1.tgz", + "integrity": "sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==", "dev": true, "requires": { - "@jest/environment": "^29.1.2", - "@jest/expect": "^29.1.2", - "@jest/test-result": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/environment": "^29.3.1", + "@jest/expect": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.1.2", - "jest-matcher-utils": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-runtime": "^29.1.2", - "jest-snapshot": "^29.1.2", - "jest-util": "^29.1.2", + "jest-each": "^29.3.1", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", "p-limit": "^3.1.0", - "pretty-format": "^29.1.2", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -65422,9 +65396,9 @@ "dev": true }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -65458,21 +65432,21 @@ } }, "jest-cli": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.1.2.tgz", - "integrity": "sha512-vsvBfQ7oS2o4MJdAH+4u9z76Vw5Q8WBQF5MchDbkylNknZdrPTX1Ix7YRJyTlOWqRaS7ue/cEAn+E4V1MWyMzw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.3.1.tgz", + "integrity": "sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==", "dev": true, "requires": { - "@jest/core": "^29.1.2", - "@jest/test-result": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/core": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.1.2", - "jest-util": "^29.1.2", - "jest-validate": "^29.1.2", + "jest-config": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -65538,9 +65512,9 @@ } }, "yargs": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", - "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", "dev": true, "requires": { "cliui": "^8.0.1", @@ -65549,7 +65523,7 @@ "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" } }, "yargs-parser": { @@ -65561,31 +65535,31 @@ } }, "jest-config": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.1.2.tgz", - "integrity": "sha512-EC3Zi86HJUOz+2YWQcJYQXlf0zuBhJoeyxLM6vb6qJsVmpP7KcCP1JnyF0iaqTaXdBP8Rlwsvs7hnKWQWWLwwA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz", + "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.1.2", - "@jest/types": "^29.1.2", - "babel-jest": "^29.1.2", + "@jest/test-sequencer": "^29.3.1", + "@jest/types": "^29.3.1", + "babel-jest": "^29.3.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.1.2", - "jest-environment-node": "^29.1.2", - "jest-get-type": "^29.0.0", - "jest-regex-util": "^29.0.0", - "jest-resolve": "^29.1.2", - "jest-runner": "^29.1.2", - "jest-util": "^29.1.2", - "jest-validate": "^29.1.2", + "jest-circus": "^29.3.1", + "jest-environment-node": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-runner": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.1.2", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -65610,9 +65584,9 @@ } }, "ci-info": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", - "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", + "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", "dev": true }, "color-convert": { @@ -65637,9 +65611,9 @@ "dev": true }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -65673,15 +65647,15 @@ } }, "jest-diff": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.1.2.tgz", - "integrity": "sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", + "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^29.0.0", - "jest-get-type": "^29.0.0", - "pretty-format": "^29.1.2" + "diff-sequences": "^29.3.1", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" }, "dependencies": { "ansi-styles": { @@ -65725,9 +65699,9 @@ "dev": true }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -65761,25 +65735,25 @@ } }, "jest-docblock": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.0.0.tgz", - "integrity": "sha512-s5Kpra/kLzbqu9dEjov30kj1n4tfu3e7Pl8v+f8jOkeWNqM6Ds8jRaJfZow3ducoQUrf2Z4rs2N5S3zXnb83gw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz", + "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.1.2.tgz", - "integrity": "sha512-AmTQp9b2etNeEwMyr4jc0Ql/LIX/dhbgP21gHAizya2X6rUspHn2gysMXaj6iwWuOJ2sYRgP8c1P4cXswgvS1A==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.3.1.tgz", + "integrity": "sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==", "dev": true, "requires": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "chalk": "^4.0.0", - "jest-get-type": "^29.0.0", - "jest-util": "^29.1.2", - "pretty-format": "^29.1.2" + "jest-get-type": "^29.2.0", + "jest-util": "^29.3.1", + "pretty-format": "^29.3.1" }, "dependencies": { "ansi-styles": { @@ -65823,9 +65797,9 @@ "dev": true }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -65859,69 +65833,69 @@ } }, "jest-environment-jsdom": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.1.1.tgz", - "integrity": "sha512-bXmOu26O4W/pszWgaUNCfFBMy8hqSz/SOcGKhqJ2ICYlNEUAXBk77eYkO57/Pmn9kNXVG18A8xwVQlZAzZzJ7Q==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.3.1.tgz", + "integrity": "sha512-G46nKgiez2Gy4zvYNhayfMEAFlVHhWfncqvqS6yCd0i+a4NsSUD2WtrKSaYQrYiLQaupHXxCRi8xxVL2M9PbhA==", "dev": true, "requires": { - "@jest/environment": "^29.1.1", - "@jest/fake-timers": "^29.1.1", - "@jest/types": "^29.1.0", + "@jest/environment": "^29.3.1", + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", "@types/jsdom": "^20.0.0", "@types/node": "*", - "jest-mock": "^29.1.1", - "jest-util": "^29.1.0", + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1", "jsdom": "^20.0.0" } }, "jest-environment-node": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.1.2.tgz", - "integrity": "sha512-C59yVbdpY8682u6k/lh8SUMDJPbOyCHOTgLVVi1USWFxtNV+J8fyIwzkg+RJIVI30EKhKiAGNxYaFr3z6eyNhQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.3.1.tgz", + "integrity": "sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==", "dev": true, "requires": { - "@jest/environment": "^29.1.2", - "@jest/fake-timers": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/environment": "^29.3.1", + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", - "jest-mock": "^29.1.2", - "jest-util": "^29.1.2" + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1" } }, "jest-get-type": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", - "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", + "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", "dev": true }, "jest-haste-map": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.1.2.tgz", - "integrity": "sha512-xSjbY8/BF11Jh3hGSPfYTa/qBFrm3TPM7WU8pU93m2gqzORVLkHFWvuZmFsTEBPRKndfewXhMOuzJNHyJIZGsw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", + "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", "dev": true, "requires": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.0.0", - "jest-util": "^29.1.2", - "jest-worker": "^29.1.2", + "jest-regex-util": "^29.2.0", + "jest-util": "^29.3.1", + "jest-worker": "^29.3.1", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "jest-leak-detector": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.1.2.tgz", - "integrity": "sha512-TG5gAZJpgmZtjb6oWxBLf2N6CfQ73iwCe6cofu/Uqv9iiAm6g502CAnGtxQaTfpHECBdVEMRBhomSXeLnoKjiQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz", + "integrity": "sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==", "dev": true, "requires": { - "jest-get-type": "^29.0.0", - "pretty-format": "^29.1.2" + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" }, "dependencies": { "ansi-styles": { @@ -65931,9 +65905,9 @@ "dev": true }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -65950,15 +65924,15 @@ } }, "jest-matcher-utils": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.1.2.tgz", - "integrity": "sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz", + "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.1.2", - "jest-get-type": "^29.0.0", - "pretty-format": "^29.1.2" + "jest-diff": "^29.3.1", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" }, "dependencies": { "ansi-styles": { @@ -66002,9 +65976,9 @@ "dev": true }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -66038,18 +66012,18 @@ } }, "jest-message-util": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.1.2.tgz", - "integrity": "sha512-9oJ2Os+Qh6IlxLpmvshVbGUiSkZVc2FK+uGOm6tghafnB2RyjKAxMZhtxThRMxfX1J1SOMhTn9oK3/MutRWQJQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", + "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.1.2", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -66095,9 +66069,9 @@ "dev": true }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -66131,41 +66105,41 @@ } }, "jest-mock": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.1.2.tgz", - "integrity": "sha512-PFDAdjjWbjPUtQPkQufvniXIS3N9Tv7tbibePEjIIprzjgo0qQlyUiVMrT4vL8FaSJo1QXifQUOuPH3HQC/aMA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", "dev": true, "requires": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@types/node": "*", - "jest-util": "^29.1.2" + "jest-util": "^29.3.1" } }, "jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "requires": {} }, "jest-regex-util": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.0.0.tgz", - "integrity": "sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", + "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", "dev": true }, "jest-resolve": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.1.2.tgz", - "integrity": "sha512-7fcOr+k7UYSVRJYhSmJHIid3AnDBcLQX3VmT9OSbPWsWz1MfT7bcoerMhADKGvKCoMpOHUQaDHtQoNp/P9JMGg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz", + "integrity": "sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.1.2", + "jest-haste-map": "^29.3.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.1.2", - "jest-validate": "^29.1.2", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" @@ -66223,40 +66197,40 @@ } }, "jest-resolve-dependencies": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.1.2.tgz", - "integrity": "sha512-44yYi+yHqNmH3OoWZvPgmeeiwKxhKV/0CfrzaKLSkZG9gT973PX8i+m8j6pDrTYhhHoiKfF3YUFg/6AeuHw4HQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz", + "integrity": "sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==", "dev": true, "requires": { - "jest-regex-util": "^29.0.0", - "jest-snapshot": "^29.1.2" + "jest-regex-util": "^29.2.0", + "jest-snapshot": "^29.3.1" } }, "jest-runner": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.1.2.tgz", - "integrity": "sha512-yy3LEWw8KuBCmg7sCGDIqKwJlULBuNIQa2eFSVgVASWdXbMYZ9H/X0tnXt70XFoGf92W2sOQDOIFAA6f2BG04Q==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.3.1.tgz", + "integrity": "sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==", "dev": true, "requires": { - "@jest/console": "^29.1.2", - "@jest/environment": "^29.1.2", - "@jest/test-result": "^29.1.2", - "@jest/transform": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/console": "^29.3.1", + "@jest/environment": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", - "emittery": "^0.10.2", + "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.0.0", - "jest-environment-node": "^29.1.2", - "jest-haste-map": "^29.1.2", - "jest-leak-detector": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-resolve": "^29.1.2", - "jest-runtime": "^29.1.2", - "jest-util": "^29.1.2", - "jest-watcher": "^29.1.2", - "jest-worker": "^29.1.2", + "jest-docblock": "^29.2.0", + "jest-environment-node": "^29.3.1", + "jest-haste-map": "^29.3.1", + "jest-leak-detector": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-resolve": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-util": "^29.3.1", + "jest-watcher": "^29.3.1", + "jest-worker": "^29.3.1", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -66323,31 +66297,31 @@ } }, "jest-runtime": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.1.2.tgz", - "integrity": "sha512-jr8VJLIf+cYc+8hbrpt412n5jX3tiXmpPSYTGnwcvNemY+EOuLNiYnHJ3Kp25rkaAcTWOEI4ZdOIQcwYcXIAZw==", - "dev": true, - "requires": { - "@jest/environment": "^29.1.2", - "@jest/fake-timers": "^29.1.2", - "@jest/globals": "^29.1.2", - "@jest/source-map": "^29.0.0", - "@jest/test-result": "^29.1.2", - "@jest/transform": "^29.1.2", - "@jest/types": "^29.1.2", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.3.1.tgz", + "integrity": "sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==", + "dev": true, + "requires": { + "@jest/environment": "^29.3.1", + "@jest/fake-timers": "^29.3.1", + "@jest/globals": "^29.3.1", + "@jest/source-map": "^29.2.0", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-mock": "^29.1.2", - "jest-regex-util": "^29.0.0", - "jest-resolve": "^29.1.2", - "jest-snapshot": "^29.1.2", - "jest-util": "^29.1.2", + "jest-haste-map": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-mock": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -66404,9 +66378,9 @@ } }, "jest-snapshot": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.1.2.tgz", - "integrity": "sha512-rYFomGpVMdBlfwTYxkUp3sjD6usptvZcONFYNqVlaz4EpHPnDvlWjvmOQ9OCSNKqYZqLM2aS3wq01tWujLg7gg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz", + "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -66415,23 +66389,23 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.1.2", - "@jest/transform": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/expect-utils": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.1.2", + "expect": "^29.3.1", "graceful-fs": "^4.2.9", - "jest-diff": "^29.1.2", - "jest-get-type": "^29.0.0", - "jest-haste-map": "^29.1.2", - "jest-matcher-utils": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-util": "^29.1.2", + "jest-diff": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-haste-map": "^29.3.1", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", "natural-compare": "^1.4.0", - "pretty-format": "^29.1.2", + "pretty-format": "^29.3.1", "semver": "^7.3.5" }, "dependencies": { @@ -66476,9 +66450,9 @@ "dev": true }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -66512,12 +66486,12 @@ } }, "jest-util": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", - "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", + "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", "dev": true, "requires": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -66583,17 +66557,17 @@ } }, "jest-validate": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.1.2.tgz", - "integrity": "sha512-k71pOslNlV8fVyI+mEySy2pq9KdXdgZtm7NHrBX8LghJayc3wWZH0Yr0mtYNGaCU4F1OLPXRkwZR0dBm/ClshA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.3.1.tgz", + "integrity": "sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==", "dev": true, "requires": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.3.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.0.0", + "jest-get-type": "^29.2.0", "leven": "^3.1.0", - "pretty-format": "^29.1.2" + "pretty-format": "^29.3.1" }, "dependencies": { "ansi-styles": { @@ -66643,9 +66617,9 @@ "dev": true }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -66679,18 +66653,18 @@ } }, "jest-watcher": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.1.2.tgz", - "integrity": "sha512-6JUIUKVdAvcxC6bM8/dMgqY2N4lbT+jZVsxh0hCJRbwkIEnbr/aPjMQ28fNDI5lB51Klh00MWZZeVf27KBUj5w==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.3.1.tgz", + "integrity": "sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==", "dev": true, "requires": { - "@jest/test-result": "^29.1.2", - "@jest/types": "^29.1.2", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^29.1.2", + "emittery": "^0.13.1", + "jest-util": "^29.3.1", "string-length": "^4.0.1" }, "dependencies": { @@ -66746,13 +66720,13 @@ } }, "jest-worker": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.1.2.tgz", - "integrity": "sha512-AdTZJxKjTSPHbXT/AIOjQVmoFx0LHFcVabWu0sxI7PAy7rFf8c0upyvgBKgguVXdM4vY74JdwkyD4hSmpTW8jA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", + "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.1.2", + "jest-util": "^29.3.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -73751,33 +73725,6 @@ "has-flag": "^3.0.0" } }, - "supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -74219,16 +74166,6 @@ "fs-extra": "^10.0.0" } }, - "terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - } - }, "terser": { "version": "3.17.0", "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", diff --git a/package.json b/package.json index cdf464932..83241da71 100644 --- a/package.json +++ b/package.json @@ -131,7 +131,7 @@ "@nomiclabs/hardhat-ethers": "^2.1.1", "@nomiclabs/hardhat-waffle": "2.0.3", "@sentry/types": "7.14.0", - "@testing-library/dom": "8.18.1", + "@testing-library/dom": "8.19.0", "@testing-library/react": "13.4.0", "@testing-library/user-event": "14.4.3", "@types/cookie": "0.5.1", @@ -151,8 +151,8 @@ "ethereum-waffle": "3.4.4", "ethers": "5.7.1", "hardhat": "2.11.2", - "jest": "29.1.1", - "jest-environment-jsdom": "29.1.1", + "jest": "29.3.1", + "jest-environment-jsdom": "29.3.1", "nock": "13.2.9", "node-abi": "3.25.0", "node-gyp": "9.1.0", From 121c787cbe2d822e7ba045a103d2f7109dab609f Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 16 Nov 2022 13:48:47 +0000 Subject: [PATCH 40/50] move test --- test/{resources => app}/Components/DisplayValue/index.test.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{resources => app}/Components/DisplayValue/index.test.js (100%) diff --git a/test/resources/Components/DisplayValue/index.test.js b/test/app/Components/DisplayValue/index.test.js similarity index 100% rename from test/resources/Components/DisplayValue/index.test.js rename to test/app/Components/DisplayValue/index.test.js From 75939dea8a9a17f7a2973fad7e073b085da903ca Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 16 Nov 2022 17:32:20 +0000 Subject: [PATCH 41/50] move resources Components tests --- test/{app => resources}/Components/Confirm/index.test.js | 0 test/{app => resources}/Components/DisplayValue/index.test.js | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/{app => resources}/Components/Confirm/index.test.js (100%) rename test/{app => resources}/Components/DisplayValue/index.test.js (100%) diff --git a/test/app/Components/Confirm/index.test.js b/test/resources/Components/Confirm/index.test.js similarity index 100% rename from test/app/Components/Confirm/index.test.js rename to test/resources/Components/Confirm/index.test.js diff --git a/test/app/Components/DisplayValue/index.test.js b/test/resources/Components/DisplayValue/index.test.js similarity index 100% rename from test/app/Components/DisplayValue/index.test.js rename to test/resources/Components/DisplayValue/index.test.js From 9203e66799db64080d7258072f1e47ab04363a42 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 16 Nov 2022 17:32:34 +0000 Subject: [PATCH 42/50] fix test invocation --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 83241da71..c8a2f6749 100644 --- a/package.json +++ b/package.json @@ -46,10 +46,10 @@ "test": "npm run compile && npm run test:unit && npm run test:e2e", "test:exec": "jest --detectOpenHandles --runInBand", "test:unit": "npm run test:unit:main && npm run test:unit:components && npm run test:unit:resources", - "test:unit:main": "npm run test:exec -- --env=node ./test/main", - "test:unit:resources": "npm run test:exec -- --env=node ./test/resources", - "test:unit:components": "npm run test:exec -- --env=jsdom --testTimeout=500 ./test/app", - "test:e2e": "npm run test:exec -- --env=node --config ./jest.e2e.config.json ./test/e2e", + "test:unit:main": "npm run test:exec -- --env=node --roots=test/main", + "test:unit:resources": "npm run test:exec -- --env=node --roots=test/resources --testPathIgnorePatterns=Components", + "test:unit:components": "npm run test:exec -- --env=jsdom --roots 'test/app' 'test/resources/Components' --testTimeout=500", + "test:e2e": "npm run test:exec -- --env=node --config ./jest.e2e.config.json --roots=test/e2e", "test:usbAdapters": "ELECTRON_RUN_AS_NODE=true ./node_modules/.bin/electron ./node_modules/jest/bin/jest.js ./test/main/signers/ledger/adapter.test.js --testPathIgnorePatterns=''", "standard": "standardx --fix --verbose", "local:rpc": "ganache-cli --account=\"0x2d6945dbddb8dcf5492004e6f720f8e971196ff61a61c4be99714ebc71e06c00, 5000000000000000000000\" --account=\"0xaef6a68a47c1628081e4e6df195f5f712ae4eb7da332a6d74dca06ae32a3e7ae,5000\"" From f11b3b6ae010c174301e2b0f6a54232a9f88e1ae Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Wed, 16 Nov 2022 17:42:02 +0000 Subject: [PATCH 43/50] revert non-resources / components change --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c8a2f6749..04484fcec 100644 --- a/package.json +++ b/package.json @@ -46,10 +46,10 @@ "test": "npm run compile && npm run test:unit && npm run test:e2e", "test:exec": "jest --detectOpenHandles --runInBand", "test:unit": "npm run test:unit:main && npm run test:unit:components && npm run test:unit:resources", - "test:unit:main": "npm run test:exec -- --env=node --roots=test/main", + "test:unit:main": "npm run test:exec -- --env=node ./test/main", "test:unit:resources": "npm run test:exec -- --env=node --roots=test/resources --testPathIgnorePatterns=Components", "test:unit:components": "npm run test:exec -- --env=jsdom --roots 'test/app' 'test/resources/Components' --testTimeout=500", - "test:e2e": "npm run test:exec -- --env=node --config ./jest.e2e.config.json --roots=test/e2e", + "test:e2e": "npm run test:exec -- --env=node --config ./jest.e2e.config.json ./test/e2e", "test:usbAdapters": "ELECTRON_RUN_AS_NODE=true ./node_modules/.bin/electron ./node_modules/jest/bin/jest.js ./test/main/signers/ledger/adapter.test.js --testPathIgnorePatterns=''", "standard": "standardx --fix --verbose", "local:rpc": "ganache-cli --account=\"0x2d6945dbddb8dcf5492004e6f720f8e971196ff61a61c4be99714ebc71e06c00, 5000000000000000000000\" --account=\"0xaef6a68a47c1628081e4e6df195f5f712ae4eb7da332a6d74dca06ae32a3e7ae,5000\"" From 893289728f0166f37302d484c84a7bccaae83b4b Mon Sep 17 00:00:00 2001 From: goosewobbler <432005+goosewobbler@users.noreply.github.com> Date: Wed, 16 Nov 2022 17:52:20 +0000 Subject: [PATCH 44/50] add NL --- test/resources/Components/DisplayValue/index.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/resources/Components/DisplayValue/index.test.js b/test/resources/Components/DisplayValue/index.test.js index 2f1e3e6ef..fb9280e51 100644 --- a/test/resources/Components/DisplayValue/index.test.js +++ b/test/resources/Components/DisplayValue/index.test.js @@ -74,4 +74,4 @@ it('should not render a shorthand unit when displayFullValue is specified on an const displayValue = getByTestId('display-value') expect(displayValue.textContent).toBe('ETH3,560,000,000,000') -}) \ No newline at end of file +}) From 00f984bd62f18b47c57871f63ec60ec666d551b0 Mon Sep 17 00:00:00 2001 From: Jordan Muir Date: Mon, 21 Nov 2022 06:27:16 -0900 Subject: [PATCH 45/50] Currency rework style (#1184) --- .../Account/Account/Balances/Balance/index.js | 9 +- .../Account/Account/Balances/style/index.styl | 18 ++-- resources/Components/DisplayValue/index.js | 85 ++++++++++++++++--- .../Components/DisplayValue/style/index.styl | 25 ++++++ resources/Components/index.styl | 1 + resources/utils/displayValue.ts | 45 +++++----- 6 files changed, 139 insertions(+), 44 deletions(-) create mode 100644 resources/Components/DisplayValue/style/index.styl diff --git a/app/App/Account/Account/Balances/Balance/index.js b/app/App/Account/Account/Balances/Balance/index.js index 4a8f13d83..60d8c3c51 100644 --- a/app/App/Account/Account/Balances/Balance/index.js +++ b/app/App/Account/Account/Balances/Balance/index.js @@ -52,8 +52,13 @@ class Balance extends React.Component {
{name}
-
= 12 ? { fontSize: '15px', top: '10px' } : {}}> - +
+
diff --git a/app/App/Account/Account/Balances/style/index.styl b/app/App/Account/Account/Balances/style/index.styl index 5e3032d72..fb22ed687 100644 --- a/app/App/Account/Account/Balances/style/index.styl +++ b/app/App/Account/Account/Balances/style/index.styl @@ -220,9 +220,9 @@ .signerBalanceCurrency position absolute left 62px - top 25px + top 26px right 135px - font-size 15px + font-size 14px display flex align-items center font-weight 400 @@ -339,25 +339,23 @@ .signerBalanceValue position absolute right 12px - top 23px - font-size 19px + top 24px + font-size 16px text-align center display flex align-items center font-family 'FiraCode' - letter-spacing -1px - font-weight 250 + font-weight 400 - .signerBalanceSymbol + .displayValueSymbol font-family 'MainFont' font-weight 500 - font-size 13px + font-size 0.75em line-height 13px position relative - top -0.5px letter-spacing 0.5px color var(--outerspace) - padding 3px 6px + padding 3px 4px border-radius 6px .signerBalanceEquivalent diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js index 95e6867c4..6131c31da 100644 --- a/resources/Components/DisplayValue/index.js +++ b/resources/Components/DisplayValue/index.js @@ -1,17 +1,82 @@ import React from 'react' import { displayValueData } from '../../utils/displayValue' -const CurrencySymbol = ({ symbol }) => {symbol} +const Approx = ({ approximationSymbol }) => { + return approximationSymbol && ( + + {approximationSymbol} + + ) +} + +const FiatSymbol = ({ fiatSymbol }) => { + return fiatSymbol && ( + + {fiatSymbol} + + ) +} + +const Symbol = ({ currencySymbol, show }) => { + return currencySymbol && show && ( + + {currencySymbol.toUpperCase()} + + ) +} + +const Main = ({ displayValue }) => { + return ( + + {displayValue} + + ) +} + +const Unit = ({ displayUnit }) => { + return displayUnit && ( + + {displayUnit.shortName} + + ) +} + +export const DisplayValue = props => { + + const { + value, + valueData, + valueDataParams, + currencySymbol, + type = 'ether', + displayDecimals = true, + currencySymbolPosition = 'first' + } = props -export const DisplayValue = ({ value, valueData, valueDataParams, currencySymbol, type = 'ether', displayDecimals = true, currencySymbolPosition = 'first' }) => { const data = valueData || displayValueData(value, valueDataParams) - const { approximationSymbol = '', displayValue, displayUnit } = data[type]({ displayDecimals }) + + const { + approximationSymbol = '', + displayValue, + displayUnit + } = data[type]({ displayDecimals }) - return
- {approximationSymbol && {approximationSymbol}} - {currencySymbol && currencySymbolPosition === 'first' && } - {displayValue} - {displayUnit && {displayUnit.shortName}} - {currencySymbol && currencySymbolPosition === 'last' && } -
+ return ( +
+ {type === 'fiat' ? ( + <> + + + + ) : ( + <> + + + + )} +
+ + +
+ ) } diff --git a/resources/Components/DisplayValue/style/index.styl b/resources/Components/DisplayValue/style/index.styl new file mode 100644 index 000000000..a6d5e3c45 --- /dev/null +++ b/resources/Components/DisplayValue/style/index.styl @@ -0,0 +1,25 @@ +.displayValue + display inline-flex + justify-content center + align-items center + + span + padding 0 + margin 0 + + .displayValueApprox + font-weight 600 + font-size 0.9em + + .displayValueFiat + font-weight 600 + font-size 0.8em + padding 0em 0.2em + + .displayValueSymbol + padding 0em 0.2em 0em 0.2em + font-family MainFont + + .displayValueUnit + font-weight 600 + padding 0em 0em 0em 0.2em diff --git a/resources/Components/index.styl b/resources/Components/index.styl index 8953aef7c..4f694e077 100644 --- a/resources/Components/index.styl +++ b/resources/Components/index.styl @@ -5,3 +5,4 @@ @import './FooterAux/style' @import './Gas/style' @import './Cluster/style' +@import './DisplayValue/style' diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index a0d65b45a..92c6a3851 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -2,35 +2,30 @@ import BigNumber from 'bignumber.js' import { isHexString } from 'ethers/lib/utils' const displayUnitMapping = { - thousand: { - lowerBound: BigNumber(999.99), - upperBound: BigNumber(999999.99), - unitDisplay: 'K' - }, million: { - lowerBound: BigNumber(999999.99), - upperBound: BigNumber(999999999.99), + lowerBound: BigNumber(1000000), + upperBound: BigNumber(1000000000), unitDisplay: 'M' }, billion: { - lowerBound: BigNumber(999999999.99), - upperBound: BigNumber(999999999999.99), + lowerBound: BigNumber(100000000), + upperBound: BigNumber(1000000000000), unitDisplay: 'B' }, trillion: { - lowerBound: BigNumber(999999999999.99), - upperBound: BigNumber(999999999999999).plus(0.99), // working around the 15sd limit + lowerBound: BigNumber(1000000000000), + upperBound: BigNumber(1000000000000000), unitDisplay: 'T' }, quadrillion: { - lowerBound: BigNumber(999999999999999).plus(0.99), // working around the 15sd limit + lowerBound: BigNumber(1000000000000000), upperBound: BigNumber(Infinity), unitDisplay: 'Q' } } const maxDisplayValue = BigNumber(999999999999999999999) -function getDisplay (bn: BigNumber, context: string, decimals: number, displayFullValue?: boolean) { +function getDisplay (bn: BigNumber, type: string, decimals: number, displayFullValue?: boolean) { const value = bn.decimalPlaces(decimals, BigNumber.ROUND_FLOOR) if (value.isZero()) { return { @@ -42,13 +37,12 @@ function getDisplay (bn: BigNumber, context: string, decimals: number, displayFu if (!displayFullValue) { // shorthand display of large numbers for (const [unitName, { lowerBound, upperBound, unitDisplay }] of Object.entries(displayUnitMapping)) { - if (value.isGreaterThan(lowerBound) && value.isLessThan(upperBound)) { + if (value.isGreaterThanOrEqualTo(lowerBound) && value.isLessThan(upperBound)) { const displayMax = value.isGreaterThan(maxDisplayValue) - // maximum display value is hard coded because maxDisplayValue is above the bignumber 15sd limit return { approximationSymbol: displayMax ? '>' : '', - displayValue: displayMax ? '999,999' : value.shiftedBy(-(lowerBound.sd(true) - 2)).decimalPlaces(3, BigNumber.ROUND_FLOOR).toFormat(), + displayValue: displayMax ? '999,999' : value.shiftedBy(-(lowerBound.sd(true) - 1)).decimalPlaces(2, BigNumber.ROUND_FLOOR).toFormat(), displayUnit: { fullName: unitName, shortName: unitDisplay @@ -60,7 +54,7 @@ function getDisplay (bn: BigNumber, context: string, decimals: number, displayFu // display small numbers or full values return { - displayValue: value.toFormat(context === 'fiat' ? decimals : undefined) + displayValue: value.toFormat(type === 'fiat' ? decimals : undefined) } } @@ -74,7 +68,14 @@ type DisplayValueDataParams = { type SourceValue = string | number | BigNumber export function displayValueData (sourceValue: SourceValue, params: DisplayValueDataParams) { - const { currencyRate, decimals = 18, isTestnet = false, displayFullValue = false } = params || {} as DisplayValueDataParams + + const { + currencyRate, + decimals = 18, + isTestnet = false, + displayFullValue = false + } = (params || {}) as DisplayValueDataParams + const bn = BigNumber(sourceValue, isHexString(sourceValue) ? 16 : undefined) const currencyHelperMap = { fiat: ({ displayDecimals } = { displayDecimals: true }) => { @@ -97,12 +98,12 @@ export function displayValueData (sourceValue: SourceValue, params: DisplayValue ether: ({ displayDecimals } = { displayDecimals: true }) => { const value = bn.shiftedBy(-decimals) const getDisplayedDecimals = () => { - if (!displayDecimals) { - return 0 - } + if (!displayDecimals) return 0 + const preDecimalStr = value.toFixed(1, BigNumber.ROUND_FLOOR).split('.')[0] const numNonDecimals = preDecimalStr === '0' ? 0 : preDecimalStr.length - return BigNumber(6).minus(BigNumber.min(3, BigNumber.min(6, numNonDecimals))).toNumber() + + return BigNumber(6).minus(BigNumber.min(6, BigNumber.min(6, numNonDecimals))).toNumber() } return { From b59f47a5225ffb7b32b602124e1c7dbcb40ab0e8 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Tue, 22 Nov 2022 11:17:30 +0000 Subject: [PATCH 46/50] fix tests --- resources/utils/displayValue.ts | 2 +- test/resources/utils/displayValue.test.js | 170 ++++++---------------- 2 files changed, 47 insertions(+), 125 deletions(-) diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index 92c6a3851..042ffb483 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -8,7 +8,7 @@ const displayUnitMapping = { unitDisplay: 'M' }, billion: { - lowerBound: BigNumber(100000000), + lowerBound: BigNumber(1000000000), upperBound: BigNumber(1000000000000), unitDisplay: 'B' }, diff --git a/test/resources/utils/displayValue.test.js b/test/resources/utils/displayValue.test.js index 58daebd52..ec3bc04c0 100644 --- a/test/resources/utils/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -77,46 +77,7 @@ describe('fiat currency', () => { }) describe('shorthand large values', () => { - it('should return a value of thousands to 3dp', () => { - const value = displayValueData(356253e17, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'thousand', - shortName: 'K', - }, - displayValue: '35.625', - value: BigNumber(35625.3) - }) - }) - - it('should round down a value of thousands to 3dp', () => { - const value = displayValueData(356259e17, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'thousand', - shortName: 'K', - }, - displayValue: '35.625', - value: BigNumber(35625.9) - }) - }) - - it('should return an exact value of thousands', () => { - const value = displayValueData(35e21, { currencyRate: { price: BigNumber(1) }}) - expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'thousand', - shortName: 'K', - }, - displayValue: '35', - value: BigNumber(35000) - }) - }) - - it('should return a value of millions to 3dp', () => { + it('should return a value of millions to 2dp', () => { const value = displayValueData(356253e20, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ approximationSymbol: '', @@ -124,12 +85,12 @@ describe('fiat currency', () => { fullName: 'million', shortName: 'M', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625300) }) }) - it('should round down a value of millions to 3dp', () => { + it('should round down a value of millions to 2dp', () => { const value = displayValueData(356259e20, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ approximationSymbol: '', @@ -137,7 +98,7 @@ describe('fiat currency', () => { fullName: 'million', shortName: 'M', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625900) }) }) @@ -155,28 +116,28 @@ describe('fiat currency', () => { }) }) - it('should return a value of billions to 3dp', () => { - const value = displayValueData(356253e23, { currencyRate: { price: BigNumber(1) }}) + it('should return a value of billions to 2dp', () => { + const value = displayValueData(35.6253e27, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625300000) }) }) - it('should round down a value of billions to 3dp', () => { - const value = displayValueData(356259e23, { currencyRate: { price: BigNumber(1) }}) + it('should round down a value of billions to 2dp', () => { + const value = displayValueData(35.6259e27, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625900000) }) }) @@ -194,28 +155,28 @@ describe('fiat currency', () => { }) }) - it('should return a value of trillions to 3dp', () => { - const value = displayValueData(356253e26, { currencyRate: { price: BigNumber(1) }}) + it('should return a value of trillions to 2dp', () => { + const value = displayValueData(35.6253e30, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625300000000) }) }) - it('should round down a value of trillions to 3dp', () => { - const value = displayValueData(356259e26, { currencyRate: { price: BigNumber(1) }}) + it('should round down a value of trillions to 2dp', () => { + const value = displayValueData(35.6259e30, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625900000000) }) }) @@ -233,28 +194,28 @@ describe('fiat currency', () => { }) }) - it('should return a value of quadrillions to 3dp', () => { - const value = displayValueData(356253e29, { currencyRate: { price: BigNumber(1) }}) + it('should return a value of quadrillions to 2dp', () => { + const value = displayValueData(35.6253e33, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625300000000000) }) }) - it('should round down a value of quadrillions to 3dp', () => { - const value = displayValueData(356259e29, { currencyRate: { price: BigNumber(1) }}) + it('should round down a value of quadrillions to 2dp', () => { + const value = displayValueData(35.6259e33, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625900000000000) }) }) @@ -392,67 +353,28 @@ describe('ether currency', () => { }) describe('shorthand large values', () => { - it('should return a value of thousands to 3dp', () => { - const value = displayValueData(356253e17) - expect(value.ether()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'thousand', - shortName: 'K', - }, - displayValue: '35.625', - value: BigNumber(35625.3) - }) - }) - - it('should round down a value of thousands to 3dp', () => { - const value = displayValueData(356259e17) - expect(value.ether()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'thousand', - shortName: 'K', - }, - displayValue: '35.625', - value: BigNumber(35625.9) - }) - }) - - it('should return an exact value of thousands', () => { - const value = displayValueData(35e21) - expect(value.ether()).toStrictEqual({ - approximationSymbol: '', - displayUnit: { - fullName: 'thousand', - shortName: 'K', - }, - displayValue: '35', - value: BigNumber(35000) - }) - }) - - it('should return a value of millions to 3dp', () => { - const value = displayValueData(356253e20) + it('should return a value of millions to 2dp', () => { + const value = displayValueData(35.6253e24) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'million', shortName: 'M', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625300) }) }) - it('should round down a value of millions to 3dp', () => { - const value = displayValueData(356259e20) + it('should round down a value of millions to 2dp', () => { + const value = displayValueData(35.6259e24) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'million', shortName: 'M', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625900) }) }) @@ -470,28 +392,28 @@ describe('ether currency', () => { }) }) - it('should return a value of billions to 3dp', () => { - const value = displayValueData(356253e23) + it('should return a value of billions to 2dp', () => { + const value = displayValueData(35.6253e27) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625300000) }) }) - it('should round down a value of billions to 3dp', () => { - const value = displayValueData(356259e23) + it('should round down a value of billions to 2dp', () => { + const value = displayValueData(35.6259e27) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625900000) }) }) @@ -509,28 +431,28 @@ describe('ether currency', () => { }) }) - it('should return a value of trillions to 3dp', () => { - const value = displayValueData(356253e26) + it('should return a value of trillions to 2dp', () => { + const value = displayValueData(35.6253e30) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625300000000) }) }) - it('should round down a value of trillions to 3dp', () => { - const value = displayValueData(356259e26) + it('should round down a value of trillions to 2dp', () => { + const value = displayValueData(35.6259e30) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625900000000) }) }) @@ -548,28 +470,28 @@ describe('ether currency', () => { }) }) - it('should return a value of quadrillions to 3dp', () => { - const value = displayValueData(356253e29) + it('should return a value of quadrillions to 2dp', () => { + const value = displayValueData(35.6253e33) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625300000000000) }) }) - it('should round down a value of quadrillions to 3dp', () => { - const value = displayValueData(356259e29) + it('should round down a value of quadrillions to 2dp', () => { + const value = displayValueData(35.6259e33) expect(value.ether()).toStrictEqual({ approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', }, - displayValue: '35.625', + displayValue: '35.62', value: BigNumber(35625900000000000) }) }) From f05d9cab683351022ae94d4e7fdf1da452eb86f0 Mon Sep 17 00:00:00 2001 From: Matt Holtzman Date: Tue, 29 Nov 2022 09:40:42 -0500 Subject: [PATCH 47/50] remove cap on max display value --- resources/utils/displayValue.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index 042ffb483..a18892936 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -3,27 +3,26 @@ import { isHexString } from 'ethers/lib/utils' const displayUnitMapping = { million: { - lowerBound: BigNumber(1000000), - upperBound: BigNumber(1000000000), + lowerBound: BigNumber('1000000'), + upperBound: BigNumber('1000000000'), unitDisplay: 'M' }, billion: { - lowerBound: BigNumber(1000000000), - upperBound: BigNumber(1000000000000), + lowerBound: BigNumber('1000000000'), + upperBound: BigNumber('1000000000000'), unitDisplay: 'B' }, trillion: { - lowerBound: BigNumber(1000000000000), - upperBound: BigNumber(1000000000000000), + lowerBound: BigNumber('1000000000000'), + upperBound: BigNumber('1000000000000000'), unitDisplay: 'T' }, quadrillion: { - lowerBound: BigNumber(1000000000000000), + lowerBound: BigNumber('1000000000000000'), upperBound: BigNumber(Infinity), unitDisplay: 'Q' } } -const maxDisplayValue = BigNumber(999999999999999999999) function getDisplay (bn: BigNumber, type: string, decimals: number, displayFullValue?: boolean) { const value = bn.decimalPlaces(decimals, BigNumber.ROUND_FLOOR) @@ -38,11 +37,8 @@ function getDisplay (bn: BigNumber, type: string, decimals: number, displayFullV // shorthand display of large numbers for (const [unitName, { lowerBound, upperBound, unitDisplay }] of Object.entries(displayUnitMapping)) { if (value.isGreaterThanOrEqualTo(lowerBound) && value.isLessThan(upperBound)) { - const displayMax = value.isGreaterThan(maxDisplayValue) - // maximum display value is hard coded because maxDisplayValue is above the bignumber 15sd limit return { - approximationSymbol: displayMax ? '>' : '', - displayValue: displayMax ? '999,999' : value.shiftedBy(-(lowerBound.sd(true) - 1)).decimalPlaces(2, BigNumber.ROUND_FLOOR).toFormat(), + displayValue: value.shiftedBy(-(lowerBound.sd(true) - 1)).decimalPlaces(2, BigNumber.ROUND_FLOOR).toFormat(), displayUnit: { fullName: unitName, shortName: unitDisplay From aee9f78a6295b72a29ad96b4276f9fdf0fe50a81 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Tue, 29 Nov 2022 19:30:03 +0000 Subject: [PATCH 48/50] address review comments --- resources/Components/DisplayValue/index.js | 74 ++++++++++------------ 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js index 6131c31da..584fca0b3 100644 --- a/resources/Components/DisplayValue/index.js +++ b/resources/Components/DisplayValue/index.js @@ -1,48 +1,38 @@ import React from 'react' import { displayValueData } from '../../utils/displayValue' -const Approx = ({ approximationSymbol }) => { - return approximationSymbol && ( - - {approximationSymbol} - - ) -} +const ApproximateValue = ({ approximationSymbol }) => ( + + {approximationSymbol} + +) -const FiatSymbol = ({ fiatSymbol }) => { - return fiatSymbol && ( - - {fiatSymbol} - - ) -} +const FiatSymbol = ({ fiatSymbol }) => ( + + {fiatSymbol} + +) -const Symbol = ({ currencySymbol, show }) => { - return currencySymbol && show && ( - - {currencySymbol.toUpperCase()} - - ) -} -const Main = ({ displayValue }) => { - return ( - - {displayValue} - - ) -} +const Symbol = ({ currencySymbol }) => ( + + {currencySymbol.toUpperCase()} + +) -const Unit = ({ displayUnit }) => { - return displayUnit && ( - - {displayUnit.shortName} - - ) -} +const Main = ({ displayValue }) => ( + + {displayValue} + +) -export const DisplayValue = props => { +const Unit = ({ displayUnit }) => ( + + {displayUnit.shortName} + +) +export const DisplayValue = (props) => { const { value, valueData, @@ -65,18 +55,18 @@ export const DisplayValue = props => {
{type === 'fiat' ? ( <> - - + {approximationSymbol && } + {currencySymbol && } ) : ( <> - - + {currencySymbol && currencySymbolPosition === 'first' && } + {approximationSymbol && } )}
- - + {displayUnit && } + {currencySymbol && currencySymbolPosition === 'last' && }
) } From d2a788de479bb2b0f230dccd6cf8099bd646073b Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Tue, 29 Nov 2022 20:05:24 +0000 Subject: [PATCH 49/50] create displayfiatprice wrapper --- app/App/Account/Account/Balances/Balance/index.js | 5 ++--- resources/Components/DisplayValue/index.js | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/App/Account/Account/Balances/Balance/index.js b/app/App/Account/Account/Balances/Balance/index.js index 60d8c3c51..7148753c0 100644 --- a/app/App/Account/Account/Balances/Balance/index.js +++ b/app/App/Account/Account/Balances/Balance/index.js @@ -1,9 +1,8 @@ import React from 'react' import Restore from 'react-restore' -import { DisplayValue } from '../../../../../../resources/Components/DisplayValue' +import { DisplayFiatPrice, DisplayValue } from '../../../../../../resources/Components/DisplayValue' import RingIcon from '../../../../../../resources/Components/RingIcon' -import svg from '../../../../../../resources/svg' class Balance extends React.Component { render () { @@ -63,7 +62,7 @@ class Balance extends React.Component {
- + {displayPriceChange()} diff --git a/resources/Components/DisplayValue/index.js b/resources/Components/DisplayValue/index.js index 584fca0b3..0ecef4042 100644 --- a/resources/Components/DisplayValue/index.js +++ b/resources/Components/DisplayValue/index.js @@ -32,6 +32,9 @@ const Unit = ({ displayUnit }) => ( ) +export const DisplayFiatPrice = ({ decimals, currencyRate, isTestnet }) => + + export const DisplayValue = (props) => { const { value, From a867780e837c3a8ebd882f721d549f49c9c43be2 Mon Sep 17 00:00:00 2001 From: goosewobbler Date: Tue, 29 Nov 2022 21:35:24 +0000 Subject: [PATCH 50/50] fix max display, min display, update tests --- resources/utils/displayValue.ts | 50 ++++++++++++++++------- test/resources/utils/displayValue.test.js | 24 ----------- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/resources/utils/displayValue.ts b/resources/utils/displayValue.ts index a18892936..9589a1834 100644 --- a/resources/utils/displayValue.ts +++ b/resources/utils/displayValue.ts @@ -19,13 +19,22 @@ const displayUnitMapping = { }, quadrillion: { lowerBound: BigNumber('1000000000000000'), - upperBound: BigNumber(Infinity), + upperBound: BigNumber('999999000000000000000'), unitDisplay: 'Q' } } +function isLargeNumber(bn: BigNumber) { + const largeNumberDisplayKeys = Object.keys(displayUnitMapping) + const firstLargeNumberDisplayKey = largeNumberDisplayKeys[0] + const firstLargeNumberDisplayValue = displayUnitMapping[firstLargeNumberDisplayKey as keyof typeof displayUnitMapping] + return bn.isGreaterThanOrEqualTo(firstLargeNumberDisplayValue.lowerBound) +} + function getDisplay (bn: BigNumber, type: string, decimals: number, displayFullValue?: boolean) { const value = bn.decimalPlaces(decimals, BigNumber.ROUND_FLOOR) + + // minimum display value if (value.isZero()) { return { approximationSymbol: '<', @@ -33,24 +42,37 @@ function getDisplay (bn: BigNumber, type: string, decimals: number, displayFullV } } - if (!displayFullValue) { - // shorthand display of large numbers - for (const [unitName, { lowerBound, upperBound, unitDisplay }] of Object.entries(displayUnitMapping)) { - if (value.isGreaterThanOrEqualTo(lowerBound) && value.isLessThan(upperBound)) { - return { - displayValue: value.shiftedBy(-(lowerBound.sd(true) - 1)).decimalPlaces(2, BigNumber.ROUND_FLOOR).toFormat(), - displayUnit: { - fullName: unitName, - shortName: unitDisplay - } + // small numbers + if (displayFullValue || !isLargeNumber(value)) { + return { + displayValue: value.toFormat(type === 'fiat' ? decimals : undefined) + } + } + + // shorthand display of large numbers + for (const [unitName, { lowerBound, upperBound, unitDisplay }] of Object.entries(displayUnitMapping)) { + if (value.isGreaterThanOrEqualTo(lowerBound) && value.isLessThan(upperBound)) { + return { + displayValue: value.shiftedBy(-(lowerBound.sd(true) - 1)).decimalPlaces(2, BigNumber.ROUND_FLOOR).toFormat(), + displayUnit: { + fullName: unitName, + shortName: unitDisplay } } } } - - // display small numbers or full values + + // maximum display value + const displayUnitKeys = Object.keys(displayUnitMapping) + const lastDisplayUnitKey = displayUnitKeys[displayUnitKeys.length - 1] + const lastDisplayUnitValue = displayUnitMapping[lastDisplayUnitKey as keyof typeof displayUnitMapping] return { - displayValue: value.toFormat(type === 'fiat' ? decimals : undefined) + approximationSymbol: '>', + displayValue: '999,999', + displayUnit: { + fullName: lastDisplayUnitKey, + shortName: lastDisplayUnitValue.unitDisplay + } } } diff --git a/test/resources/utils/displayValue.test.js b/test/resources/utils/displayValue.test.js index ec3bc04c0..af0fd86b7 100644 --- a/test/resources/utils/displayValue.test.js +++ b/test/resources/utils/displayValue.test.js @@ -80,7 +80,6 @@ describe('fiat currency', () => { it('should return a value of millions to 2dp', () => { const value = displayValueData(356253e20, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'million', shortName: 'M', @@ -93,7 +92,6 @@ describe('fiat currency', () => { it('should round down a value of millions to 2dp', () => { const value = displayValueData(356259e20, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'million', shortName: 'M', @@ -106,7 +104,6 @@ describe('fiat currency', () => { it('should return an exact value of millions', () => { const value = displayValueData(35e24, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'million', shortName: 'M', @@ -119,7 +116,6 @@ describe('fiat currency', () => { it('should return a value of billions to 2dp', () => { const value = displayValueData(35.6253e27, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', @@ -132,7 +128,6 @@ describe('fiat currency', () => { it('should round down a value of billions to 2dp', () => { const value = displayValueData(35.6259e27, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', @@ -145,7 +140,6 @@ describe('fiat currency', () => { it('should return an exact value of billions', () => { const value = displayValueData(35e27, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', @@ -158,7 +152,6 @@ describe('fiat currency', () => { it('should return a value of trillions to 2dp', () => { const value = displayValueData(35.6253e30, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', @@ -171,7 +164,6 @@ describe('fiat currency', () => { it('should round down a value of trillions to 2dp', () => { const value = displayValueData(35.6259e30, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', @@ -184,7 +176,6 @@ describe('fiat currency', () => { it('should return an exact value of trillions', () => { const value = displayValueData(35e30, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', @@ -197,7 +188,6 @@ describe('fiat currency', () => { it('should return a value of quadrillions to 2dp', () => { const value = displayValueData(35.6253e33, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', @@ -210,7 +200,6 @@ describe('fiat currency', () => { it('should round down a value of quadrillions to 2dp', () => { const value = displayValueData(35.6259e33, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', @@ -223,7 +212,6 @@ describe('fiat currency', () => { it('should return an exact value of quadrillions', () => { const value = displayValueData(35e33, { currencyRate: { price: BigNumber(1) }}) expect(value.fiat()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', @@ -356,7 +344,6 @@ describe('ether currency', () => { it('should return a value of millions to 2dp', () => { const value = displayValueData(35.6253e24) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'million', shortName: 'M', @@ -369,7 +356,6 @@ describe('ether currency', () => { it('should round down a value of millions to 2dp', () => { const value = displayValueData(35.6259e24) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'million', shortName: 'M', @@ -382,7 +368,6 @@ describe('ether currency', () => { it('should return an exact value of millions', () => { const value = displayValueData(35e24) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'million', shortName: 'M', @@ -395,7 +380,6 @@ describe('ether currency', () => { it('should return a value of billions to 2dp', () => { const value = displayValueData(35.6253e27) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', @@ -408,7 +392,6 @@ describe('ether currency', () => { it('should round down a value of billions to 2dp', () => { const value = displayValueData(35.6259e27) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', @@ -421,7 +404,6 @@ describe('ether currency', () => { it('should return an exact value of billions', () => { const value = displayValueData(35e27) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'billion', shortName: 'B', @@ -434,7 +416,6 @@ describe('ether currency', () => { it('should return a value of trillions to 2dp', () => { const value = displayValueData(35.6253e30) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', @@ -447,7 +428,6 @@ describe('ether currency', () => { it('should round down a value of trillions to 2dp', () => { const value = displayValueData(35.6259e30) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', @@ -460,7 +440,6 @@ describe('ether currency', () => { it('should return an exact value of trillions', () => { const value = displayValueData(35e30) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'trillion', shortName: 'T', @@ -473,7 +452,6 @@ describe('ether currency', () => { it('should return a value of quadrillions to 2dp', () => { const value = displayValueData(35.6253e33) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', @@ -486,7 +464,6 @@ describe('ether currency', () => { it('should round down a value of quadrillions to 2dp', () => { const value = displayValueData(35.6259e33) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q', @@ -499,7 +476,6 @@ describe('ether currency', () => { it('should return an exact value of quadrillions', () => { const value = displayValueData(35e33) expect(value.ether()).toStrictEqual({ - approximationSymbol: '', displayUnit: { fullName: 'quadrillion', shortName: 'Q',