diff --git a/src/components/Account/AccountBalancesTable/index.tsx b/src/components/Account/AccountBalancesTable/index.tsx index 3edfba9c..774aef81 100644 --- a/src/components/Account/AccountBalancesTable/index.tsx +++ b/src/components/Account/AccountBalancesTable/index.tsx @@ -1,5 +1,5 @@ import classNames from 'classnames' -import { useLocation, useNavigate } from 'react-router-dom' +import { useLocation, useNavigate, useSearchParams } from 'react-router-dom' import useAccountBalancesColumns from 'components/Account/AccountBalancesTable/Columns/useAccountBalancesColumns' import useAccountBalanceData from 'components/Account/AccountBalancesTable/useAccountBalanceData' @@ -22,6 +22,7 @@ interface Props { } export default function AccountBalancesTable(props: Props) { + const [searchParams] = useSearchParams() const { account, lendingData, borrowingData, tableBodyClassName, hideCard } = props const currentAccount = useCurrentAccount() const navigate = useNavigate() @@ -55,7 +56,7 @@ export default function AccountBalancesTable(props: Props) { color='tertiary' onClick={() => { if (currentAccount?.id !== account.id) { - navigate(getRoute(getPage(pathname), address, account.id)) + navigate(getRoute(getPage(pathname), searchParams, address, account.id)) } useStore.setState({ focusComponent: { diff --git a/src/components/Account/AccountCreateFirst.tsx b/src/components/Account/AccountCreateFirst.tsx index 0c8c38d1..e2ea005e 100644 --- a/src/components/Account/AccountCreateFirst.tsx +++ b/src/components/Account/AccountCreateFirst.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect } from 'react' -import { useLocation, useNavigate } from 'react-router-dom' +import { useLocation, useNavigate, useSearchParams } from 'react-router-dom' import AccountFundFullPage from 'components/Account/AccountFund/AccountFundFullPage' import FullOverlayContent from 'components/FullOverlayContent' @@ -14,6 +14,7 @@ export default function AccountCreateFirst() { const address = useStore((s) => s.address) const createAccount = useStore((s) => s.createAccount) const [isCreating, setIsCreating] = useToggle(false) + const [searchParams] = useSearchParams() useEffect(() => { if (!address) useStore.setState({ focusComponent: { component: } }) @@ -24,7 +25,7 @@ export default function AccountCreateFirst() { const accountId = await createAccount('default') setIsCreating(false) if (accountId) { - navigate(getRoute(getPage(pathname), address, accountId)) + navigate(getRoute(getPage(pathname), searchParams, address, accountId)) useStore.setState({ focusComponent: { component: , @@ -34,7 +35,7 @@ export default function AccountCreateFirst() { }, }) } - }, [createAccount, navigate, pathname, address, setIsCreating]) + }, [setIsCreating, createAccount, navigate, pathname, searchParams, address]) return ( s.address) const { data: accountIds } = useAccountIds(address, true, true) + const [searchParams] = useSearchParams() useEffect(() => { if (!currentAccountId) return @@ -54,7 +55,7 @@ export default function AccountList(props: Props) { onClick={() => { if (isActive) return useStore.setState({ accountDeleteModal: null }) - navigate(getRoute(getPage(pathname), address, accountId)) + navigate(getRoute(getPage(pathname), searchParams, address, accountId)) }} title={
diff --git a/src/components/Account/AccountMenuContent.tsx b/src/components/Account/AccountMenuContent.tsx index ad63b4fe..8265ef55 100644 --- a/src/components/Account/AccountMenuContent.tsx +++ b/src/components/Account/AccountMenuContent.tsx @@ -1,6 +1,6 @@ import classNames from 'classnames' import { useCallback } from 'react' -import { useLocation, useNavigate } from 'react-router-dom' +import { useLocation, useNavigate, useSearchParams } from 'react-router-dom' import AccountCreateFirst from 'components/Account/AccountCreateFirst' import AccountFund from 'components/Account/AccountFund/AccountFundFullPage' @@ -33,6 +33,7 @@ export default function AccountMenuContent() { const address = useStore((s) => s.address) const { data: accountIds } = useAccountIds(address, true, true) const accountId = useAccountId() + const [searchParams] = useSearchParams() const createAccount = useStore((s) => s.createAccount) const baseCurrency = useStore((s) => s.baseCurrency) @@ -63,7 +64,7 @@ export default function AccountMenuContent() { setIsCreating(false) if (accountId) { - navigate(getRoute(getPage(pathname), address, accountId)) + navigate(getRoute(getPage(pathname), searchParams, address, accountId)) if (lendAssets) enableAutoLendAccountId(accountId) useStore.setState({ focusComponent: { @@ -80,6 +81,7 @@ export default function AccountMenuContent() { createAccount, navigate, pathname, + searchParams, address, lendAssets, enableAutoLendAccountId, diff --git a/src/components/Asset/AssetSymbol.tsx b/src/components/Asset/AssetSymbol.tsx new file mode 100644 index 00000000..becc4d71 --- /dev/null +++ b/src/components/Asset/AssetSymbol.tsx @@ -0,0 +1,16 @@ +import Text from 'components/Text' + +interface Props { + symbol: string +} +export default function AssetSymbol(props: Props) { + return ( + + {props.symbol} + + ) +} diff --git a/src/components/Earn/Tab.tsx b/src/components/Earn/Tab.tsx index 1495c47c..d9431e34 100644 --- a/src/components/Earn/Tab.tsx +++ b/src/components/Earn/Tab.tsx @@ -1,5 +1,5 @@ import classNames from 'classnames' -import { NavLink, useParams } from 'react-router-dom' +import { NavLink, useParams, useSearchParams } from 'react-router-dom' import useAccountId from 'hooks/useAccountId' import { getRoute } from 'utils/route' @@ -15,13 +15,14 @@ interface Props { export default function Tab(props: Props) { const accountId = useAccountId() const { address } = useParams() + const [searchParams] = useSearchParams() return (
{props.tabs.map((tab, index) => ( { useStore.setState({ accountDeleteModal: null }) @@ -38,9 +39,18 @@ function AccountDeleteModal(props: Props) { const deleteAccountHandler = useCallback(() => { const options = { accountId: modal.id, lends: modal.lends } deleteAccount(options) - navigate(getRoute(getPage(pathname), address)) + navigate(getRoute(getPage(pathname), searchParams, address)) closeDeleteAccountModal() - }, [modal, deleteAccount, navigate, pathname, address, closeDeleteAccountModal]) + }, [ + modal.id, + modal.lends, + deleteAccount, + navigate, + pathname, + searchParams, + address, + closeDeleteAccountModal, + ]) const depositsAndLends = useMemo( () => combineBNCoins([...modal.deposits, ...modal.lends]), @@ -58,7 +68,7 @@ function AccountDeleteModal(props: Props) { text: 'Repay Debts', icon: , onClick: () => { - navigate(getRoute('borrow', address, accountId)) + navigate(getRoute('borrow', searchParams, address, accountId)) closeDeleteAccountModal() }, }} @@ -75,7 +85,7 @@ function AccountDeleteModal(props: Props) { text: 'Close Positions', icon: , onClick: () => { - navigate(getRoute('farm', address, accountId)) + navigate(getRoute('farm', searchParams, address, accountId)) closeDeleteAccountModal() }, }} diff --git a/src/components/Navigation/DesktopNavigation.tsx b/src/components/Navigation/DesktopNavigation.tsx index 859b1b80..e0ad5bee 100644 --- a/src/components/Navigation/DesktopNavigation.tsx +++ b/src/components/Navigation/DesktopNavigation.tsx @@ -1,6 +1,7 @@ import { useShuttle } from '@delphi-labs/shuttle-react' import classNames from 'classnames' import { useMemo } from 'react' +import { useSearchParams } from 'react-router-dom' import Button from 'components/Button' import { menuTree } from 'components/Header/DesktopHeader' @@ -18,7 +19,7 @@ export default function DesktopNavigation() { const walletId = (recentWallet?.providerId as WalletID) ?? WalletID.Keplr const address = useStore((s) => s.address) const accountId = useAccountId() - + const [searchParams] = useSearchParams() const focusComponent = useStore((s) => s.focusComponent) const menu = useMemo(() => menuTree(walletId), [walletId]) @@ -36,7 +37,7 @@ export default function DesktopNavigation() { : 'flex flex-1 items-center relative z-50', )} > - + @@ -47,7 +48,9 @@ export default function DesktopNavigation() {
) } + +interface InterestItemProps { + market: PerpsMarket | null + type: 'long' | 'short' +} +function InterestItem(props: InterestItemProps) { + if (!props.market) return + + return ( +
+ + +
+ ) +} diff --git a/src/components/Portfolio/Account/BreadCrumbs.tsx b/src/components/Portfolio/Account/BreadCrumbs.tsx index 88d94e4d..db43314a 100644 --- a/src/components/Portfolio/Account/BreadCrumbs.tsx +++ b/src/components/Portfolio/Account/BreadCrumbs.tsx @@ -1,4 +1,4 @@ -import { NavLink, useParams } from 'react-router-dom' +import { NavLink, useParams, useSearchParams } from 'react-router-dom' import { ArrowRight } from 'components/Icons' import Text from 'components/Text' @@ -12,10 +12,11 @@ interface Props { export default function PortfolioAccountPageHeader(props: Props) { const { address } = useParams() const selectedAccountId = useAccountId() + const [searchParams] = useSearchParams() return (
- + Portfolio diff --git a/src/components/Portfolio/Card/index.tsx b/src/components/Portfolio/Card/index.tsx index f21d49a7..7a233b61 100644 --- a/src/components/Portfolio/Card/index.tsx +++ b/src/components/Portfolio/Card/index.tsx @@ -1,6 +1,6 @@ import classNames from 'classnames' import { ReactNode, useMemo } from 'react' -import { NavLink, useParams } from 'react-router-dom' +import { NavLink, useParams, useSearchParams } from 'react-router-dom' import { FormattedNumber } from 'components/FormattedNumber' import Loading from 'components/Loading' @@ -36,6 +36,7 @@ export default function PortfolioCard(props: Props) { const { allAssets: lendingAssets } = useLendingMarketAssetsTableData() const { data } = useBorrowMarketAssetsTableData(false) const { data: hlsStrategies } = useHLSStakingAssets() + const [searchParams] = useSearchParams() const borrowAssets = useMemo(() => data?.allAssets || [], [data]) const [reduceMotion] = useLocalStorage( @@ -111,7 +112,12 @@ export default function PortfolioCard(props: Props) { return ( {
} contentClassName='px-0.5 pb-0.5 h-full' - className='min-h-[55vh]' + className='min-h-[55vh] h-full' >
diff --git a/src/components/Trade/TradeModule/AssetSelector/AssetItem.tsx b/src/components/Trade/TradeModule/AssetSelector/AssetItem.tsx index a1723efe..27512dce 100644 --- a/src/components/Trade/TradeModule/AssetSelector/AssetItem.tsx +++ b/src/components/Trade/TradeModule/AssetSelector/AssetItem.tsx @@ -1,4 +1,5 @@ import AssetImage from 'components/Asset/AssetImage' +import AssetSymbol from 'components/Asset/AssetSymbol' import DisplayCurrency from 'components/DisplayCurrency' import { FormattedNumber } from 'components/FormattedNumber' import { StarFilled, StarOutlined } from 'components/Icons' @@ -53,9 +54,7 @@ export default function AssetItem(props: Props) { {asset.name} -
- {asset.symbol} -
+
{props.balances.length > 0 && (
diff --git a/src/components/Wallet/WalletConnectedButton.tsx b/src/components/Wallet/WalletConnectedButton.tsx index 11417723..26288b8f 100644 --- a/src/components/Wallet/WalletConnectedButton.tsx +++ b/src/components/Wallet/WalletConnectedButton.tsx @@ -1,10 +1,10 @@ import { useShuttle } from '@delphi-labs/shuttle-react' import BigNumber from 'bignumber.js' import classNames from 'classnames' -import { useCallback, useEffect, useState } from 'react' -import { useLocation, useNavigate } from 'react-router-dom' -import useClipboard from 'react-use-clipboard' import { resolvePrimaryDomainByAddress } from 'ibc-domains-sdk' +import { useCallback, useEffect, useState } from 'react' +import { useLocation, useNavigate, useSearchParams } from 'react-router-dom' +import useClipboard from 'react-use-clipboard' import Button from 'components/Button' import { CircularProgress } from 'components/CircularProgress' @@ -44,6 +44,7 @@ export default function WalletConnectedButton() { const { data: icnsData, isLoading: isLoadingICNS } = useICNSDomain(address) const navigate = useNavigate() const { pathname } = useLocation() + const [searchParams] = useSearchParams() // --------------- // LOCAL STATE @@ -87,7 +88,7 @@ export default function WalletConnectedButton() { }) } - navigate(getRoute(getPage(pathname))) + navigate(getRoute(getPage(pathname), searchParams)) } useEffect(() => { diff --git a/src/components/Wallet/WalletFetchBalancesAndAccounts.tsx b/src/components/Wallet/WalletFetchBalancesAndAccounts.tsx index 426a19dc..411f6bbd 100644 --- a/src/components/Wallet/WalletFetchBalancesAndAccounts.tsx +++ b/src/components/Wallet/WalletFetchBalancesAndAccounts.tsx @@ -1,5 +1,5 @@ import { Suspense, useEffect, useMemo } from 'react' -import { useLocation, useNavigate, useParams } from 'react-router-dom' +import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom' import AccountCreateFirst from 'components/Account/AccountCreateFirst' import { CircularProgress } from 'components/CircularProgress' @@ -28,6 +28,8 @@ function FetchLoading() { function Content() { const address = useStore((s) => s.address) + const [searchParams] = useSearchParams() + const { address: urlAddress } = useParams() const urlAccountId = useAccountId() const navigate = useNavigate() @@ -48,7 +50,7 @@ function Content() { useEffect(() => { const page = getPage(pathname) if (page === 'portfolio' && urlAddress && urlAddress !== address) { - navigate(getRoute(page, urlAddress as string)) + navigate(getRoute(page, searchParams, urlAddress as string)) useStore.setState({ balances: walletBalances, focusComponent: null }) return } @@ -60,7 +62,7 @@ function Content() { ) { const currentAccountIsHLS = urlAccountId && !accountIds.includes(urlAccountId) const currentAccount = currentAccountIsHLS || !urlAccountId ? accountIds[0] : urlAccountId - navigate(getRoute(page, address, currentAccount)) + navigate(getRoute(page, searchParams, address, currentAccount)) useStore.setState({ balances: walletBalances, focusComponent: null }) } }, [ @@ -72,6 +74,7 @@ function Content() { walletBalances, urlAddress, urlAccountId, + searchParams, ]) if (isLoadingAccounts || isLoadingBalances) return diff --git a/src/hooks/perps/usePerpsMarket.ts b/src/hooks/perps/usePerpsMarket.ts new file mode 100644 index 00000000..5b0490f0 --- /dev/null +++ b/src/hooks/perps/usePerpsMarket.ts @@ -0,0 +1,36 @@ +import { useSearchParams } from 'react-router-dom' +import useSWR from 'swr' + +import { ASSETS } from 'constants/assets' +import { getAssetBySymbol } from 'utils/assets' +import { BN } from 'utils/helpers' + +export default function usePerpsMarket() { + const [searchParams] = useSearchParams() + const perpsMarket = searchParams.get('perpsMarket') || ASSETS[0].symbol + + const asset = getAssetBySymbol(perpsMarket) + + return useSWR( + `perpsMarket/${perpsMarket}`, + async () => { + await delay(3000) + if (!asset) return null + return { + asset, + fundingRate: BN(0.001432), + openInterest: { + long: BN(92901203), + short: BN(129891203), + }, + } as PerpsMarket + }, + { + fallbackData: null, + }, + ) +} + +function delay(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} diff --git a/src/pages/PortfolioAccountPage.tsx b/src/pages/PortfolioAccountPage.tsx index 84a9b835..6759b276 100644 --- a/src/pages/PortfolioAccountPage.tsx +++ b/src/pages/PortfolioAccountPage.tsx @@ -1,4 +1,4 @@ -import { useNavigate, useParams } from 'react-router-dom' +import { useNavigate, useParams, useSearchParams } from 'react-router-dom' import MigrationBanner from 'components/MigrationBanner' import Balances from 'components/Portfolio/Account/Balances' @@ -12,9 +12,10 @@ export default function PortfolioAccountPage() { const selectedAccountId = useAccountId() const { address, accountId } = useParams() const navigate = useNavigate() + const [searchParams] = useSearchParams() if (!accountId) { - navigate(getRoute('portfolio', address, selectedAccountId)) + navigate(getRoute('portfolio', searchParams, address, selectedAccountId)) return null } diff --git a/src/types/interfaces/asset.d.ts b/src/types/interfaces/asset.d.ts index 16bbe89b..e86091e6 100644 --- a/src/types/interfaces/asset.d.ts +++ b/src/types/interfaces/asset.d.ts @@ -144,3 +144,12 @@ interface StakingApr { unbondingDelay: number unbondingPeriod: number } + +interface PerpsMarket { + asset: Asset + fundingRate: BigNumber + openInterest: { + long: BigNumber + short: BigNumber + } +} diff --git a/src/utils/route.ts b/src/utils/route.ts index df38bd2f..7251d9b5 100644 --- a/src/utils/route.ts +++ b/src/utils/route.ts @@ -1,4 +1,9 @@ -export function getRoute(page: Page, address?: string, accountId?: string | null) { +export function getRoute( + page: Page, + searchParams: URLSearchParams, + address?: string, + accountId?: string | null, +) { let nextUrl = '' if (address) { @@ -9,10 +14,13 @@ export function getRoute(page: Page, address?: string, accountId?: string | null let url = new URL(nextUrl, 'https://app.marsprotocol.io') + Array.from(searchParams?.entries() || []).map(([key, value]) => + url.searchParams.append(key, value), + ) + if (accountId) { - url.searchParams.append('accountId', accountId) - } else { url.searchParams.delete('accountId') + url.searchParams.append('accountId', accountId) } return url.pathname + url.search diff --git a/tailwind.config.js b/tailwind.config.js index f8e3f952..afe6345c 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -41,12 +41,14 @@ module.exports = { '@nav-3/navigation:inline-block', '@nav-4/navigation:inline-block', '@nav-5/navigation:inline-block', + '@nav-6/navigation:inline-block', '@nav-0/navigation:hidden', '@nav-1/navigation:hidden', '@nav-2/navigation:hidden', '@nav-3/navigation:hidden', '@nav-4/navigation:hidden', '@nav-5/navigation:hidden', + '@nav-6/navigation:hidden', ], theme: { extend: { @@ -141,6 +143,7 @@ module.exports = { 'nav-3': '400px', 'nav-4': '500px', 'nav-5': '600px', + 'nav-6': '650px', }, fontFamily: { sans: ['Inter', 'sans-serif'],