Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
interface
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
LuckySwap
interface
Commits
91c20135
Unverified
Commit
91c20135
authored
Sep 18, 2023
by
Jack Short
Committed by
GitHub
Sep 18, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: only exposing useFormatter (#7308)
parent
cf09e809
Changes
17
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
681 additions
and
624 deletions
+681
-624
hooks.ts
src/components/AccountDrawer/MiniPortfolio/Activity/hooks.ts
+6
-1
parseLocal.test.ts
...s/AccountDrawer/MiniPortfolio/Activity/parseLocal.test.ts
+16
-5
parseLocal.ts
...onents/AccountDrawer/MiniPortfolio/Activity/parseLocal.ts
+54
-25
parseRemote.tsx
...ents/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx
+51
-23
SuggestionRow.tsx
src/components/NavBar/SuggestionRow.tsx
+3
-2
PopupContent.tsx
src/components/Popups/PopupContent.tsx
+5
-2
index.tsx
src/components/PositionListItem/index.tsx
+3
-1
index.tsx
src/components/PositionPreview/index.tsx
+2
-1
PriceChart.tsx
src/components/Tokens/TokenDetails/PriceChart.tsx
+4
-3
TokenRow.tsx
src/components/Tokens/TokenTable/TokenRow.tsx
+3
-3
SwapModalFooter.tsx
src/components/swap/SwapModalFooter.tsx
+1
-2
SwapModalHeader.test.tsx
src/components/swap/SwapModalHeader.test.tsx
+6
-31
CarouselCard.tsx
src/nft/components/explore/CarouselCard.tsx
+4
-2
PositionPage.tsx
src/pages/Pool/PositionPage.tsx
+1
-1
formatNumbers.test.ts
src/utils/formatNumbers.test.ts
+398
-460
formatNumbers.ts
src/utils/formatNumbers.ts
+124
-38
formatTickPrice.ts
src/utils/formatTickPrice.ts
+0
-24
No files found.
src/components/AccountDrawer/MiniPortfolio/Activity/hooks.ts
View file @
91c20135
...
...
@@ -2,6 +2,7 @@ import { TransactionStatus, useActivityQuery } from 'graphql/data/__generated__/
import
{
useEffect
,
useMemo
}
from
'
react
'
import
{
usePendingOrders
}
from
'
state/signatures/hooks
'
import
{
usePendingTransactions
,
useTransactionCanceller
}
from
'
state/transactions/hooks
'
import
{
useFormatter
}
from
'
utils/formatNumbers
'
import
{
useLocalActivities
}
from
'
./parseLocal
'
import
{
parseRemoteActivities
}
from
'
./parseRemote
'
...
...
@@ -55,6 +56,7 @@ function combineActivities(localMap: ActivityMap = {}, remoteMap: ActivityMap =
}
export
function
useAllActivities
(
account
:
string
)
{
const
{
formatNumberOrString
}
=
useFormatter
()
const
{
data
,
loading
,
refetch
}
=
useActivityQuery
({
variables
:
{
account
},
errorPolicy
:
'
all
'
,
...
...
@@ -62,7 +64,10 @@ export function useAllActivities(account: string) {
})
const
localMap
=
useLocalActivities
(
account
)
const
remoteMap
=
useMemo
(()
=>
parseRemoteActivities
(
data
?.
portfolios
?.[
0
].
assetActivities
),
[
data
?.
portfolios
])
const
remoteMap
=
useMemo
(
()
=>
parseRemoteActivities
(
formatNumberOrString
,
data
?.
portfolios
?.[
0
].
assetActivities
),
[
data
?.
portfolios
,
formatNumberOrString
]
)
const
updateCancelledTx
=
useTransactionCanceller
()
/* Updates locally stored pendings tx's when remote data contains a conflicting cancellation tx */
...
...
src/components/AccountDrawer/MiniPortfolio/Activity/parseLocal.test.ts
View file @
91c20135
...
...
@@ -11,6 +11,7 @@ import {
TransactionType
as
MockTxType
,
}
from
'
state/transactions/types
'
import
{
renderHook
}
from
'
test-utils/render
'
import
{
useFormatter
}
from
'
utils/formatNumbers
'
import
{
UniswapXOrderStatus
}
from
'
../../../../lib/hooks/orders/types
'
import
{
SignatureDetails
,
SignatureType
}
from
'
../../../../state/signatures/types
'
...
...
@@ -237,6 +238,8 @@ jest.mock('../../../../state/transactions/hooks', () => {
describe
(
'
parseLocalActivity
'
,
()
=>
{
it
(
'
returns swap activity fields with known tokens, exact input
'
,
()
=>
{
const
{
formatNumber
}
=
renderHook
(()
=>
useFormatter
()).
result
.
current
const
details
=
{
info
:
mockSwapInfo
(
MockTradeType
.
EXACT_INPUT
,
...
...
@@ -251,7 +254,7 @@ describe('parseLocalActivity', () => {
},
}
as
TransactionDetails
const
chainId
=
ChainId
.
MAINNET
expect
(
transactionToActivity
(
details
,
chainId
,
mockTokenAddressMap
)).
toEqual
({
expect
(
transactionToActivity
(
details
,
chainId
,
mockTokenAddressMap
,
formatNumber
)).
toEqual
({
chainId
:
1
,
currencies
:
[
MockUSDC_MAINNET
,
MockDAI
],
descriptor
:
'
1.00 USDC for 1.00 DAI
'
,
...
...
@@ -264,6 +267,8 @@ describe('parseLocalActivity', () => {
})
it
(
'
returns swap activity fields with known tokens, exact output
'
,
()
=>
{
const
{
formatNumber
}
=
renderHook
(()
=>
useFormatter
()).
result
.
current
const
details
=
{
info
:
mockSwapInfo
(
MockTradeType
.
EXACT_OUTPUT
,
...
...
@@ -278,7 +283,7 @@ describe('parseLocalActivity', () => {
},
}
as
TransactionDetails
const
chainId
=
ChainId
.
MAINNET
expect
(
transactionToActivity
(
details
,
chainId
,
mockTokenAddressMap
)).
toMatchObject
({
expect
(
transactionToActivity
(
details
,
chainId
,
mockTokenAddressMap
,
formatNumber
)).
toMatchObject
({
chainId
:
1
,
currencies
:
[
MockUSDC_MAINNET
,
MockDAI
],
descriptor
:
'
1.00 USDC for 1.00 DAI
'
,
...
...
@@ -288,6 +293,8 @@ describe('parseLocalActivity', () => {
})
it
(
'
returns swap activity fields with unknown tokens
'
,
()
=>
{
const
{
formatNumber
}
=
renderHook
(()
=>
useFormatter
()).
result
.
current
const
details
=
{
info
:
mockSwapInfo
(
MockTradeType
.
EXACT_INPUT
,
...
...
@@ -303,7 +310,7 @@ describe('parseLocalActivity', () => {
}
as
TransactionDetails
const
chainId
=
ChainId
.
MAINNET
const
tokens
=
{}
as
ChainTokenMap
expect
(
transactionToActivity
(
details
,
chainId
,
tokens
)).
toMatchObject
({
expect
(
transactionToActivity
(
details
,
chainId
,
tokens
,
formatNumber
)).
toMatchObject
({
chainId
:
1
,
currencies
:
[
undefined
,
undefined
],
descriptor
:
'
Unknown for Unknown
'
,
...
...
@@ -496,13 +503,16 @@ describe('parseLocalActivity', () => {
})
it
(
'
Signature to activity - returns undefined if is on chain order
'
,
()
=>
{
const
{
formatNumber
}
=
renderHook
(()
=>
useFormatter
()).
result
.
current
expect
(
signatureToActivity
(
{
type
:
SignatureType
.
SIGN_UNISWAPX_ORDER
,
status
:
UniswapXOrderStatus
.
FILLED
,
}
as
SignatureDetails
,
{}
{},
formatNumber
)
).
toBeUndefined
()
...
...
@@ -512,7 +522,8 @@ describe('parseLocalActivity', () => {
type
:
SignatureType
.
SIGN_UNISWAPX_ORDER
,
status
:
UniswapXOrderStatus
.
CANCELLED
,
}
as
SignatureDetails
,
{}
{},
formatNumber
)
).
toBeUndefined
()
})
...
...
src/components/AccountDrawer/MiniPortfolio/Activity/parseLocal.ts
View file @
91c20135
...
...
@@ -2,7 +2,6 @@ import { BigNumber } from '@ethersproject/bignumber'
import
{
t
}
from
'
@lingui/macro
'
import
{
ChainId
,
Currency
,
CurrencyAmount
,
TradeType
}
from
'
@uniswap/sdk-core
'
import
UniswapXBolt
from
'
assets/svg/bolt.svg
'
import
{
SupportedLocale
}
from
'
constants/locales
'
import
{
nativeOnChain
}
from
'
constants/tokens
'
import
{
TransactionStatus
}
from
'
graphql/data/__generated__/types-and-hooks
'
import
{
ChainTokenMap
,
useAllTokensMultichain
}
from
'
hooks/Tokens
'
...
...
@@ -24,11 +23,13 @@ import {
TransactionType
,
WrapTransactionInfo
,
}
from
'
state/transactions/types
'
import
{
formatCurrencyAmount
,
useFormatterLocales
}
from
'
utils/formatNumbers
'
import
{
NumberType
,
useFormatter
}
from
'
utils/formatNumbers
'
import
{
CancelledTransactionTitleTable
,
getActivityTitle
,
OrderTextTable
}
from
'
../constants
'
import
{
Activity
,
ActivityMap
}
from
'
./types
'
type
FormatNumberFunctionType
=
ReturnType
<
typeof
useFormatter
>
[
'
formatNumber
'
]
function
getCurrency
(
currencyId
:
string
,
chainId
:
ChainId
,
tokens
:
ChainTokenMap
):
Currency
|
undefined
{
return
currencyId
===
'
ETH
'
?
nativeOnChain
(
chainId
)
:
tokens
[
chainId
]?.[
currencyId
]
}
...
...
@@ -38,15 +39,21 @@ function buildCurrencyDescriptor(
amtA
:
string
,
currencyB
:
Currency
|
undefined
,
amtB
:
string
,
delimiter
=
t
`for`
,
locale
?:
SupportedLocale
formatNumber
:
FormatNumberFunctionType
,
delimiter
=
t
`for`
)
{
const
formattedA
=
currencyA
?
formatCurrencyAmount
({
amount
:
CurrencyAmount
.
fromRawAmount
(
currencyA
,
amtA
),
locale
})
?
formatNumber
({
input
:
parseFloat
(
CurrencyAmount
.
fromRawAmount
(
currencyA
,
amtA
).
toSignificant
()),
type
:
NumberType
.
TokenNonTx
,
})
:
t
`Unknown`
const
symbolA
=
currencyA
?.
symbol
??
''
const
formattedB
=
currencyB
?
formatCurrencyAmount
({
amount
:
CurrencyAmount
.
fromRawAmount
(
currencyB
,
amtB
),
locale
})
?
formatNumber
({
input
:
parseFloat
(
CurrencyAmount
.
fromRawAmount
(
currencyB
,
amtB
).
toSignificant
()),
type
:
NumberType
.
TokenNonTx
,
})
:
t
`Unknown`
const
symbolB
=
currencyB
?.
symbol
??
''
return
[
formattedA
,
symbolA
,
delimiter
,
formattedB
,
symbolB
].
filter
(
Boolean
).
join
(
'
'
)
...
...
@@ -56,7 +63,7 @@ function parseSwap(
swap
:
ExactInputSwapTransactionInfo
|
ExactOutputSwapTransactionInfo
,
chainId
:
ChainId
,
tokens
:
ChainTokenMap
,
locale
?:
SupportedLocal
e
formatNumber
:
FormatNumberFunctionTyp
e
):
Partial
<
Activity
>
{
const
tokenIn
=
getCurrency
(
swap
.
inputCurrencyId
,
chainId
,
tokens
)
const
tokenOut
=
getCurrency
(
swap
.
outputCurrencyId
,
chainId
,
tokens
)
...
...
@@ -66,18 +73,29 @@ function parseSwap(
:
[
swap
.
expectedInputCurrencyAmountRaw
,
swap
.
outputCurrencyAmountRaw
]
return
{
descriptor
:
buildCurrencyDescriptor
(
tokenIn
,
inputRaw
,
tokenOut
,
outputRaw
,
undefined
,
locale
),
descriptor
:
buildCurrencyDescriptor
(
tokenIn
,
inputRaw
,
tokenOut
,
outputRaw
,
formatNumber
,
undefined
),
currencies
:
[
tokenIn
,
tokenOut
],
prefixIconSrc
:
swap
.
isUniswapXOrder
?
UniswapXBolt
:
undefined
,
}
}
function
parseWrap
(
wrap
:
WrapTransactionInfo
,
chainId
:
ChainId
,
status
:
TransactionStatus
):
Partial
<
Activity
>
{
function
parseWrap
(
wrap
:
WrapTransactionInfo
,
chainId
:
ChainId
,
status
:
TransactionStatus
,
formatNumber
:
FormatNumberFunctionType
):
Partial
<
Activity
>
{
const
native
=
nativeOnChain
(
chainId
)
const
wrapped
=
native
.
wrapped
const
[
input
,
output
]
=
wrap
.
unwrapped
?
[
wrapped
,
native
]
:
[
native
,
wrapped
]
const
descriptor
=
buildCurrencyDescriptor
(
input
,
wrap
.
currencyAmountRaw
,
output
,
wrap
.
currencyAmountRaw
)
const
descriptor
=
buildCurrencyDescriptor
(
input
,
wrap
.
currencyAmountRaw
,
output
,
wrap
.
currencyAmountRaw
,
formatNumber
)
const
title
=
getActivityTitle
(
TransactionType
.
WRAP
,
status
,
wrap
.
unwrapped
)
const
currencies
=
wrap
.
unwrapped
?
[
wrapped
,
native
]
:
[
native
,
wrapped
]
...
...
@@ -107,11 +125,16 @@ type GenericLPInfo = Omit<
AddLiquidityV3PoolTransactionInfo
|
RemoveLiquidityV3TransactionInfo
|
AddLiquidityV2PoolTransactionInfo
,
'
type
'
>
function
parseLP
(
lp
:
GenericLPInfo
,
chainId
:
ChainId
,
tokens
:
ChainTokenMap
):
Partial
<
Activity
>
{
function
parseLP
(
lp
:
GenericLPInfo
,
chainId
:
ChainId
,
tokens
:
ChainTokenMap
,
formatNumber
:
FormatNumberFunctionType
):
Partial
<
Activity
>
{
const
baseCurrency
=
getCurrency
(
lp
.
baseCurrencyId
,
chainId
,
tokens
)
const
quoteCurrency
=
getCurrency
(
lp
.
quoteCurrencyId
,
chainId
,
tokens
)
const
[
baseRaw
,
quoteRaw
]
=
[
lp
.
expectedAmountBaseRaw
,
lp
.
expectedAmountQuoteRaw
]
const
descriptor
=
buildCurrencyDescriptor
(
baseCurrency
,
baseRaw
,
quoteCurrency
,
quoteRaw
,
t
`and`
)
const
descriptor
=
buildCurrencyDescriptor
(
baseCurrency
,
baseRaw
,
quoteCurrency
,
quoteRaw
,
formatNumber
,
t
`and`
)
return
{
descriptor
,
currencies
:
[
baseCurrency
,
quoteCurrency
]
}
}
...
...
@@ -119,7 +142,8 @@ function parseLP(lp: GenericLPInfo, chainId: ChainId, tokens: ChainTokenMap): Pa
function
parseCollectFees
(
collect
:
CollectFeesTransactionInfo
,
chainId
:
ChainId
,
tokens
:
ChainTokenMap
tokens
:
ChainTokenMap
,
formatNumber
:
FormatNumberFunctionType
):
Partial
<
Activity
>
{
// Adapts CollectFeesTransactionInfo to generic LP type
const
{
...
...
@@ -128,7 +152,12 @@ function parseCollectFees(
expectedCurrencyOwed0
:
expectedAmountBaseRaw
,
expectedCurrencyOwed1
:
expectedAmountQuoteRaw
,
}
=
collect
return
parseLP
({
baseCurrencyId
,
quoteCurrencyId
,
expectedAmountBaseRaw
,
expectedAmountQuoteRaw
},
chainId
,
tokens
)
return
parseLP
(
{
baseCurrencyId
,
quoteCurrencyId
,
expectedAmountBaseRaw
,
expectedAmountQuoteRaw
},
chainId
,
tokens
,
formatNumber
)
}
function
parseMigrateCreateV3
(
...
...
@@ -157,7 +186,7 @@ export function transactionToActivity(
details
:
TransactionDetails
,
chainId
:
ChainId
,
tokens
:
ChainTokenMap
,
locale
?:
SupportedLocal
e
formatNumber
:
FormatNumberFunctionTyp
e
):
Activity
|
undefined
{
try
{
const
status
=
getTransactionStatus
(
details
)
...
...
@@ -176,19 +205,19 @@ export function transactionToActivity(
let
additionalFields
:
Partial
<
Activity
>
=
{}
const
info
=
details
.
info
if
(
info
.
type
===
TransactionType
.
SWAP
)
{
additionalFields
=
parseSwap
(
info
,
chainId
,
tokens
,
locale
)
additionalFields
=
parseSwap
(
info
,
chainId
,
tokens
,
formatNumber
)
}
else
if
(
info
.
type
===
TransactionType
.
APPROVAL
)
{
additionalFields
=
parseApproval
(
info
,
chainId
,
tokens
,
status
)
}
else
if
(
info
.
type
===
TransactionType
.
WRAP
)
{
additionalFields
=
parseWrap
(
info
,
chainId
,
status
)
additionalFields
=
parseWrap
(
info
,
chainId
,
status
,
formatNumber
)
}
else
if
(
info
.
type
===
TransactionType
.
ADD_LIQUIDITY_V3_POOL
||
info
.
type
===
TransactionType
.
REMOVE_LIQUIDITY_V3
||
info
.
type
===
TransactionType
.
ADD_LIQUIDITY_V2_POOL
)
{
additionalFields
=
parseLP
(
info
,
chainId
,
tokens
)
additionalFields
=
parseLP
(
info
,
chainId
,
tokens
,
formatNumber
)
}
else
if
(
info
.
type
===
TransactionType
.
COLLECT_FEES
)
{
additionalFields
=
parseCollectFees
(
info
,
chainId
,
tokens
)
additionalFields
=
parseCollectFees
(
info
,
chainId
,
tokens
,
formatNumber
)
}
else
if
(
info
.
type
===
TransactionType
.
MIGRATE_LIQUIDITY_V3
||
info
.
type
===
TransactionType
.
CREATE_V3_POOL
)
{
additionalFields
=
parseMigrateCreateV3
(
info
,
chainId
,
tokens
)
}
...
...
@@ -210,7 +239,7 @@ export function transactionToActivity(
export
function
signatureToActivity
(
signature
:
SignatureDetails
,
tokens
:
ChainTokenMap
,
locale
?:
SupportedLocal
e
formatNumber
:
FormatNumberFunctionTyp
e
):
Activity
|
undefined
{
switch
(
signature
.
type
)
{
case
SignatureType
.
SIGN_UNISWAPX_ORDER
:
{
...
...
@@ -229,7 +258,7 @@ export function signatureToActivity(
from
:
signature
.
offerer
,
statusMessage
,
prefixIconSrc
:
UniswapXBolt
,
...
parseSwap
(
signature
.
swapInfo
,
signature
.
chainId
,
tokens
,
locale
),
...
parseSwap
(
signature
.
swapInfo
,
signature
.
chainId
,
tokens
,
formatNumber
),
}
}
default
:
...
...
@@ -241,24 +270,24 @@ export function useLocalActivities(account: string): ActivityMap {
const
allTransactions
=
useMultichainTransactions
()
const
allSignatures
=
useAllSignatures
()
const
tokens
=
useAllTokensMultichain
()
const
{
format
terLocale
}
=
useFormatterLocales
()
const
{
format
Number
}
=
useFormatter
()
return
useMemo
(()
=>
{
const
activityMap
:
ActivityMap
=
{}
for
(
const
[
transaction
,
chainId
]
of
allTransactions
)
{
if
(
transaction
.
from
!==
account
)
continue
const
activity
=
transactionToActivity
(
transaction
,
chainId
,
tokens
,
format
terLocale
)
const
activity
=
transactionToActivity
(
transaction
,
chainId
,
tokens
,
format
Number
)
if
(
activity
)
activityMap
[
transaction
.
hash
]
=
activity
}
for
(
const
signature
of
Object
.
values
(
allSignatures
))
{
if
(
signature
.
offerer
!==
account
)
continue
const
activity
=
signatureToActivity
(
signature
,
tokens
,
format
terLocale
)
const
activity
=
signatureToActivity
(
signature
,
tokens
,
format
Number
)
if
(
activity
)
activityMap
[
signature
.
id
]
=
activity
}
return
activityMap
},
[
account
,
allSignatures
,
allTransactions
,
format
terLocale
,
tokens
])
},
[
account
,
allSignatures
,
allTransactions
,
format
Number
,
tokens
])
}
src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx
View file @
91c20135
...
...
@@ -21,7 +21,7 @@ import { gqlToCurrency, logSentryErrorForUnsupportedChain, supportedChainIdFromG
import
ms
from
'
ms
'
import
{
useEffect
,
useState
}
from
'
react
'
import
{
isAddress
}
from
'
utils
'
import
{
formatFiatPrice
,
formatNumberOrString
,
NumberType
}
from
'
utils/formatNumbers
'
import
{
NumberType
,
useFormatter
}
from
'
utils/formatNumbers
'
import
{
MOONPAY_SENDER_ADDRESSES
,
OrderStatusTable
,
OrderTextTable
}
from
'
../constants
'
import
{
Activity
}
from
'
./types
'
...
...
@@ -34,6 +34,8 @@ type TransactionChanges = {
NftApproveForAll
:
NftApproveForAllPartsFragment
[]
}
type
FormatNumberOrStringFunctionType
=
ReturnType
<
typeof
useFormatter
>
[
'
formatNumberOrString
'
]
// TODO: Move common contract metadata to a backend service
const
UNI_IMG
=
'
https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984/logo.png
'
...
...
@@ -140,13 +142,13 @@ function getSwapDescriptor({
* @param transactedValue Transacted value amount from TokenTransfer API response
* @returns parsed & formatted USD value as a string if currency is of type USD
*/
function
formatTransactedValue
(
transactedValue
:
TokenTransferPartsFragment
[
'
transactedValue
'
]):
string
{
if
(
!
transactedValue
)
return
'
-
'
function
getTransactedValue
(
transactedValue
:
TokenTransferPartsFragment
[
'
transactedValue
'
]):
number
|
undefined
{
if
(
!
transactedValue
)
return
undefined
const
price
=
transactedValue
?.
currency
===
GQLCurrency
.
Usd
?
transactedValue
.
value
??
undefined
:
undefined
return
formatFiatPrice
(
price
)
return
price
}
function
parseSwap
(
changes
:
TransactionChanges
)
{
function
parseSwap
(
changes
:
TransactionChanges
,
formatNumberOrString
:
FormatNumberOrStringFunctionType
)
{
if
(
changes
.
NftTransfer
.
length
>
0
&&
changes
.
TokenTransfer
.
length
===
1
)
{
const
collectionCounts
=
getCollectionCounts
(
changes
.
NftTransfer
)
...
...
@@ -168,8 +170,8 @@ function parseSwap(changes: TransactionChanges) {
if
(
sent
&&
received
)
{
const
adjustedInput
=
parseFloat
(
sent
.
quantity
)
-
parseFloat
(
refund
?.
quantity
??
'
0
'
)
const
inputAmount
=
formatNumberOrString
(
adjustedInput
,
NumberType
.
TokenNonTx
)
const
outputAmount
=
formatNumberOrString
(
received
.
quantity
,
NumberType
.
TokenNonTx
)
const
inputAmount
=
formatNumberOrString
(
{
input
:
adjustedInput
,
type
:
NumberType
.
TokenNonTx
}
)
const
outputAmount
=
formatNumberOrString
(
{
input
:
received
.
quantity
,
type
:
NumberType
.
TokenNonTx
}
)
return
{
title
:
getSwapTitle
(
sent
,
received
),
descriptor
:
getSwapDescriptor
({
tokenIn
:
sent
.
asset
,
inputAmount
,
tokenOut
:
received
.
asset
,
outputAmount
}),
...
...
@@ -180,8 +182,8 @@ function parseSwap(changes: TransactionChanges) {
return
{
title
:
t
`Unknown Swap`
}
}
function
parseSwapOrder
(
changes
:
TransactionChanges
)
{
return
{
...
parseSwap
(
changes
),
prefixIconSrc
:
UniswapXBolt
}
function
parseSwapOrder
(
changes
:
TransactionChanges
,
formatNumberOrString
:
FormatNumberOrStringFunctionType
)
{
return
{
...
parseSwap
(
changes
,
formatNumberOrString
),
prefixIconSrc
:
UniswapXBolt
}
}
function
parseApprove
(
changes
:
TransactionChanges
)
{
...
...
@@ -194,12 +196,12 @@ function parseApprove(changes: TransactionChanges) {
return
{
title
:
t
`Unknown Approval`
}
}
function
parseLPTransfers
(
changes
:
TransactionChanges
)
{
function
parseLPTransfers
(
changes
:
TransactionChanges
,
formatNumberOrString
:
FormatNumberOrStringFunctionType
)
{
const
poolTokenA
=
changes
.
TokenTransfer
[
0
]
const
poolTokenB
=
changes
.
TokenTransfer
[
1
]
const
tokenAQuanitity
=
formatNumberOrString
(
poolTokenA
.
quantity
,
NumberType
.
TokenNonTx
)
const
tokenBQuantity
=
formatNumberOrString
(
poolTokenB
.
quantity
,
NumberType
.
TokenNonTx
)
const
tokenAQuanitity
=
formatNumberOrString
(
{
input
:
poolTokenA
.
quantity
,
type
:
NumberType
.
TokenNonTx
}
)
const
tokenBQuantity
=
formatNumberOrString
(
{
input
:
poolTokenB
.
quantity
,
type
:
NumberType
.
TokenNonTx
}
)
return
{
descriptor
:
`
${
tokenAQuanitity
}
${
poolTokenA
.
asset
.
symbol
}
and
${
tokenBQuantity
}
${
poolTokenB
.
asset
.
symbol
}
`
,
...
...
@@ -211,11 +213,15 @@ function parseLPTransfers(changes: TransactionChanges) {
type
TransactionActivity
=
AssetActivityPartsFragment
&
{
details
:
TransactionDetailsPartsFragment
}
type
OrderActivity
=
AssetActivityPartsFragment
&
{
details
:
SwapOrderDetailsPartsFragment
}
function
parseSendReceive
(
changes
:
TransactionChanges
,
assetActivity
:
TransactionActivity
)
{
function
parseSendReceive
(
changes
:
TransactionChanges
,
formatNumberOrString
:
FormatNumberOrStringFunctionType
,
assetActivity
:
TransactionActivity
)
{
// TODO(cartcrom): remove edge cases after backend implements
// Edge case: Receiving two token transfers in interaction w/ V3 manager === removing liquidity. These edge cases should potentially be moved to backend
if
(
changes
.
TokenTransfer
.
length
===
2
&&
callsPositionManagerContract
(
assetActivity
))
{
return
{
title
:
t
`Removed Liquidity`
,
...
parseLPTransfers
(
changes
)
}
return
{
title
:
t
`Removed Liquidity`
,
...
parseLPTransfers
(
changes
,
formatNumberOrString
)
}
}
let
transfer
:
NftTransferPartsFragment
|
TokenTransferPartsFragment
|
undefined
...
...
@@ -230,7 +236,7 @@ function parseSendReceive(changes: TransactionChanges, assetActivity: Transactio
}
else
if
(
changes
.
TokenTransfer
.
length
===
1
)
{
transfer
=
changes
.
TokenTransfer
[
0
]
assetName
=
transfer
.
asset
.
symbol
amount
=
formatNumberOrString
(
transfer
.
quantity
,
NumberType
.
TokenNonTx
)
amount
=
formatNumberOrString
(
{
input
:
transfer
.
quantity
,
type
:
NumberType
.
TokenNonTx
}
)
currencies
=
[
gqlToCurrency
(
transfer
.
asset
)]
}
...
...
@@ -241,7 +247,10 @@ function parseSendReceive(changes: TransactionChanges, assetActivity: Transactio
return
isMoonpayPurchase
&&
transfer
.
__typename
===
'
TokenTransfer
'
?
{
title
:
t
`Purchased`
,
descriptor
:
`
${
amount
}
${
assetName
}
${
t
`for`
}
${
formatTransactedValue
(
transfer
.
transactedValue
)}
`
,
descriptor
:
`
${
amount
}
${
assetName
}
${
t
`for`
}
${
formatNumberOrString
({
input
:
getTransactedValue
(
transfer
.
transactedValue
),
type
:
NumberType
.
FiatTokenPrice
,
})}
`
,
logos
:
[
moonpayLogoSrc
],
currencies
,
}
...
...
@@ -263,25 +272,37 @@ function parseSendReceive(changes: TransactionChanges, assetActivity: Transactio
return
{
title
:
t
`Unknown Send`
}
}
function
parseMint
(
changes
:
TransactionChanges
,
assetActivity
:
TransactionActivity
)
{
function
parseMint
(
changes
:
TransactionChanges
,
formatNumberOrString
:
FormatNumberOrStringFunctionType
,
assetActivity
:
TransactionActivity
)
{
const
collectionMap
=
getCollectionCounts
(
changes
.
NftTransfer
)
if
(
Object
.
keys
(
collectionMap
).
length
===
1
)
{
const
collectionName
=
Object
.
keys
(
collectionMap
)[
0
]
// Edge case: Minting a v3 positon represents adding liquidity
if
(
changes
.
TokenTransfer
.
length
===
2
&&
callsPositionManagerContract
(
assetActivity
))
{
return
{
title
:
t
`Added Liquidity`
,
...
parseLPTransfers
(
changes
)
}
return
{
title
:
t
`Added Liquidity`
,
...
parseLPTransfers
(
changes
,
formatNumberOrString
)
}
}
return
{
title
:
t
`Minted`
,
descriptor
:
`
${
collectionMap
[
collectionName
]}
${
collectionName
}
`
}
}
return
{
title
:
t
`Unknown Mint`
}
}
function
parseUnknown
(
_changes
:
TransactionChanges
,
assetActivity
:
TransactionActivity
)
{
function
parseUnknown
(
_changes
:
TransactionChanges
,
_formatNumberOrString
:
FormatNumberOrStringFunctionType
,
assetActivity
:
TransactionActivity
)
{
return
{
title
:
t
`Contract Interaction`
,
...
COMMON_CONTRACTS
[
assetActivity
.
details
.
to
.
toLowerCase
()]
}
}
type
ActivityTypeParser
=
(
changes
:
TransactionChanges
,
assetActivity
:
TransactionActivity
)
=>
Partial
<
Activity
>
type
ActivityTypeParser
=
(
changes
:
TransactionChanges
,
formatNumberOrString
:
FormatNumberOrStringFunctionType
,
assetActivity
:
TransactionActivity
)
=>
Partial
<
Activity
>
const
ActivityParserByType
:
{
[
key
:
string
]:
ActivityTypeParser
|
undefined
}
=
{
[
ActivityType
.
Swap
]:
parseSwap
,
[
ActivityType
.
SwapOrder
]:
parseSwapOrder
,
...
...
@@ -345,7 +366,10 @@ function parseUniswapXOrder({ details, chain, timestamp }: OrderActivity): Activ
}
}
function
parseRemoteActivity
(
assetActivity
:
AssetActivityPartsFragment
):
Activity
|
undefined
{
function
parseRemoteActivity
(
assetActivity
:
AssetActivityPartsFragment
,
formatNumberOrString
:
FormatNumberOrStringFunctionType
):
Activity
|
undefined
{
try
{
if
(
assetActivity
.
details
.
__typename
===
'
SwapOrderDetails
'
)
{
return
parseUniswapXOrder
(
assetActivity
as
OrderActivity
)
...
...
@@ -385,6 +409,7 @@ function parseRemoteActivity(assetActivity: AssetActivityPartsFragment): Activit
const
parsedFields
=
ActivityParserByType
[
assetActivity
.
details
.
type
]?.(
changes
,
formatNumberOrString
,
assetActivity
as
TransactionActivity
)
return
{
...
defaultFields
,
...
parsedFields
}
...
...
@@ -394,9 +419,12 @@ function parseRemoteActivity(assetActivity: AssetActivityPartsFragment): Activit
}
}
export
function
parseRemoteActivities
(
assetActivities
?:
readonly
AssetActivityPartsFragment
[])
{
export
function
parseRemoteActivities
(
formatNumberOrString
:
FormatNumberOrStringFunctionType
,
assetActivities
?:
readonly
AssetActivityPartsFragment
[]
)
{
return
assetActivities
?.
reduce
((
acc
:
{
[
hash
:
string
]:
Activity
},
assetActivity
)
=>
{
const
activity
=
parseRemoteActivity
(
assetActivity
)
const
activity
=
parseRemoteActivity
(
assetActivity
,
formatNumberOrString
)
if
(
activity
)
acc
[
activity
.
hash
]
=
activity
return
acc
},
{})
...
...
src/components/NavBar/SuggestionRow.tsx
View file @
91c20135
...
...
@@ -18,7 +18,7 @@ import { useCallback, useEffect, useState } from 'react'
import
{
Link
,
useNavigate
}
from
'
react-router-dom
'
import
styled
from
'
styled-components
'
import
{
ThemedText
}
from
'
theme
'
import
{
formatUSDPrice
}
from
'
utils/formatNumbers
'
import
{
useFormatter
}
from
'
utils/formatNumbers
'
import
{
DeltaArrow
,
DeltaText
}
from
'
../Tokens/TokenDetails/Delta
'
import
{
useAddRecentlySearchedAsset
}
from
'
./RecentlySearchedAssets
'
...
...
@@ -128,6 +128,7 @@ interface TokenRowProps {
export
const
TokenRow
=
({
token
,
isHovered
,
setHoveredIndex
,
toggleOpen
,
index
,
eventProperties
}:
TokenRowProps
)
=>
{
const
addRecentlySearchedAsset
=
useAddRecentlySearchedAsset
()
const
navigate
=
useNavigate
()
const
{
formatFiatPrice
}
=
useFormatter
()
const
handleClick
=
useCallback
(()
=>
{
const
address
=
!
token
.
address
&&
token
.
standard
===
TokenStandard
.
Native
?
'
NATIVE
'
:
token
.
address
...
...
@@ -184,7 +185,7 @@ export const TokenRow = ({ token, isHovered, setHoveredIndex, toggleOpen, index,
{
!!
token
.
market
?.
price
?.
value
&&
(
<>
<
Row
gap=
"4"
>
<
Box
className=
{
styles
.
primaryText
}
>
{
format
USDPrice
(
token
.
market
.
price
.
value
)
}
</
Box
>
<
Box
className=
{
styles
.
primaryText
}
>
{
format
FiatPrice
({
price
:
token
.
market
.
price
.
value
}
)
}
</
Box
>
</
Row
>
<
PriceChangeContainer
>
<
DeltaArrow
delta=
{
token
.
market
?.
pricePercentChange
?.
value
}
/>
...
...
src/components/Popups/PopupContent.tsx
View file @
91c20135
...
...
@@ -17,6 +17,7 @@ import { useOrder } from 'state/signatures/hooks'
import
{
useTransaction
}
from
'
state/transactions/hooks
'
import
styled
from
'
styled-components
'
import
{
EllipsisStyle
,
ThemedText
}
from
'
theme
'
import
{
useFormatter
}
from
'
utils/formatNumbers
'
import
{
ExplorerDataType
,
getExplorerLink
}
from
'
utils/getExplorerLink
'
const
StyledClose
=
styled
(
X
)
<
{
$padding
:
number
}
>
`
...
...
@@ -137,9 +138,10 @@ export function TransactionPopupContent({
})
{
const
transaction
=
useTransaction
(
hash
)
const
tokens
=
useAllTokensMultichain
()
const
{
formatNumber
}
=
useFormatter
()
if
(
!
transaction
)
return
null
const
activity
=
transactionToActivity
(
transaction
,
chainId
,
tokens
)
const
activity
=
transactionToActivity
(
transaction
,
chainId
,
tokens
,
formatNumber
)
if
(
!
activity
)
return
null
...
...
@@ -153,9 +155,10 @@ export function UniswapXOrderPopupContent({ orderHash, onClose }: { orderHash: s
const
order
=
useOrder
(
orderHash
)
const
tokens
=
useAllTokensMultichain
()
const
openOffchainActivityModal
=
useOpenOffchainActivityModal
()
const
{
formatNumber
}
=
useFormatter
()
if
(
!
order
)
return
null
const
activity
=
signatureToActivity
(
order
,
tokens
)
const
activity
=
signatureToActivity
(
order
,
tokens
,
formatNumber
)
if
(
!
activity
)
return
null
...
...
src/components/PositionListItem/index.tsx
View file @
91c20135
...
...
@@ -15,7 +15,7 @@ import { Link } from 'react-router-dom'
import
{
Bound
}
from
'
state/mint/v3/actions
'
import
styled
from
'
styled-components
'
import
{
HideSmall
,
MEDIA_WIDTHS
,
SmallOnly
,
ThemedText
}
from
'
theme
'
import
{
formatTickPrice
}
from
'
utils/formatTickPrice
'
import
{
useFormatter
}
from
'
utils/formatNumbers
'
import
{
unwrappedToken
}
from
'
utils/unwrappedToken
'
import
{
DAI
,
USDC_MAINNET
,
USDT
,
WBTC
,
WRAPPED_NATIVE_CURRENCY
}
from
'
../../constants/tokens
'
...
...
@@ -172,6 +172,8 @@ export default function PositionListItem({
tickLower
,
tickUpper
,
}:
PositionListItemProps
)
{
const
{
formatTickPrice
}
=
useFormatter
()
const
token0
=
useToken
(
token0Address
)
const
token1
=
useToken
(
token1Address
)
...
...
src/components/PositionPreview/index.tsx
View file @
91c20135
...
...
@@ -14,7 +14,7 @@ import { ReactNode, useCallback, useState } from 'react'
import
{
Bound
}
from
'
state/mint/v3/actions
'
import
{
useTheme
}
from
'
styled-components
'
import
{
ThemedText
}
from
'
theme
'
import
{
formatTickPrice
}
from
'
utils/formatTickPrice
'
import
{
useFormatter
}
from
'
utils/formatNumbers
'
import
{
unwrappedToken
}
from
'
utils/unwrappedToken
'
export
const
PositionPreview
=
({
...
...
@@ -31,6 +31,7 @@ export const PositionPreview = ({
ticksAtLimit
:
{
[
bound
:
string
]:
boolean
|
undefined
}
})
=>
{
const
theme
=
useTheme
()
const
{
formatTickPrice
}
=
useFormatter
()
const
currency0
=
unwrappedToken
(
position
.
pool
.
token0
)
const
currency1
=
unwrappedToken
(
position
.
pool
.
token1
)
...
...
src/components/Tokens/TokenDetails/PriceChart.tsx
View file @
91c20135
...
...
@@ -17,7 +17,7 @@ import { Info, TrendingUp } from 'react-feather'
import
styled
,
{
useTheme
}
from
'
styled-components
'
import
{
ThemedText
}
from
'
theme
'
import
{
textFadeIn
}
from
'
theme/styles
'
import
{
formatUSDPrice
}
from
'
utils/formatNumbers
'
import
{
useFormatter
}
from
'
utils/formatNumbers
'
import
{
calculateDelta
,
DeltaArrow
,
formatDelta
}
from
'
./Delta
'
...
...
@@ -87,6 +87,7 @@ interface PriceChartProps {
export
function
PriceChart
({
width
,
height
,
prices
:
originalPrices
,
timePeriod
}:
PriceChartProps
)
{
const
locale
=
useActiveLocale
()
const
theme
=
useTheme
()
const
{
formatFiatPrice
}
=
useFormatter
()
const
{
prices
,
blanks
}
=
useMemo
(
()
=>
...
...
@@ -208,13 +209,13 @@ export function PriceChart({ width, height, prices: originalPrices, timePeriod }
<
ChartHeader
data
-
cy=
"chart-header"
>
{
displayPrice
.
value
?
(
<>
<
TokenPrice
>
{
format
USDPrice
(
displayPrice
.
value
)
}
</
TokenPrice
>
<
TokenPrice
>
{
format
FiatPrice
({
price
:
displayPrice
.
value
}
)
}
</
TokenPrice
>
<
ChartDelta
startingPrice=
{
startingPrice
}
endingPrice=
{
displayPrice
}
/>
</>
)
:
lastPrice
.
value
?
(
<
OutdatedContainer
>
<
OutdatedPriceContainer
>
<
TokenPrice
>
{
format
USDPrice
(
lastPrice
.
value
)
}
</
TokenPrice
>
<
TokenPrice
>
{
format
FiatPrice
({
price
:
lastPrice
.
value
}
)
}
</
TokenPrice
>
<
MouseoverTooltip
text=
{
tooltipMessage
}
>
<
Info
size=
{
16
}
/>
</
MouseoverTooltip
>
...
...
src/components/Tokens/TokenTable/TokenRow.tsx
View file @
91c20135
...
...
@@ -16,7 +16,7 @@ import { CSSProperties, ReactNode } from 'react'
import
{
Link
,
useParams
}
from
'
react-router-dom
'
import
styled
,
{
css
,
useTheme
}
from
'
styled-components
'
import
{
BREAKPOINTS
,
ClickableStyle
}
from
'
theme
'
import
{
formatUSDPrice
,
NumberType
,
useFormatter
}
from
'
utils/formatNumbers
'
import
{
NumberType
,
useFormatter
}
from
'
utils/formatNumbers
'
import
{
LARGE_MEDIA_BREAKPOINT
,
...
...
@@ -440,7 +440,7 @@ interface LoadedRowProps {
/* Loaded State: row component with token information */
export
const
LoadedRow
=
forwardRef
((
props
:
LoadedRowProps
,
ref
:
ForwardedRef
<
HTMLDivElement
>
)
=>
{
const
{
formatNumber
}
=
useFormatter
()
const
{
format
FiatPrice
,
format
Number
}
=
useFormatter
()
const
{
tokenListIndex
,
tokenListLength
,
token
,
sortRank
}
=
props
const
filterString
=
useAtomValue
(
filterStringAtom
)
...
...
@@ -463,7 +463,7 @@ export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HT
}
// A simple 0 price indicates the price is not currently available from the api
const
price
=
token
.
market
?.
price
?.
value
===
0
?
'
-
'
:
format
USDPrice
(
token
.
market
?.
price
?.
value
)
const
price
=
token
.
market
?.
price
?.
value
===
0
?
'
-
'
:
format
FiatPrice
({
price
:
token
.
market
?.
price
?.
value
}
)
// TODO: currency logo sizing mobile (32px) vs. desktop (24px)
return
(
...
...
src/components/swap/SwapModalFooter.tsx
View file @
91c20135
...
...
@@ -17,7 +17,6 @@ import { useRouterPreference, useUserSlippageTolerance } from 'state/user/hooks'
import
styled
,
{
DefaultTheme
,
useTheme
}
from
'
styled-components
'
import
{
ExternalLink
,
ThemedText
}
from
'
theme
'
import
{
FormatterRule
,
NumberType
,
SIX_SIG_FIGS_NO_COMMAS
,
useFormatter
}
from
'
utils/formatNumbers
'
import
{
priceToPreciseFloat
}
from
'
utils/formatNumbers
'
import
getRoutingDiagramEntries
from
'
utils/getRoutingDiagramEntries
'
import
{
formatSwapButtonClickEventProperties
}
from
'
utils/loggingFormatters
'
import
{
getPriceImpactColor
}
from
'
utils/prices
'
...
...
@@ -85,7 +84,7 @@ export default function SwapModalFooter({
const
label
=
`
${
trade
.
executionPrice
.
baseCurrency
?.
symbol
}
`
const labelInverted = `
$
{
trade
.
executionPrice
.
quoteCurrency
?.
symbol
}
`
const formattedPrice = formatNumber({
input:
priceToPreciseFloat(trade.executionPrice)
,
input:
trade.executionPrice ? parseFloat(trade.executionPrice.toFixed(9)) : undefined
,
type: NumberType.TokenTx,
})
const txCount = getTransactionCount(trade)
...
...
src/components/swap/SwapModalHeader.test.tsx
View file @
91c20135
...
...
@@ -6,7 +6,6 @@ import {
TEST_TRADE_EXACT_OUTPUT
,
}
from
'
test-utils/constants
'
import
{
render
,
screen
}
from
'
test-utils/render
'
import
{
formatCurrencyAmount
,
NumberType
}
from
'
utils/formatNumbers
'
import
SwapModalHeader
from
'
./SwapModalHeader
'
...
...
@@ -17,16 +16,8 @@ describe('SwapModalHeader.tsx', () => {
)
expect
(
asFragment
()).
toMatchSnapshot
()
expect
(
screen
.
getByText
(
/Output is estimated. You will receive at least /i
)).
toBeInTheDocument
()
expect
(
screen
.
getByTestId
(
'
INPUT-amount
'
)).
toHaveTextContent
(
`
${
formatCurrencyAmount
({
amount
:
TEST_TRADE_EXACT_INPUT
.
inputAmount
,
type
:
NumberType
.
TokenTx
})}
${
TEST_TRADE_EXACT_INPUT
.
inputAmount
.
currency
.
symbol
??
''
}
`
)
expect(screen.getByTestId('OUTPUT-amount')).toHaveTextContent(
`
$
{
formatCurrencyAmount
({
amount
:
TEST_TRADE_EXACT_INPUT
.
outputAmount
,
type
:
NumberType
.
TokenTx
})}
$
{
TEST_TRADE_EXACT_INPUT
.
outputAmount
.
currency
.
symbol
??
''
}
`
)
expect
(
screen
.
getByTestId
(
'
INPUT-amount
'
)).
toHaveTextContent
(
`<0.00001 ABC`
)
expect
(
screen
.
getByTestId
(
'
OUTPUT-amount
'
)).
toHaveTextContent
(
`<0.00001 DEF`
)
})
it
(
'
renders ETH input token for an ETH input UniswapX swap
'
,
()
=>
{
...
...
@@ -39,16 +30,8 @@ describe('SwapModalHeader.tsx', () => {
)
expect
(
asFragment
()).
toMatchSnapshot
()
expect
(
screen
.
getByText
(
/Output is estimated. You will receive at least /i
)).
toBeInTheDocument
()
expect(screen.getByTestId('INPUT-amount')).toHaveTextContent(
`
$
{
formatCurrencyAmount
({
amount
:
TEST_DUTCH_TRADE_ETH_INPUT
.
inputAmount
,
type
:
NumberType
.
TokenTx
})}
$
{
ETH_MAINNET
.
symbol
}
`
)
expect(screen.getByTestId('OUTPUT-amount')).toHaveTextContent(
`
$
{
formatCurrencyAmount
({
amount
:
TEST_DUTCH_TRADE_ETH_INPUT
.
outputAmount
,
type
:
NumberType
.
TokenTx
})}
$
{
TEST_DUTCH_TRADE_ETH_INPUT
.
outputAmount
.
currency
.
symbol
??
''
}
`
)
expect
(
screen
.
getByTestId
(
'
INPUT-amount
'
)).
toHaveTextContent
(
`<0.00001 ETH`
)
expect
(
screen
.
getByTestId
(
'
OUTPUT-amount
'
)).
toHaveTextContent
(
`<0.00001 DEF`
)
})
it
(
'
test trade exact output, no recipient
'
,
()
=>
{
...
...
@@ -58,15 +41,7 @@ describe('SwapModalHeader.tsx', () => {
expect
(
asFragment
()).
toMatchSnapshot
()
expect
(
screen
.
getByText
(
/Input is estimated. You will sell at most/i
)).
toBeInTheDocument
()
expect(screen.getByTestId('INPUT-amount')).toHaveTextContent(
`
$
{
formatCurrencyAmount
({
amount
:
TEST_TRADE_EXACT_OUTPUT
.
inputAmount
,
type
:
NumberType
.
TokenTx
})}
$
{
TEST_TRADE_EXACT_OUTPUT
.
inputAmount
.
currency
.
symbol
??
''
}
`
)
expect(screen.getByTestId('OUTPUT-amount')).toHaveTextContent(
`
$
{
formatCurrencyAmount
({
amount
:
TEST_TRADE_EXACT_OUTPUT
.
outputAmount
,
type
:
NumberType
.
TokenTx
})}
$
{
TEST_TRADE_EXACT_OUTPUT
.
outputAmount
.
currency
.
symbol
??
''
}
`
)
expect
(
screen
.
getByTestId
(
'
INPUT-amount
'
)).
toHaveTextContent
(
`<0.00001 ABC`
)
expect
(
screen
.
getByTestId
(
'
OUTPUT-amount
'
)).
toHaveTextContent
(
`<0.00001 GHI`
)
})
})
src/nft/components/explore/CarouselCard.tsx
View file @
91c20135
...
...
@@ -6,7 +6,7 @@ import { Markets, TrendingCollection } from 'nft/types'
import
{
ethNumberStandardFormatter
}
from
'
nft/utils
'
import
styled
from
'
styled-components
'
import
{
ThemedText
}
from
'
theme/components/text
'
import
{
formatNumberOrString
,
NumberType
}
from
'
utils/formatNumbers
'
import
{
NumberType
,
useFormatter
}
from
'
utils/formatNumbers
'
const
CarouselCardBorder
=
styled
.
div
`
width: 100%;
...
...
@@ -198,6 +198,8 @@ interface MarketplaceRowProps {
}
const
MarketplaceRow
=
({
marketplace
,
floorInEth
,
listings
}:
MarketplaceRowProps
)
=>
{
const
{
formatNumberOrString
}
=
useFormatter
()
return
(
<>
<
TableElement
>
...
...
@@ -212,7 +214,7 @@ const MarketplaceRow = ({ marketplace, floorInEth, listings }: MarketplaceRowPro
<
TableElement
>
<
ThemedText
.
BodySmall
color=
"neutral2"
>
{
Number
(
floorInEth
)
>
0
?
`${formatNumberOrString(
floorInEth, NumberType.NFTTokenFloorPriceTrailingZeros
)} ETH`
?
`${formatNumberOrString(
{ input: floorInEth, type: NumberType.NFTTokenFloorPriceTrailingZeros }
)} ETH`
:
'
-
'
}
</
ThemedText
.
BodySmall
>
</
TableElement
>
...
...
src/pages/Pool/PositionPage.tsx
View file @
91c20135
...
...
@@ -38,7 +38,6 @@ import { currencyId } from 'utils/currencyId'
import
{
WrongChainError
}
from
'
utils/errors
'
import
{
formatCurrencyAmount
}
from
'
utils/formatCurrencyAmount
'
import
{
NumberType
,
useFormatter
}
from
'
utils/formatNumbers
'
import
{
formatTickPrice
}
from
'
utils/formatTickPrice
'
import
{
unwrappedToken
}
from
'
utils/unwrappedToken
'
import
RangeBadge
from
'
../../components/Badge/RangeBadge
'
...
...
@@ -389,6 +388,7 @@ function PositionPageContent() {
const
{
tokenId
:
tokenIdFromUrl
}
=
useParams
<
{
tokenId
?:
string
}
>
()
const
{
chainId
,
account
,
provider
}
=
useWeb3React
()
const
theme
=
useTheme
()
const
{
formatTickPrice
}
=
useFormatter
()
const
parsedTokenId
=
tokenIdFromUrl
?
BigNumber
.
from
(
tokenIdFromUrl
)
:
undefined
const
{
loading
,
position
:
positionDetails
}
=
useV3PositionFromTokenId
(
parsedTokenId
)
...
...
src/utils/formatNumbers.test.ts
View file @
91c20135
This diff is collapsed.
Click to expand it.
src/utils/formatNumbers.ts
View file @
91c20135
import
{
Currency
,
CurrencyAmount
,
Percent
,
Price
}
from
'
@uniswap/sdk-core
'
import
{
Currency
,
CurrencyAmount
,
Percent
,
Price
,
Token
}
from
'
@uniswap/sdk-core
'
import
{
DEFAULT_LOCAL_CURRENCY
,
LOCAL_CURRENCY_SYMBOL_DISPLAY_TYPE
,
...
...
@@ -12,6 +12,7 @@ import { useActiveLocalCurrency } from 'hooks/useActiveLocalCurrency'
import
{
useActiveLocale
}
from
'
hooks/useActiveLocale
'
import
usePrevious
from
'
hooks/usePrevious
'
import
{
useCallback
,
useMemo
}
from
'
react
'
import
{
Bound
}
from
'
state/mint/v3/actions
'
type
Nullish
<
T
>
=
T
|
null
|
undefined
type
NumberFormatOptions
=
Intl
.
NumberFormatOptions
...
...
@@ -392,7 +393,7 @@ interface FormatNumberOptions {
conversionRate
?:
number
}
export
function
formatNumber
({
function
formatNumber
({
input
,
type
=
NumberType
.
TokenNonTx
,
placeholder
=
'
-
'
,
...
...
@@ -434,7 +435,7 @@ interface FormatCurrencyAmountOptions {
conversionRate
?:
number
}
export
function
formatCurrencyAmount
({
function
formatCurrencyAmount
({
amount
,
type
=
NumberType
.
TokenNonTx
,
placeholder
,
...
...
@@ -452,7 +453,7 @@ export function formatCurrencyAmount({
})
}
export
function
formatPriceImpact
(
priceImpact
:
Percent
|
undefined
,
locale
:
SupportedLocale
=
DEFAULT_LOCALE
):
string
{
function
formatPriceImpact
(
priceImpact
:
Percent
|
undefined
,
locale
:
SupportedLocale
=
DEFAULT_LOCALE
):
string
{
if
(
!
priceImpact
)
return
'
-
'
return
`
${
Number
(
priceImpact
.
multiply
(
-
1
).
toFixed
(
3
)).
toLocaleString
(
locale
,
{
...
...
@@ -462,13 +463,17 @@ export function formatPriceImpact(priceImpact: Percent | undefined, locale: Supp
})}
%`
}
export
function
formatSlippage
(
slippage
:
Percent
|
undefined
)
{
function
formatSlippage
(
slippage
:
Percent
|
undefined
,
locale
:
SupportedLocale
=
DEFAULT_LOCALE
)
{
if
(
!
slippage
)
return
'
-
'
return
`
${
slippage
.
toFixed
(
3
)}
%`
return
`
${
Number
(
slippage
.
toFixed
(
3
)).
toLocaleString
(
locale
,
{
minimumFractionDigits
:
3
,
maximumFractionDigits
:
3
,
useGrouping
:
false
,
})}
%`
}
interface
FormatPrice
Prop
s
{
interface
FormatPrice
Option
s
{
price
:
Nullish
<
Price
<
Currency
,
Currency
>>
type
:
FormatterType
locale
?:
SupportedLocale
...
...
@@ -476,13 +481,13 @@ interface FormatPriceProps {
conversionRate
?:
number
}
export
function
formatPrice
({
function
formatPrice
({
price
,
type
=
NumberType
.
FiatTokenPrice
,
locale
=
DEFAULT_LOCALE
,
localCurrency
=
DEFAULT_LOCAL_CURRENCY
,
conversionRate
,
}:
FormatPrice
Prop
s
):
string
{
}:
FormatPrice
Option
s
):
string
{
if
(
price
===
null
||
price
===
undefined
)
{
return
'
-
'
}
...
...
@@ -490,45 +495,80 @@ export function formatPrice({
return
formatNumber
({
input
:
parseFloat
(
price
.
toSignificant
()),
type
,
locale
,
localCurrency
,
conversionRate
})
}
export
function
formatNumberOrString
(
price
:
Nullish
<
number
|
string
>
,
type
:
FormatterType
):
string
{
if
(
price
===
null
||
price
===
undefined
)
return
'
-
'
if
(
typeof
price
===
'
string
'
)
return
formatNumber
({
input
:
parseFloat
(
price
),
type
})
return
formatNumber
({
input
:
price
,
type
})
interface
FormatTickPriceOptions
{
price
?:
Price
<
Token
,
Token
>
atLimit
:
{
[
bound
in
Bound
]?:
boolean
|
undefined
}
direction
:
Bound
placeholder
?:
string
numberType
?:
NumberType
locale
?:
SupportedLocale
localCurrency
?:
SupportedLocalCurrency
conversionRate
?:
number
}
export
function
formatUSDPrice
(
price
:
Nullish
<
number
|
string
>
,
type
:
NumberType
=
NumberType
.
FiatTokenPrice
):
string
{
return
formatNumberOrString
(
price
,
type
)
function
formatTickPrice
({
price
,
atLimit
,
direction
,
placeholder
,
numberType
,
locale
,
localCurrency
,
conversionRate
,
}:
FormatTickPriceOptions
)
{
if
(
atLimit
[
direction
])
{
return
direction
===
Bound
.
LOWER
?
'
0
'
:
'
∞
'
}
if
(
!
price
&&
placeholder
!==
undefined
)
{
return
placeholder
}
return
formatPrice
({
price
,
type
:
numberType
??
NumberType
.
TokenNonTx
,
locale
,
localCurrency
,
conversionRate
})
}
/** Formats USD and non-USD prices */
export
function
formatFiatPrice
(
price
:
Nullish
<
number
>
,
currency
=
'
USD
'
):
string
{
if
(
price
===
null
||
price
===
undefined
)
return
'
-
'
return
new
Intl
.
NumberFormat
(
'
en-US
'
,
{
style
:
'
currency
'
,
currency
}).
format
(
price
)
interface
FormatNumberOrStringOptions
{
input
:
Nullish
<
number
|
string
>
type
:
FormatterType
locale
?:
SupportedLocale
localCurrency
?:
SupportedLocalCurrency
conversionRate
?:
number
}
// Convert [CurrencyAmount] to number with necessary precision for price formatting.
export
const
currencyAmountToPreciseFloat
=
(
currencyAmount
:
CurrencyAmount
<
Currency
>
|
undefined
)
=>
{
if
(
!
currencyAmount
)
return
undefined
const
floatForLargerNumbers
=
parseFloat
(
currencyAmount
.
toExact
())
if
(
floatForLargerNumbers
<
0.1
)
{
return
parseFloat
(
currencyAmount
.
toSignificant
(
6
))
}
return
floatForLargerNumbers
function
formatNumberOrString
({
input
,
type
,
locale
,
localCurrency
,
conversionRate
,
}:
FormatNumberOrStringOptions
):
string
{
if
(
input
===
null
||
input
===
undefined
)
return
'
-
'
if
(
typeof
input
===
'
string
'
)
return
formatNumber
({
input
:
parseFloat
(
input
),
type
,
locale
,
localCurrency
,
conversionRate
})
return
formatNumber
({
input
,
type
,
locale
,
localCurrency
,
conversionRate
})
}
// Convert [Price] to number with necessary precision for price formatting.
export
const
priceToPreciseFloat
=
(
price
:
Price
<
Currency
,
Currency
>
|
undefined
)
=>
{
if
(
!
price
)
return
undefined
const
floatForLargerNumbers
=
parseFloat
(
price
.
toFixed
(
9
))
if
(
floatForLargerNumbers
<
0.1
)
{
return
parseFloat
(
price
.
toSignificant
(
6
))
}
return
floatForLargerNumbers
interface
FormatFiatPriceOptions
{
price
:
Nullish
<
number
|
string
>
type
?:
FormatterType
locale
?:
SupportedLocale
localCurrency
?:
SupportedLocalCurrency
conversionRate
?:
number
}
function
formatFiatPrice
({
price
,
type
=
NumberType
.
FiatTokenPrice
,
locale
,
localCurrency
,
conversionRate
,
}:
FormatFiatPriceOptions
):
string
{
return
formatNumberOrString
({
input
:
price
,
type
,
locale
,
localCurrency
,
conversionRate
})
}
const
MAX_AMOUNT_STR_LENGTH
=
9
export
function
formatReviewSwapCurrencyAmount
(
function
formatReviewSwapCurrencyAmount
(
amount
:
CurrencyAmount
<
Currency
>
,
locale
:
SupportedLocale
=
DEFAULT_LOCALE
):
string
{
...
...
@@ -539,7 +579,7 @@ export function formatReviewSwapCurrencyAmount(
return
formattedAmount
}
export
function
useFormatterLocales
():
{
function
useFormatterLocales
():
{
formatterLocale
:
SupportedLocale
formatterLocalCurrency
:
SupportedLocalCurrency
}
{
...
...
@@ -620,7 +660,7 @@ export function useFormatter() {
)
const
formatPriceWithLocales
=
useCallback
(
(
options
:
Omit
<
FormatPrice
Prop
s
,
LocalesType
>
)
=>
(
options
:
Omit
<
FormatPrice
Option
s
,
LocalesType
>
)
=>
formatPrice
({
...
options
,
locale
:
formatterLocale
,
...
...
@@ -640,20 +680,66 @@ export function useFormatter() {
[
formatterLocale
]
)
const
formatSlippageWithLocales
=
useCallback
(
(
slippage
:
Percent
|
undefined
)
=>
formatSlippage
(
slippage
,
formatterLocale
),
[
formatterLocale
]
)
const
formatTickPriceWithLocales
=
useCallback
(
(
options
:
Omit
<
FormatTickPriceOptions
,
LocalesType
>
)
=>
formatTickPrice
({
...
options
,
locale
:
formatterLocale
,
localCurrency
:
currencyToFormatWith
,
conversionRate
:
localCurrencyConversionRateToFormatWith
,
}),
[
currencyToFormatWith
,
formatterLocale
,
localCurrencyConversionRateToFormatWith
]
)
const
formatNumberOrStringWithLocales
=
useCallback
(
(
options
:
Omit
<
FormatNumberOrStringOptions
,
LocalesType
>
)
=>
formatNumberOrString
({
...
options
,
locale
:
formatterLocale
,
localCurrency
:
currencyToFormatWith
,
conversionRate
:
localCurrencyConversionRateToFormatWith
,
}),
[
currencyToFormatWith
,
formatterLocale
,
localCurrencyConversionRateToFormatWith
]
)
const
formatFiatPriceWithLocales
=
useCallback
(
(
options
:
Omit
<
FormatFiatPriceOptions
,
LocalesType
>
)
=>
formatFiatPrice
({
...
options
,
locale
:
formatterLocale
,
localCurrency
:
currencyToFormatWith
,
conversionRate
:
localCurrencyConversionRateToFormatWith
,
}),
[
currencyToFormatWith
,
formatterLocale
,
localCurrencyConversionRateToFormatWith
]
)
return
useMemo
(
()
=>
({
formatCurrencyAmount
:
formatCurrencyAmountWithLocales
,
formatFiatPrice
:
formatFiatPriceWithLocales
,
formatNumber
:
formatNumberWithLocales
,
formatNumberOrString
:
formatNumberOrStringWithLocales
,
formatPrice
:
formatPriceWithLocales
,
formatPriceImpact
:
formatPriceImpactWithLocales
,
formatReviewSwapCurrencyAmount
:
formatReviewSwapCurrencyAmountWithLocales
,
formatSlippage
:
formatSlippageWithLocales
,
formatTickPrice
:
formatTickPriceWithLocales
,
}),
[
formatCurrencyAmountWithLocales
,
formatFiatPriceWithLocales
,
formatNumberOrStringWithLocales
,
formatNumberWithLocales
,
formatPriceImpactWithLocales
,
formatPriceWithLocales
,
formatReviewSwapCurrencyAmountWithLocales
,
formatSlippageWithLocales
,
formatTickPriceWithLocales
,
]
)
}
src/utils/formatTickPrice.ts
deleted
100644 → 0
View file @
cf09e809
import
{
Price
,
Token
}
from
'
@uniswap/sdk-core
'
import
{
formatPrice
,
NumberType
}
from
'
utils/formatNumbers
'
import
{
Bound
}
from
'
../state/mint/v3/actions
'
interface
FormatTickPriceArgs
{
price
?:
Price
<
Token
,
Token
>
atLimit
:
{
[
bound
in
Bound
]?:
boolean
|
undefined
}
direction
:
Bound
placeholder
?:
string
numberType
?:
NumberType
}
export
function
formatTickPrice
({
price
,
atLimit
,
direction
,
placeholder
,
numberType
}:
FormatTickPriceArgs
)
{
if
(
atLimit
[
direction
])
{
return
direction
===
Bound
.
LOWER
?
'
0
'
:
'
∞
'
}
if
(
!
price
&&
placeholder
!==
undefined
)
{
return
placeholder
}
return
formatPrice
({
price
,
type
:
numberType
??
NumberType
.
TokenNonTx
})
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment