diff --git a/.gitignore b/.gitignore index 930cb8289b..1254cdbebc 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ cypress/fixtures/example.json .vim target/ +*.tsbuildinfo \ No newline at end of file diff --git a/src/components/ProAmm/ChartPositions.tsx b/src/components/ProAmm/ChartPositions.tsx deleted file mode 100644 index 01c71140bb..0000000000 --- a/src/components/ProAmm/ChartPositions.tsx +++ /dev/null @@ -1,185 +0,0 @@ -import { Position } from '@kyberswap/ks-sdk-elastic' -import { Trans } from '@lingui/macro' -import { Flex, Text } from 'rebass' -import styled from 'styled-components' - -import CurrencyLogo from 'components/CurrencyLogo' -import { Bound } from 'state/mint/proamm/type' -import { formattedNum } from 'utils' -import { getTickToPrice } from 'utils/getTickToPrice' - -import PriceVisualize from './PriceVisualize' - -const TableWrapper = styled.div` - margin-top: 1rem; -` - -const TableHeader = styled.div` - display: grid; - grid-gap: 1.5rem; - grid-template-columns: 20px 1fr 1fr 1fr 1.5fr; - padding: 16px 20px; - font-size: 12px; - align-items: center; - height: fit-content; - position: relative; - background-color: ${({ theme }) => theme.background}; - border-top-left-radius: 20px; - border-top-right-radius: 20px; - z-index: 1; - border-bottom: ${({ theme }) => `1px solid ${theme.border}`}; - text-align: right; -` - -const TableRow = styled.div` - display: grid; - grid-gap: 1.5rem; - grid-template-columns: 20px 1fr 1fr 1fr 1.5fr; - padding: 12px 16px; - font-size: 14px; - align-items: center; - height: fit-content; - position: relative; - border-bottom: 1px solid ${({ theme }) => theme.border}; - - :last-child { - border-bottom: none; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - } -` - -const RowItem = styled(Flex)` - flex-direction: column; -` - -const PositionListItem = ({ - position, - index, - usdPrices, - ticksAtLimit, - rotated, -}: { - position: Position - index: number - usdPrices: { - [address: string]: number - } - ticksAtLimit: { - [bound in Bound]: boolean | undefined - } - rotated: boolean -}) => { - const [tokenA, tokenB] = rotated - ? [position.amount1.currency, position.amount0.currency] - : [position.amount0.currency, position.amount1.currency] - const usdValue = - parseFloat(position.amount0.toSignificant(6)) * usdPrices[tokenA.address] + - parseFloat(position.amount1.toSignificant(6)) * usdPrices[tokenB.address] - const priceLower = getTickToPrice(tokenA, tokenB, position.tickLower) - const priceUpper = getTickToPrice(tokenA, tokenB, position.tickUpper) - if (!priceLower || !priceUpper) return null - - return ( - - - {index + 1} - - {formattedNum(usdValue.toString(), true)} - - - - - {position.amount0.toSignificant(4)} {position.amount0.currency.symbol} - - - - - - - - {position.amount1.toSignificant(4)} {position.amount1.currency.symbol} - - - - - - - - ) -} - -const ChartPositions = ({ - positions, - usdPrices, - rotated, - ticksAtLimits, -}: { - positions: Position[] - usdPrices: { - [address: string]: number - } - ticksAtLimits: { - [bound in Bound]: (boolean | undefined)[] - } - rotated: boolean -}) => { - const [tokenA, tokenB] = rotated - ? [positions[0].amount1.currency, positions[0].amount0.currency] - : [positions[0].amount0.currency, positions[0].amount1.currency] - - const header = ( - - - # - - - VALUE - - - - {positions[0].amount0.currency.symbol} - - - - {positions[0].amount1.currency.symbol} - - - - - PRICE RANGE ({tokenB.symbol} per {tokenA.symbol}) - - - - ) - - const body = positions.map((position, index) => { - return ( - - ) - }) - return ( - - {header} - {body} - - ) -} - -export default ChartPositions diff --git a/src/components/ProAmm/ListPositions.tsx b/src/components/ProAmm/ListPositions.tsx index 11d89b89cc..abe2f81071 100644 --- a/src/components/ProAmm/ListPositions.tsx +++ b/src/components/ProAmm/ListPositions.tsx @@ -1,3 +1,4 @@ +import { Currency } from '@kyberswap/ks-sdk-core' import { Position } from '@kyberswap/ks-sdk-elastic' import { Trans } from '@lingui/macro' import { useState } from 'react' @@ -12,10 +13,9 @@ import { ClickableText } from 'components/YieldPools/styleds' import useTheme from 'hooks/useTheme' import { Bound } from 'state/mint/proamm/type' import { MEDIA_WIDTHS } from 'theme' -import { formattedNum } from 'utils' import { formatTickPrice } from 'utils/formatTickPrice' import { getTickToPrice } from 'utils/getTickToPrice' -import { unwrappedToken } from 'utils/wrappedCurrency' +import { formatDisplayNumber } from 'utils/numbers' import PriceVisualizeAlignCurrent from './PriceVisualizeAlignCurrent' @@ -83,6 +83,8 @@ const PositionListItem = ({ usdPrices, ticksAtLimit, rotated, + baseCurrency, + quoteCurrency, }: { position: Position index: number @@ -93,23 +95,40 @@ const PositionListItem = ({ [bound in Bound]: boolean | undefined } rotated: boolean + baseCurrency: Currency + quoteCurrency: Currency }) => { const upToSmall = useMedia(`(max-width: ${MEDIA_WIDTHS.upToSmall}px)`) const [isExpanded, setIsExpanded] = useState(false) const theme = useTheme() - const [tokenA, tokenB] = rotated - ? [position.amount1.currency, position.amount0.currency] - : [position.amount0.currency, position.amount1.currency] + + const [tokenAmountA, tokenAmountB, currencyA, currencyB, tokenA, tokenB] = rotated + ? [ + position.amount1, + position.amount0, + quoteCurrency, + baseCurrency, + position.amount1.currency, + position.amount0.currency, + ] + : [ + position.amount0, + position.amount1, + baseCurrency, + quoteCurrency, + position.amount0.currency, + position.amount1.currency, + ] + const usdValue = parseFloat(position.amount0.toSignificant(6)) * usdPrices[position.amount0.currency.address] + parseFloat(position.amount1.toSignificant(6)) * usdPrices[position.amount1.currency.address] + const priceLower = getTickToPrice(tokenA, tokenB, position.tickLower) const priceUpper = getTickToPrice(tokenA, tokenB, position.tickUpper) const formattedLowerPrice = formatTickPrice(priceLower, ticksAtLimit, Bound.LOWER) const formattedUpperPrice = formatTickPrice(priceUpper, ticksAtLimit, Bound.UPPER) - const currency0 = unwrappedToken(position.amount0.currency) - const currency1 = unwrappedToken(position.amount1.currency) if (!priceLower || !priceUpper) return null return ( @@ -118,23 +137,23 @@ const PositionListItem = ({ {index + 1} - {formattedNum(usdValue.toString(), true)} + {formatDisplayNumber(usdValue, { style: 'currency', significantDigits: 4 })} {upToSmall ? null : ( <> - + - {position.amount0.toSignificant(4)} {currency0.symbol} + {tokenAmountA.toSignificant(4)} {currencyA.symbol} - + - {position.amount1.toSignificant(4)} {currency1.symbol} + {tokenAmountB.toSignificant(4)} {currencyB.symbol} @@ -161,20 +180,18 @@ const PositionListItem = ({ - {/* {position.amount0.currency.symbol} */} - + - {position.amount0.toSignificant(4)} {currency0.symbol} + {tokenAmountA.toSignificant(4)} {currencyA.symbol} - {/* {position.amount1.currency.symbol} */} - + - {position.amount1.toSignificant(4)} {currency1.symbol} + {tokenAmountB.toSignificant(4)} {currencyB.symbol} @@ -197,11 +214,13 @@ const PositionListItem = ({ ) } -const ChartPositions = ({ +const ListPositions = ({ positions, usdPrices, rotated, ticksAtLimits, + baseCurrency, + quoteCurrency, }: { positions: Position[] usdPrices: { @@ -211,10 +230,10 @@ const ChartPositions = ({ [bound in Bound]: (boolean | undefined)[] } rotated: boolean + baseCurrency: Currency + quoteCurrency: Currency }) => { - const [tokenA, tokenB] = rotated - ? [positions[0].amount1.currency, positions[0].amount0.currency] - : [positions[0].amount0.currency, positions[0].amount1.currency] + const [tokenA, tokenB] = rotated ? [quoteCurrency, baseCurrency] : [baseCurrency, quoteCurrency] const upToSmall = useMedia(`(max-width: ${MEDIA_WIDTHS.upToSmall}px)`) const header = ( @@ -228,13 +247,8 @@ const ChartPositions = ({ {upToSmall ? null : ( <> - - {unwrappedToken(positions[0].amount0.currency).symbol} - - - - {unwrappedToken(positions[0].amount1.currency).symbol} - + {tokenA.symbol} + {tokenB.symbol} )} @@ -243,7 +257,7 @@ const ChartPositions = ({ PRICE RANGE{' '} - ({unwrappedToken(tokenB).symbol} per {unwrappedToken(tokenA).symbol}) + ({quoteCurrency.symbol} per {baseCurrency.symbol}) @@ -263,6 +277,8 @@ const ChartPositions = ({ [Bound.LOWER]: ticksAtLimits[Bound.LOWER][index], [Bound.UPPER]: ticksAtLimits[Bound.UPPER][index], }} + baseCurrency={baseCurrency} + quoteCurrency={quoteCurrency} /> ) }) @@ -274,4 +290,4 @@ const ChartPositions = ({ ) } -export default ChartPositions +export default ListPositions diff --git a/src/components/ProAmm/PoolPriceChart.tsx b/src/components/ProAmm/PoolPriceChart.tsx index e172170ae7..25d95bd025 100644 --- a/src/components/ProAmm/PoolPriceChart.tsx +++ b/src/components/ProAmm/PoolPriceChart.tsx @@ -92,8 +92,8 @@ const PoolPriceChart = ({ const [currentRate, setCurrentRate] = useState<{ price: string; time?: string } | null>(null) const theme = useTheme() - const formattedSymbol0 = shortString(poolData?.token0?.symbol, 5) - const formattedSymbol1 = shortString(poolData?.token1?.symbol, 5) + const formattedSymbol0 = shortString(poolData?.token0?.symbol, 7) + const formattedSymbol1 = shortString(poolData?.token1?.symbol, 7) const ratesData0 = ratesDatas?.[0] const ratesData1 = ratesDatas?.[1] diff --git a/src/components/WalletPopup/Transactions/TransactionItem.tsx b/src/components/WalletPopup/Transactions/TransactionItem.tsx index d6ce53fcc0..ad22aa1f7d 100644 --- a/src/components/WalletPopup/Transactions/TransactionItem.tsx +++ b/src/components/WalletPopup/Transactions/TransactionItem.tsx @@ -18,7 +18,7 @@ import PoolFarmLink from 'components/WalletPopup/Transactions/PoolFarmLink' import Status from 'components/WalletPopup/Transactions/Status' import { isTxsPendingTooLong } from 'components/WalletPopup/Transactions/helper' import { CancellingOrderInfo } from 'components/swapv2/LimitOrder/useCancellingOrders' -import { APP_PATHS } from 'constants/index' +import { APP_PATHS, ETHER_ADDRESS } from 'constants/index' import { NETWORKS_INFO } from 'constants/networks' import useTheme from 'hooks/useTheme' import { getAxelarScanUrl } from 'pages/CrossChain' @@ -32,7 +32,7 @@ import { TransactionExtraInfoStakeFarm, } from 'state/transactions/type' import { ExternalLink, ExternalLinkIcon } from 'theme' -import { getEtherscanLink } from 'utils' +import { getEtherscanLink, getNativeTokenLogo } from 'utils' const ItemWrapper = styled.div` border-bottom: 1px solid ${({ theme }) => theme.border}; @@ -77,7 +77,7 @@ const Description1Token = (transaction: TransactionDetails) => { //ex: +3knc -2usdt const Description2Token = (transaction: TransactionDetails) => { - const { extraInfo = {}, type } = transaction + const { extraInfo = {}, type, chainId } = transaction const { tokenAmountIn, tokenAmountOut, tokenSymbolIn, tokenSymbolOut, tokenAddressIn, tokenAddressOut } = extraInfo as TransactionExtraInfo2Token @@ -102,12 +102,14 @@ const Description2Token = (transaction: TransactionDetails) => { symbol={tokenSymbolOut} amount={tokenAmountOut} plus={signTokenOut} + logoURL={tokenAddressOut === ETHER_ADDRESS ? getNativeTokenLogo(chainId) : undefined} /> ) diff --git a/src/hooks/usePools.ts b/src/hooks/usePools.ts index cb42287a8d..e729a99e99 100644 --- a/src/hooks/usePools.ts +++ b/src/hooks/usePools.ts @@ -9,10 +9,10 @@ import { useActiveWeb3React } from 'hooks' import { useMultipleContractSingleData } from 'state/multicall/hooks' export enum PoolState { - LOADING, - NOT_EXISTS, - EXISTS, - INVALID, + LOADING = 'LOADING', + NOT_EXISTS = 'NOT_EXISTS', + EXISTS = 'EXISTS', + INVALID = 'INVALID', } const POOL_STATE_INTERFACE = new Interface(ProAmmPoolStateABI.abi) @@ -61,8 +61,8 @@ export function usePools( if (!token0 || !token1 || !fee) return [PoolState.INVALID, null] const { result: slot0, loading: slot0Loading, valid: slot0Valid } = slot0s[index] const { result: liquidity, loading: liquidityLoading, valid: liquidityValid } = liquidities[index] - if (!slot0Valid || !liquidityValid) return [PoolState.INVALID, null] if (slot0Loading || liquidityLoading) return [PoolState.LOADING, null] + if (!slot0Valid || !liquidityValid) return [PoolState.INVALID, null] if (!slot0 || !liquidity) return [PoolState.NOT_EXISTS, null] if (!slot0.sqrtP || slot0.sqrtP.eq(0)) return [PoolState.NOT_EXISTS, null] diff --git a/src/hooks/useProAmmDerivedPositionInfo.ts b/src/hooks/useProAmmDerivedPositionInfo.ts index 770cbbaecc..011dd57c96 100644 --- a/src/hooks/useProAmmDerivedPositionInfo.ts +++ b/src/hooks/useProAmmDerivedPositionInfo.ts @@ -3,17 +3,18 @@ import { Pool, Position } from '@kyberswap/ks-sdk-elastic' import { PositionDetails } from 'types/position' import { useCurrency } from './Tokens' -import { usePool } from './usePools' +import { PoolState, usePool } from './usePools' export function useProAmmDerivedPositionInfo(positionDetails: PositionDetails | undefined): { position: Position | undefined pool: Pool | undefined + loading: boolean } { const currency0 = useCurrency(positionDetails?.token0) const currency1 = useCurrency(positionDetails?.token1) // construct pool data - const [, pool] = usePool(currency0 ?? undefined, currency1 ?? undefined, positionDetails?.fee) + const [poolState, pool] = usePool(currency0 ?? undefined, currency1 ?? undefined, positionDetails?.fee) let position = undefined if (pool && positionDetails) { @@ -24,9 +25,9 @@ export function useProAmmDerivedPositionInfo(positionDetails: PositionDetails | tickUpper: positionDetails.tickUpper, }) } - return { position, pool: pool ?? undefined, + loading: poolState === PoolState.LOADING, } } diff --git a/src/hooks/useSwapCallbackV3.ts b/src/hooks/useSwapCallbackV3.ts index 5ec98eeb29..9d653e3a9a 100644 --- a/src/hooks/useSwapCallbackV3.ts +++ b/src/hooks/useSwapCallbackV3.ts @@ -3,7 +3,7 @@ import { TransactionResponse } from '@ethersproject/providers' import { useCallback } from 'react' import { useSwapFormContext } from 'components/SwapForm/SwapFormContext' -import { ZERO_ADDRESS_SOLANA } from 'constants/index' +import { ETHER_ADDRESS } from 'constants/index' import { useActiveWeb3React, useWeb3React } from 'hooks/index' import useENS from 'hooks/useENS' import { useTransactionAdder } from 'state/transactions/hooks' @@ -39,8 +39,8 @@ const useSwapCallbackV3 = (isPermitSwap?: boolean) => { const inputSymbol = inputAmount.currency.symbol const outputSymbol = outputAmount.currency.symbol - const inputAddress = inputAmount.currency.isNative ? ZERO_ADDRESS_SOLANA : inputAmount.currency.address - const outputAddress = outputAmount.currency.isNative ? ZERO_ADDRESS_SOLANA : outputAmount.currency.address + const inputAddress = inputAmount.currency.isNative ? ETHER_ADDRESS : inputAmount.currency.address + const outputAddress = outputAmount.currency.isNative ? ETHER_ADDRESS : outputAmount.currency.address const inputAmountStr = formatCurrencyAmount(inputAmount, 6) const outputAmountStr = formatCurrencyAmount(outputAmount, 6) diff --git a/src/pages/AddLiquidityV2/index.tsx b/src/pages/AddLiquidityV2/index.tsx index c47617d3cc..170fa347b1 100644 --- a/src/pages/AddLiquidityV2/index.tsx +++ b/src/pages/AddLiquidityV2/index.tsx @@ -29,7 +29,6 @@ import HoverInlineText from 'components/HoverInlineText' import { Swap as SwapIcon, TwoWayArrow } from 'components/Icons' import LiquidityChartRangeInput from 'components/LiquidityChartRangeInput' import { AddRemoveTabs, LiquidityAction } from 'components/NavigationTabs' -import ChartPositions from 'components/ProAmm/ChartPositions' import ListPositions from 'components/ProAmm/ListPositions' import PoolPriceChart from 'components/ProAmm/PoolPriceChart' import ProAmmPoolInfo from 'components/ProAmm/ProAmmPoolInfo' @@ -46,7 +45,7 @@ import Tooltip, { MouseoverTooltip } from 'components/Tooltip' import TransactionConfirmationModal, { ConfirmationModalContent } from 'components/TransactionConfirmationModal' import { TutorialType } from 'components/Tutorial' import { Dots } from 'components/swapv2/styleds' -import { APP_PATHS } from 'constants/index' +import { APP_PATHS, ETHER_ADDRESS } from 'constants/index' import { ELASTIC_NOT_SUPPORTED } from 'constants/networks' import { EVMNetworkInfo } from 'constants/networks/type' import { NativeCurrencies } from 'constants/tokens' @@ -81,7 +80,6 @@ import { usePairFactor } from 'state/topTokens/hooks' import { useTransactionAdder } from 'state/transactions/hooks' import { TRANSACTION_TYPE } from 'state/transactions/type' import { useDegenModeManager, useUserSlippageTolerance } from 'state/user/hooks' -import { VIEW_MODE } from 'state/user/reducer' import { ExternalLink, MEDIA_WIDTHS, StyledInternalLink, TYPE } from 'theme' import { basisPointsToPercent, calculateGasMargin, formattedNum } from 'utils' import { currencyId } from 'utils/currencyId' @@ -89,7 +87,6 @@ import { friendlyError } from 'utils/errorMessage' import { maxAmountSpend } from 'utils/maxAmountSpend' import { formatDisplayNumber, toString } from 'utils/numbers' import { SLIPPAGE_STATUS, checkRangeSlippage } from 'utils/slippage' -import { unwrappedToken } from 'utils/wrappedCurrency' import DisclaimerERC20 from './components/DisclaimerERC20' import NewPoolNote from './components/NewPoolNote' @@ -500,8 +497,8 @@ export default function AddLiquidity() { tokenAmountOut, tokenSymbolIn: baseCurrency.symbol, tokenSymbolOut: quoteCurrency.symbol, - tokenAddressIn: baseCurrency.wrapped.address, - tokenAddressOut: quoteCurrency.wrapped.address, + tokenAddressIn: baseCurrency.isNative ? ETHER_ADDRESS : baseCurrency.address, + tokenAddressOut: quoteCurrency.isNative ? ETHER_ADDRESS : quoteCurrency.address, }, }) } @@ -1241,10 +1238,9 @@ export default function AddLiquidity() { ) - // const [viewMode] = useViewMode() - const viewMode = VIEW_MODE.LIST const [rotated, setRotated] = useState(false) const modalContent = () => { + if (!baseCurrency || !quoteCurrency) return null if (!isMultiplePosition) { return ( position && ( @@ -1252,11 +1248,11 @@ export default function AddLiquidity() { - {viewMode === VIEW_MODE.LIST ? ( - - ) : ( - - )} + ) } const poolStat = poolDatas?.[poolAddress] || poolDatas?.[poolAddress.toLowerCase()] - const poolStatRef = useRef(poolStat) - if (poolStat) { - poolStatRef.current = poolStat - } const openShareModal = useOpenModal(ApplicationModal.SHARE) const userLiquidityPositionsQueryResult = useUserProMMPositions(usdPrices) @@ -1605,14 +1590,14 @@ export default function AddLiquidity() { ) : ( - poolStatRef.current && ( + poolStat && ( <> Pool Stats { diff --git a/src/pages/IncreaseLiquidity/index.tsx b/src/pages/IncreaseLiquidity/index.tsx index 6156838b95..eb309e0a55 100644 --- a/src/pages/IncreaseLiquidity/index.tsx +++ b/src/pages/IncreaseLiquidity/index.tsx @@ -6,7 +6,7 @@ import { BigNumber } from 'ethers' import JSBI from 'jsbi' import { useCallback, useEffect, useState } from 'react' import { AlertTriangle } from 'react-feather' -import { Navigate, useNavigate, useParams } from 'react-router-dom' +import { Link, Navigate, useNavigate, useParams } from 'react-router-dom' import { useMedia, usePrevious } from 'react-use' import { Box, Flex, Text } from 'rebass' import styled from 'styled-components' @@ -55,7 +55,7 @@ import { TokenId, TokenInputWrapper, } from 'pages/RemoveLiquidityProAmm/styled' -import { useWalletModalToggle } from 'state/application/hooks' +import { useNetworkModalToggle, useWalletModalToggle } from 'state/application/hooks' import { useProAmmDerivedMintInfo, useProAmmMintActionHandlers, useProAmmMintState } from 'state/mint/proamm/hooks' import { Field } from 'state/mint/proamm/type' import { useSingleCallResult } from 'state/multicall/hooks' @@ -94,6 +94,7 @@ export default function IncreaseLiquidity() { const navigate = useNavigate() const theme = useTheme() const toggleWalletModal = useWalletModalToggle() // toggle wallet when disconnected + const toggleNetworkModal = useNetworkModalToggle() const [isDegenMode] = useDegenModeManager() const addTransactionWithType = useTransactionAdder() @@ -108,7 +109,7 @@ export default function IncreaseLiquidity() { const positionManager = useProAmmNFTPositionManagerReadingContract() // check for existing position if tokenId in url - const { position: existingPositionDetails } = useProAmmPositionsFromTokenId( + const { position: existingPositionDetails, loading: loadingPosition } = useProAmmPositionsFromTokenId( tokenId ? BigNumber.from(tokenId) : undefined, ) @@ -122,7 +123,7 @@ export default function IncreaseLiquidity() { (networkInfo as EVMNetworkInfo).elastic.farmV2S?.map(item => item.toLowerCase()).includes(owner?.toLowerCase()) : false - const { position: existingPosition } = useProAmmDerivedPositionInfo(existingPositionDetails) + const { position: existingPosition, loading: loadingInfo } = useProAmmDerivedPositionInfo(existingPositionDetails) // fee selection from url const feeAmount: FeeAmount | undefined = @@ -697,8 +698,25 @@ export default function IncreaseLiquidity() { - ) : ( + ) : loadingPosition || loadingInfo ? ( + ) : ( + + + 404 + + + + Position {tokenId} does not exist on {networkInfo.name} + + + + + Switch chain + {' '} + or Go back to My Pools + + )}