chore(trading): routing and link changes (#4738)
This commit is contained in:
parent
5db3453ba5
commit
3e30f053ff
31
apps/trading/client-pages/assets/assets.tsx
Normal file
31
apps/trading/client-pages/assets/assets.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { Links } from '../../lib/links';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { NavLink, Outlet } from 'react-router-dom';
|
||||||
|
|
||||||
|
export const Assets = () => {
|
||||||
|
const linkClasses = ({ isActive }: { isActive: boolean }) => {
|
||||||
|
return classNames('border-b-2 border-transparent', {
|
||||||
|
'border-vega-yellow': isActive,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="max-w-[500px] px-4 mx-auto my-8">
|
||||||
|
<nav className="flex mb-6 text-lg gap-4">
|
||||||
|
<NavLink to={Links.DEPOSIT()} className={linkClasses}>
|
||||||
|
{t('Deposit')}
|
||||||
|
</NavLink>
|
||||||
|
<NavLink to={Links.WITHDRAW()} className={linkClasses}>
|
||||||
|
{t('Withdraw')}
|
||||||
|
</NavLink>
|
||||||
|
<NavLink to={Links.TRANSFER()} className={linkClasses}>
|
||||||
|
{t('Transfer')}
|
||||||
|
</NavLink>
|
||||||
|
</nav>
|
||||||
|
<div className="pt-4 border-t md:p-6 md:border md:rounded-xl border-default">
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
1
apps/trading/client-pages/assets/index.ts
Normal file
1
apps/trading/client-pages/assets/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { Assets } from './assets';
|
44
apps/trading/client-pages/deposit/deposit-get-started.tsx
Normal file
44
apps/trading/client-pages/deposit/deposit-get-started.tsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { Intent, TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { GetStartedCheckList } from '../../components/welcome-dialog';
|
||||||
|
import {
|
||||||
|
useGetOnboardingStep,
|
||||||
|
useOnboardingStore,
|
||||||
|
OnboardingStep,
|
||||||
|
} from '../../components/welcome-dialog/use-get-onboarding-step';
|
||||||
|
import { Links } from '../../lib/links';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
export const DepositGetStarted = () => {
|
||||||
|
const onboardingDismissed = useOnboardingStore((store) => store.dismissed);
|
||||||
|
const dismiss = useOnboardingStore((store) => store.dismiss);
|
||||||
|
const step = useGetOnboardingStep();
|
||||||
|
const wrapperClasses = classNames(
|
||||||
|
'flex flex-col py-4 px-6 gap-4 rounded',
|
||||||
|
'bg-vega-blue-300 dark:bg-vega-blue-700',
|
||||||
|
'border border-vega-blue-350 dark:border-vega-blue-650'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Dont show unless still onboarding
|
||||||
|
if (onboardingDismissed) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="pt-6 border-t border-default">
|
||||||
|
<div className={wrapperClasses}>
|
||||||
|
<h3 className="text-lg">{t('Get started')}</h3>
|
||||||
|
<GetStartedCheckList />
|
||||||
|
{step > OnboardingStep.ONBOARDING_DEPOSIT_STEP && (
|
||||||
|
<TradingAnchorButton
|
||||||
|
href={Links.HOME()}
|
||||||
|
onClick={() => dismiss()}
|
||||||
|
intent={Intent.Info}
|
||||||
|
>
|
||||||
|
{t('Start trading')}
|
||||||
|
</TradingAnchorButton>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
30
apps/trading/client-pages/deposit/deposit.spec.tsx
Normal file
30
apps/trading/client-pages/deposit/deposit.spec.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { Deposit } from './deposit';
|
||||||
|
|
||||||
|
jest.mock('@vegaprotocol/deposits', () => ({
|
||||||
|
DepositContainer: ({ assetId }: { assetId?: string }) => (
|
||||||
|
<div data-testid="assetId">{assetId}</div>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('./deposit-get-started', () => ({
|
||||||
|
DepositGetStarted: () => <div>DepositGetStarted</div>,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const renderJsx = (route = '/deposit') => {
|
||||||
|
render(
|
||||||
|
<MemoryRouter initialEntries={[route]}>
|
||||||
|
<Deposit />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Deposit page', () => {
|
||||||
|
it('assetId should be passed down', () => {
|
||||||
|
const assetId = 'foo';
|
||||||
|
const route = '/deposit?assetId=' + assetId;
|
||||||
|
renderJsx(route);
|
||||||
|
expect(screen.getByTestId('assetId')).toHaveTextContent(assetId);
|
||||||
|
});
|
||||||
|
});
|
@ -1,59 +1,14 @@
|
|||||||
import { DepositContainer } from '@vegaprotocol/deposits';
|
import { DepositContainer } from '@vegaprotocol/deposits';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { Intent, TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
|
import { DepositGetStarted } from './deposit-get-started';
|
||||||
import { GetStartedCheckList } from '../../components/welcome-dialog';
|
|
||||||
import {
|
|
||||||
useGetOnboardingStep,
|
|
||||||
useOnboardingStore,
|
|
||||||
OnboardingStep,
|
|
||||||
} from '../../components/welcome-dialog/use-get-onboarding-step';
|
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
export const Deposit = () => {
|
export const Deposit = () => {
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
const assetId = searchParams.get('assetId') || undefined;
|
||||||
return (
|
return (
|
||||||
<div className="max-w-[600px] px-4 py-8 mx-auto lg:px-8">
|
<div className="flex flex-col gap-6">
|
||||||
<h1 className="mb-6 text-4xl uppercase xl:text-5xl font-alpha calt">
|
<DepositContainer assetId={assetId} />
|
||||||
{t('Deposit')}
|
<DepositGetStarted />
|
||||||
</h1>
|
|
||||||
<div className="flex flex-col gap-6">
|
|
||||||
<DepositContainer />
|
|
||||||
<DepositGetStarted />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const DepositGetStarted = () => {
|
|
||||||
const onboardingDismissed = useOnboardingStore((store) => store.dismissed);
|
|
||||||
const dismiss = useOnboardingStore((store) => store.dismiss);
|
|
||||||
const step = useGetOnboardingStep();
|
|
||||||
const wrapperClasses = classNames(
|
|
||||||
'flex flex-col py-4 px-6 gap-4 rounded',
|
|
||||||
'bg-vega-blue-300 dark:bg-vega-blue-700',
|
|
||||||
'border border-vega-blue-350 dark:border-vega-blue-650'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Dont show unless still onboarding
|
|
||||||
if (onboardingDismissed) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="pt-6 border-t border-default">
|
|
||||||
<div className={wrapperClasses}>
|
|
||||||
<h3 className="text-lg">{t('Get started')}</h3>
|
|
||||||
<GetStartedCheckList />
|
|
||||||
{step > OnboardingStep.ONBOARDING_DEPOSIT_STEP && (
|
|
||||||
<TradingAnchorButton
|
|
||||||
href={Links[Routes.HOME]()}
|
|
||||||
onClick={() => dismiss()}
|
|
||||||
intent={Intent.Info}
|
|
||||||
>
|
|
||||||
{t('Start trading')}
|
|
||||||
</TradingAnchorButton>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2,47 +2,45 @@ import { t } from '@vegaprotocol/i18n';
|
|||||||
|
|
||||||
export const Disclaimer = () => {
|
export const Disclaimer = () => {
|
||||||
return (
|
return (
|
||||||
<div className="py-16 px-8 flex w-full justify-center">
|
<>
|
||||||
<div className="lg:min-w-[700px] min-w-[300px] max-w-[700px]">
|
<h1 className="text-4xl uppercase xl:text-5xl font-alpha calt">
|
||||||
<h1 className="text-4xl xl:text-5xl uppercase font-alpha calt">
|
{t('Disclaimer')}
|
||||||
{t('Disclaimer')}
|
</h1>
|
||||||
</h1>
|
<p className="mt-10 mb-6">
|
||||||
<p className="mb-6 mt-10">
|
{t(
|
||||||
{t(
|
'Vega is a decentralised peer-to-peer protocol that can be used to trade derivatives with cryptoassets. The Vega Protocol is an implementation layer (layer one) protocol made of free, public, open-source or source-available software. Use of the Vega Protocol involves various risks, including but not limited to, losses while digital assets are supplied to the Vega Protocol and losses due to the fluctuation of prices of assets.'
|
||||||
'Vega is a decentralised peer-to-peer protocol that can be used to trade derivatives with cryptoassets. The Vega Protocol is an implementation layer (layer one) protocol made of free, public, open-source or source-available software. Use of the Vega Protocol involves various risks, including but not limited to, losses while digital assets are supplied to the Vega Protocol and losses due to the fluctuation of prices of assets.'
|
)}
|
||||||
)}
|
</p>
|
||||||
</p>
|
<p className="mb-6">
|
||||||
<p className="mb-6">
|
{t(
|
||||||
{t(
|
'Before using the Vega Protocol, review the relevant documentation at docs.vega.xyz to make sure that you understand how it works. Conduct your own due diligence and consult your financial advisor before making any investment decisions.'
|
||||||
'Before using the Vega Protocol, review the relevant documentation at docs.vega.xyz to make sure that you understand how it works. Conduct your own due diligence and consult your financial advisor before making any investment decisions.'
|
)}
|
||||||
)}
|
</p>
|
||||||
</p>
|
<p className="mb-6">
|
||||||
<p className="mb-6">
|
{t(
|
||||||
{t(
|
'As described in the Vega Protocol core license, the Vega Protocol is provided “as is”, at your own risk, and without warranties of any kind. Although Gobalsky Labs Limited developed much of the initial code for the Vega Protocol, it does not provide or control the Vega Protocol, which is run by third parties deploying it on a bespoke blockchain. Upgrades and modifications to the Vega Protocol are managed in a community-driven way by holders of the VEGA governance token.'
|
||||||
'As described in the Vega Protocol core license, the Vega Protocol is provided “as is”, at your own risk, and without warranties of any kind. Although Gobalsky Labs Limited developed much of the initial code for the Vega Protocol, it does not provide or control the Vega Protocol, which is run by third parties deploying it on a bespoke blockchain. Upgrades and modifications to the Vega Protocol are managed in a community-driven way by holders of the VEGA governance token.'
|
)}
|
||||||
)}
|
</p>
|
||||||
</p>
|
<p className="mb-8">
|
||||||
<p className="mb-8">
|
{t(
|
||||||
{t(
|
'No developer or entity involved in creating the Vega Protocol will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the Vega Protocol, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or legal costs, or loss of profits, cryptoassets, tokens or anything else of value.'
|
||||||
'No developer or entity involved in creating the Vega Protocol will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the Vega Protocol, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or legal costs, or loss of profits, cryptoassets, tokens or anything else of value.'
|
)}
|
||||||
)}
|
</p>
|
||||||
</p>
|
<p className="mb-8">
|
||||||
<p className="mb-8">
|
{t(
|
||||||
{t(
|
'This website is hosted on a decentralised network, the Interplanetary File System (“IPFS”). The IPFS decentralised web is made up of all the computers (nodes) connected to it. Data is therefore stored on many different computers.'
|
||||||
'This website is hosted on a decentralised network, the Interplanetary File System (“IPFS”). The IPFS decentralised web is made up of all the computers (nodes) connected to it. Data is therefore stored on many different computers.'
|
)}
|
||||||
)}
|
</p>
|
||||||
</p>
|
<p className="mb-8">
|
||||||
<p className="mb-8">
|
{t(
|
||||||
{t(
|
"The information provided on this website does not constitute investment advice, financial advice, trading advice, or any other sort of advice and you should not treat any of the website's content as such. No party recommends that any cryptoasset should be bought, sold, or held by you via this website. No party ensures the accuracy of information listed on this website or holds any responsibility for any missing or wrong information. You understand that you are using any and all information available here at your own risk."
|
||||||
"The information provided on this website does not constitute investment advice, financial advice, trading advice, or any other sort of advice and you should not treat any of the website's content as such. No party recommends that any cryptoasset should be bought, sold, or held by you via this website. No party ensures the accuracy of information listed on this website or holds any responsibility for any missing or wrong information. You understand that you are using any and all information available here at your own risk."
|
)}
|
||||||
)}
|
</p>
|
||||||
</p>
|
<p className="mb-8">
|
||||||
<p className="mb-8">
|
{t(
|
||||||
{t(
|
'Additionally, just as you can access email protocols such as SMTP through multiple email clients, you can potentially access the Vega Protocol through many web or mobile interfaces. You are responsible for doing your own diligence on those interfaces to understand the associated risks and any fees.'
|
||||||
'Additionally, just as you can access email protocols such as SMTP through multiple email clients, you can potentially access the Vega Protocol through many web or mobile interfaces. You are responsible for doing your own diligence on those interfaces to understand the associated risks and any fees.'
|
)}
|
||||||
)}
|
</p>
|
||||||
</p>
|
</>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1 @@
|
|||||||
import { Disclaimer } from './disclaimer';
|
export { Disclaimer } from './disclaimer';
|
||||||
|
|
||||||
export default Disclaimer;
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
|
||||||
import { useGlobalStore } from '../../stores';
|
import { useGlobalStore } from '../../stores';
|
||||||
import { useTopTradedMarkets } from '../../lib/hooks/use-top-traded-markets';
|
import { useTopTradedMarkets } from '../../lib/hooks/use-top-traded-markets';
|
||||||
|
import { Links } from '../../lib/links';
|
||||||
|
|
||||||
// The home pages only purpose is to redirect to the users last market,
|
// The home pages only purpose is to redirect to the users last market,
|
||||||
// the top traded if they are new, or fall back to the list of markets.
|
// the top traded if they are new, or fall back to the list of markets.
|
||||||
@ -15,17 +15,17 @@ export const Home = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (marketId) {
|
if (marketId) {
|
||||||
navigate(Links[Routes.MARKET](marketId), {
|
navigate(Links.MARKET(marketId), {
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
} else if (data) {
|
} else if (data) {
|
||||||
const marketDataId = data[0]?.id;
|
const marketDataId = data[0]?.id;
|
||||||
if (marketDataId) {
|
if (marketDataId) {
|
||||||
navigate(Links[Routes.MARKET](marketDataId), {
|
navigate(Links.MARKET(marketDataId), {
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
navigate(Links[Routes.MARKETS]());
|
navigate(Links.MARKETS());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [marketId, data, navigate]);
|
}, [marketId, data, navigate]);
|
||||||
|
@ -1,3 +1 @@
|
|||||||
import { Home } from './home';
|
export { Home } from './home';
|
||||||
|
|
||||||
export default Home;
|
|
||||||
|
@ -1,3 +1 @@
|
|||||||
import { Liquidity } from './liquidity';
|
export { Liquidity } from './liquidity';
|
||||||
|
|
||||||
export default Liquidity;
|
|
||||||
|
@ -1,3 +1 @@
|
|||||||
import { MarketPage } from './market';
|
export { MarketPage as default } from './market';
|
||||||
|
|
||||||
export default MarketPage;
|
|
||||||
|
@ -9,7 +9,7 @@ import { useGlobalStore, usePageTitleStore } from '../../stores';
|
|||||||
import { TradeGrid } from './trade-grid';
|
import { TradeGrid } from './trade-grid';
|
||||||
import { TradePanels } from './trade-panels';
|
import { TradePanels } from './trade-panels';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
import { Links } from '../../lib/links';
|
||||||
import { ViewType, useSidebar } from '../../components/sidebar';
|
import { ViewType, useSidebar } from '../../components/sidebar';
|
||||||
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
||||||
|
|
||||||
@ -96,12 +96,12 @@ export const MarketPage = () => {
|
|||||||
return (
|
return (
|
||||||
<Splash>
|
<Splash>
|
||||||
<span className="flex flex-col items-center gap-2">
|
<span className="flex flex-col items-center gap-2">
|
||||||
<p className="text-sm justify-center">
|
<p className="justify-center text-sm">
|
||||||
{t('This market URL is not available any more.')}
|
{t('This market URL is not available any more.')}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm justify-center">
|
<p className="justify-center text-sm">
|
||||||
{t(`Please choose another market from the`)}{' '}
|
{t(`Please choose another market from the`)}{' '}
|
||||||
<ExternalLink onClick={() => navigate(Links[Routes.MARKETS]())}>
|
<ExternalLink onClick={() => navigate(Links.MARKETS())}>
|
||||||
market list
|
market list
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
</p>
|
</p>
|
||||||
|
@ -1,3 +1 @@
|
|||||||
import { MarketsPage } from './markets-page';
|
export { MarketsPage } from './markets-page';
|
||||||
|
|
||||||
export default MarketsPage;
|
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
import { DApp, EXPLORER_MARKET, useLinks } from '@vegaprotocol/environment';
|
import { DApp, EXPLORER_MARKET, useLinks } from '@vegaprotocol/environment';
|
||||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
import { Links } from '../../lib/links';
|
||||||
|
|
||||||
export const MarketActionsDropdown = ({
|
export const MarketActionsDropdown = ({
|
||||||
marketId,
|
marketId,
|
||||||
@ -52,7 +52,7 @@ export const MarketActionsDropdown = ({
|
|||||||
{parentMarketID && (
|
{parentMarketID && (
|
||||||
<TradingDropdownItem
|
<TradingDropdownItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(Links[Routes.MARKET](parentMarketID));
|
navigate(Links.MARKET(parentMarketID));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<VegaIcon name={VegaIconNames.EYE} size={16} />
|
<VegaIcon name={VegaIconNames.EYE} size={16} />
|
||||||
@ -62,7 +62,7 @@ export const MarketActionsDropdown = ({
|
|||||||
{successorMarketID && (
|
{successorMarketID && (
|
||||||
<TradingDropdownItem
|
<TradingDropdownItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(Links[Routes.MARKET](successorMarketID));
|
navigate(Links.MARKET(successorMarketID));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<VegaIcon name={VegaIconNames.EYE} size={16} />
|
<VegaIcon name={VegaIconNames.EYE} size={16} />
|
||||||
|
@ -1,3 +1 @@
|
|||||||
import { Portfolio } from './portfolio';
|
export { Portfolio as default } from './portfolio';
|
||||||
|
|
||||||
export default Portfolio;
|
|
||||||
|
@ -21,14 +21,6 @@ const renderJsx = (route = '/transfer') => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
describe('Transfer page', () => {
|
describe('Transfer page', () => {
|
||||||
it('properly rendered', () => {
|
|
||||||
renderJsx();
|
|
||||||
expect(
|
|
||||||
screen.getByRole('heading', { level: 1, name: 'Transfer' })
|
|
||||||
).toBeInTheDocument();
|
|
||||||
expect(screen.getByTestId('assetId')).toBeEmptyDOMElement();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('assetId should be passed down', () => {
|
it('assetId should be passed down', () => {
|
||||||
const assetId = 'foo';
|
const assetId = 'foo';
|
||||||
const route = '/transfer?assetId=' + assetId;
|
const route = '/transfer?assetId=' + assetId;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
|
||||||
import { TransferContainer } from '@vegaprotocol/accounts';
|
import { TransferContainer } from '@vegaprotocol/accounts';
|
||||||
import { GetStarted } from '../../components/welcome-dialog';
|
import { GetStarted } from '../../components/welcome-dialog';
|
||||||
|
|
||||||
@ -8,16 +7,9 @@ export const Transfer = () => {
|
|||||||
const assetId = searchParams.get('assetId') || undefined;
|
const assetId = searchParams.get('assetId') || undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center w-full px-8 py-16">
|
<>
|
||||||
<div className="lg:min-w-[700px] min-w-[300px] max-w-[700px]">
|
<TransferContainer assetId={assetId} />
|
||||||
<h1 className="text-4xl uppercase xl:text-5xl font-alpha calt">
|
<GetStarted />
|
||||||
{t('Transfer')}
|
</>
|
||||||
</h1>
|
|
||||||
<div className="mt-10">
|
|
||||||
<TransferContainer assetId={assetId} />
|
|
||||||
<GetStarted />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -21,21 +21,10 @@ const renderJsx = (route = '/withdraw') => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
describe('Withdraw page', () => {
|
describe('Withdraw page', () => {
|
||||||
it('should be properly rendered', () => {
|
|
||||||
renderJsx();
|
|
||||||
expect(
|
|
||||||
screen.getByRole('heading', { level: 1, name: 'Withdraw' })
|
|
||||||
).toBeInTheDocument();
|
|
||||||
expect(screen.getByTestId('assetId')).toBeEmptyDOMElement();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('assetId should be passed down', () => {
|
it('assetId should be passed down', () => {
|
||||||
const assetId = 'foo';
|
const assetId = 'foo';
|
||||||
const route = '/withdraw?assetId=' + assetId;
|
const route = '/withdraw?assetId=' + assetId;
|
||||||
renderJsx(route);
|
renderJsx(route);
|
||||||
expect(
|
|
||||||
screen.getByRole('heading', { level: 1, name: 'Withdraw' })
|
|
||||||
).toBeInTheDocument();
|
|
||||||
expect(screen.getByTestId('assetId')).toHaveTextContent(assetId);
|
expect(screen.getByTestId('assetId')).toHaveTextContent(assetId);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
|
||||||
import { GetStarted } from '../../components/welcome-dialog';
|
import { GetStarted } from '../../components/welcome-dialog';
|
||||||
import { WithdrawContainer } from '../../components/withdraw-container';
|
import { WithdrawContainer } from '../../components/withdraw-container';
|
||||||
|
|
||||||
@ -7,16 +6,9 @@ export const Withdraw = () => {
|
|||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const assetId = searchParams.get('assetId') || undefined;
|
const assetId = searchParams.get('assetId') || undefined;
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center w-full px-8 py-16">
|
<>
|
||||||
<div className="lg:min-w-[700px] min-w-[300px] max-w-[700px]">
|
<WithdrawContainer assetId={assetId} />
|
||||||
<h1 className="text-4xl uppercase xl:text-5xl font-alpha calt">
|
<GetStarted />
|
||||||
{t('Withdraw')}
|
</>
|
||||||
</h1>
|
|
||||||
<div className="mt-10">
|
|
||||||
<WithdrawContainer assetId={assetId} />
|
|
||||||
<GetStarted />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
9
apps/trading/components/layouts/layout-centered.tsx
Normal file
9
apps/trading/components/layouts/layout-centered.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Outlet } from 'react-router-dom';
|
||||||
|
|
||||||
|
export const LayoutCentered = () => {
|
||||||
|
return (
|
||||||
|
<div className="mx-auto lg:min-w-[700px] min-w-[300px] max-w-[700px] px-4 lg:px-8 py-8 lg:py-16">
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -1,7 +1,6 @@
|
|||||||
import { Outlet, Routes, Route } from 'react-router-dom';
|
import { Outlet, Routes, Route } from 'react-router-dom';
|
||||||
import { Sidebar, SidebarContent, useSidebar } from '../sidebar';
|
import { Sidebar, SidebarContent, useSidebar } from '../sidebar';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Routes as AppRoutes } from '../../pages/client-router';
|
|
||||||
import { MarketHeader } from '../market-header';
|
import { MarketHeader } from '../market-header';
|
||||||
import { LiquidityHeader } from '../liquidity-header';
|
import { LiquidityHeader } from '../liquidity-header';
|
||||||
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
||||||
@ -23,8 +22,8 @@ export const LayoutWithSidebar = () => {
|
|||||||
<div className={gridClasses}>
|
<div className={gridClasses}>
|
||||||
<div className="col-span-full">
|
<div className="col-span-full">
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path={AppRoutes.MARKET} element={<MarketHeader />} />
|
<Route path="markets/:marketId" element={<MarketHeader />} />
|
||||||
<Route path={AppRoutes.LIQUIDITY} element={<LiquidityHeader />} />
|
<Route path="liquidity/:marketId" element={<LiquidityHeader />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
<main
|
<main
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
Indicator,
|
Indicator,
|
||||||
KeyValueTable,
|
KeyValueTable,
|
||||||
KeyValueTableRow,
|
KeyValueTableRow,
|
||||||
Link,
|
Link as UILink,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { useCheckLiquidityStatus } from '@vegaprotocol/liquidity';
|
import { useCheckLiquidityStatus } from '@vegaprotocol/liquidity';
|
||||||
@ -23,6 +23,8 @@ import {
|
|||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { DocsLinks } from '@vegaprotocol/environment';
|
import { DocsLinks } from '@vegaprotocol/environment';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { Links } from '../../lib/links';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
marketId?: string;
|
marketId?: string;
|
||||||
@ -100,51 +102,51 @@ export const MarketLiquiditySupplied = ({
|
|||||||
|
|
||||||
const description = marketId ? (
|
const description = marketId ? (
|
||||||
<section data-testid="liquidity-supplied-tooltip">
|
<section data-testid="liquidity-supplied-tooltip">
|
||||||
<KeyValueTable>
|
<div className="mb-2">
|
||||||
<KeyValueTableRow>
|
<KeyValueTable>
|
||||||
<span>{t('Supplied stake')}</span>
|
<KeyValueTableRow>
|
||||||
<span>
|
<span>{t('Supplied stake')}</span>
|
||||||
{market?.suppliedStake
|
<span>
|
||||||
? addDecimalsFormatNumber(
|
{market?.suppliedStake
|
||||||
new BigNumber(market?.suppliedStake).toString(),
|
? addDecimalsFormatNumber(
|
||||||
assetDecimals
|
new BigNumber(market?.suppliedStake).toString(),
|
||||||
)
|
assetDecimals
|
||||||
: '-'}
|
)
|
||||||
</span>
|
: '-'}
|
||||||
</KeyValueTableRow>
|
</span>
|
||||||
<KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<span>{t('Target stake')}</span>
|
<KeyValueTableRow>
|
||||||
<span>
|
<span>{t('Target stake')}</span>
|
||||||
{market?.targetStake
|
<span>
|
||||||
? addDecimalsFormatNumber(
|
{market?.targetStake
|
||||||
new BigNumber(market?.targetStake).toString(),
|
? addDecimalsFormatNumber(
|
||||||
assetDecimals
|
new BigNumber(market?.targetStake).toString(),
|
||||||
)
|
assetDecimals
|
||||||
: '-'}
|
)
|
||||||
</span>
|
: '-'}
|
||||||
</KeyValueTableRow>
|
</span>
|
||||||
</KeyValueTable>
|
</KeyValueTableRow>
|
||||||
<br />
|
</KeyValueTable>
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<Link
|
|
||||||
href={`/#/liquidity/${marketId}`}
|
|
||||||
data-testid="view-liquidity-link"
|
|
||||||
>
|
|
||||||
{t('View liquidity provision table')}
|
|
||||||
</Link>
|
|
||||||
{DocsLinks && (
|
|
||||||
<ExternalLink href={DocsLinks.LIQUIDITY} className="mt-2">
|
|
||||||
{t('Learn about providing liquidity')}
|
|
||||||
</ExternalLink>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{showMessage && (
|
{showMessage && (
|
||||||
<p className="mt-4">
|
<p className="mb-2">
|
||||||
{t(
|
{t(
|
||||||
'The market has sufficient liquidity but there are not enough priced limit orders in the order book, which are required to deploy liquidity commitment pegged orders.'
|
'The market has sufficient liquidity but there are not enough priced limit orders in the order book, which are required to deploy liquidity commitment pegged orders.'
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Link to={Links.LIQUIDITY(marketId)} data-testid="view-liquidity-link">
|
||||||
|
<UILink>{t('View liquidity provision table')}</UILink>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
{DocsLinks && (
|
||||||
|
<div>
|
||||||
|
<ExternalLink href={DocsLinks.LIQUIDITY} className="mt-2">
|
||||||
|
{t('Learn about providing liquidity')}
|
||||||
|
</ExternalLink>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
) : (
|
) : (
|
||||||
'-'
|
'-'
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Routes } from '../../pages/client-router';
|
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { Links } from '../../lib/links';
|
||||||
|
|
||||||
// Make sure these match the available __typename properties on product
|
// Make sure these match the available __typename properties on product
|
||||||
export const Product = {
|
export const Product = {
|
||||||
@ -55,7 +55,7 @@ export const ProductSelector = ({
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<Link
|
<Link
|
||||||
to={Routes.MARKETS}
|
to={Links.MARKETS()}
|
||||||
className="flex items-center ml-auto text-sm gap-2"
|
className="flex items-center ml-auto text-sm gap-2"
|
||||||
title={t('See all markets')}
|
title={t('See all markets')}
|
||||||
>
|
>
|
||||||
|
@ -15,7 +15,7 @@ import * as N from '@radix-ui/react-navigation-menu';
|
|||||||
import * as D from '@radix-ui/react-dialog';
|
import * as D from '@radix-ui/react-dialog';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
|
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
import { Links } from '../../lib/links';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { VegaWalletMenu } from '../vega-wallet';
|
import { VegaWalletMenu } from '../vega-wallet';
|
||||||
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
||||||
@ -142,9 +142,7 @@ const NavbarMenu = ({ onClick }: { onClick: () => void }) => {
|
|||||||
|
|
||||||
// If we have a stored marketId make Trade link go to that market
|
// If we have a stored marketId make Trade link go to that market
|
||||||
// otherwise always go to /markets/all
|
// otherwise always go to /markets/all
|
||||||
const tradingPath = marketId
|
const tradingPath = marketId ? Links.MARKET(marketId) : Links.MARKETS();
|
||||||
? Links[Routes.MARKET](marketId)
|
|
||||||
: Links[Routes.MARKET]('');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="lg:flex lg:h-full gap-3">
|
<div className="lg:flex lg:h-full gap-3">
|
||||||
@ -171,7 +169,7 @@ const NavbarMenu = ({ onClick }: { onClick: () => void }) => {
|
|||||||
<NavbarListDivider />
|
<NavbarListDivider />
|
||||||
<NavbarList>
|
<NavbarList>
|
||||||
<NavbarItem>
|
<NavbarItem>
|
||||||
<NavbarLink to={Links[Routes.MARKETS]()} onClick={onClick}>
|
<NavbarLink to={Links.MARKETS()} onClick={onClick}>
|
||||||
{t('Markets')}
|
{t('Markets')}
|
||||||
</NavbarLink>
|
</NavbarLink>
|
||||||
</NavbarItem>
|
</NavbarItem>
|
||||||
@ -181,7 +179,7 @@ const NavbarMenu = ({ onClick }: { onClick: () => void }) => {
|
|||||||
</NavbarLink>
|
</NavbarLink>
|
||||||
</NavbarItem>
|
</NavbarItem>
|
||||||
<NavbarItem>
|
<NavbarItem>
|
||||||
<NavbarLink to={Links[Routes.PORTFOLIO]()} onClick={onClick}>
|
<NavbarLink to={Links.PORTFOLIO()} onClick={onClick}>
|
||||||
{t('Portfolio')}
|
{t('Portfolio')}
|
||||||
</NavbarLink>
|
</NavbarLink>
|
||||||
</NavbarItem>
|
</NavbarItem>
|
||||||
@ -209,7 +207,7 @@ const NavbarMenu = ({ onClick }: { onClick: () => void }) => {
|
|||||||
</NavbarSubItem>
|
</NavbarSubItem>
|
||||||
)}
|
)}
|
||||||
<NavbarSubItem>
|
<NavbarSubItem>
|
||||||
<NavbarLink to={Links[Routes.DISCLAIMER]()} onClick={onClick}>
|
<NavbarLink to={Links.DISCLAIMER()} onClick={onClick}>
|
||||||
{t('Disclaimer')}
|
{t('Disclaimer')}
|
||||||
</NavbarLink>
|
</NavbarLink>
|
||||||
</NavbarSubItem>
|
</NavbarSubItem>
|
||||||
|
@ -11,7 +11,7 @@ import { MemoryRouter, Route, Routes } from 'react-router-dom';
|
|||||||
import { VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
import { VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
|
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
|
||||||
import { VegaWalletContext } from '@vegaprotocol/wallet';
|
import { VegaWalletContext } from '@vegaprotocol/wallet';
|
||||||
import { Routes as AppRoutes } from '../../pages/client-router';
|
import { Routes as AppRoutes } from '../../lib/links';
|
||||||
|
|
||||||
jest.mock('../node-health', () => ({
|
jest.mock('../node-health', () => ({
|
||||||
NodeHealthContainer: () => <span data-testid="node-health" />,
|
NodeHealthContainer: () => <span data-testid="node-health" />,
|
||||||
|
@ -13,10 +13,9 @@ import { NodeHealthContainer } from '../node-health';
|
|||||||
import { Settings } from '../settings';
|
import { Settings } from '../settings';
|
||||||
import { Tooltip } from '../../components/tooltip';
|
import { Tooltip } from '../../components/tooltip';
|
||||||
import { WithdrawContainer } from '../withdraw-container';
|
import { WithdrawContainer } from '../withdraw-container';
|
||||||
import { Routes as AppRoutes } from '../../pages/client-router';
|
import { GetStarted } from '../welcome-dialog';
|
||||||
import { useVegaWallet, useViewAsDialog } from '@vegaprotocol/wallet';
|
import { useVegaWallet, useViewAsDialog } from '@vegaprotocol/wallet';
|
||||||
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
||||||
import { GetStarted } from '../welcome-dialog';
|
|
||||||
|
|
||||||
export enum ViewType {
|
export enum ViewType {
|
||||||
Order = 'Order',
|
Order = 'Order',
|
||||||
@ -51,6 +50,28 @@ type SidebarView =
|
|||||||
type: ViewType.Settings;
|
type: ViewType.Settings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MarketSidebarButtons = () => {
|
||||||
|
const currentRouteId = useGetCurrentRouteId();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SidebarDivider />
|
||||||
|
<SidebarButton
|
||||||
|
view={ViewType.Order}
|
||||||
|
icon={VegaIconNames.TICKET}
|
||||||
|
tooltip={t('Order')}
|
||||||
|
routeId={currentRouteId}
|
||||||
|
/>
|
||||||
|
<SidebarButton
|
||||||
|
view={ViewType.Info}
|
||||||
|
icon={VegaIconNames.BREAKDOWN}
|
||||||
|
tooltip={t('Market specification')}
|
||||||
|
routeId={currentRouteId}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const Sidebar = () => {
|
export const Sidebar = () => {
|
||||||
const currentRouteId = useGetCurrentRouteId();
|
const currentRouteId = useGetCurrentRouteId();
|
||||||
const navClasses = 'flex lg:flex-col items-center gap-2 lg:gap-4 p-1';
|
const navClasses = 'flex lg:flex-col items-center gap-2 lg:gap-4 p-1';
|
||||||
@ -81,34 +102,19 @@ export const Sidebar = () => {
|
|||||||
{/* buttons for specific routes */}
|
{/* buttons for specific routes */}
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={AppRoutes.MARKETS}
|
path="markets/all"
|
||||||
// render nothing for markets/all, otherwise markets/:marketId will match with markets/all
|
// render nothing for markets/all, otherwise markets/:marketId will match with markets/all
|
||||||
element={null}
|
element={null}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
// render nothing for portfolio
|
// render nothing for portfolio
|
||||||
path={AppRoutes.PORTFOLIO}
|
path="portfolio"
|
||||||
element={null}
|
element={null}
|
||||||
/>
|
/>
|
||||||
|
<Route path="markets/:marketId" element={<MarketSidebarButtons />} />
|
||||||
<Route
|
<Route
|
||||||
path={AppRoutes.MARKET}
|
path="liquidity/:marketId"
|
||||||
element={
|
element={<MarketSidebarButtons />}
|
||||||
<>
|
|
||||||
<SidebarDivider />
|
|
||||||
<SidebarButton
|
|
||||||
view={ViewType.Order}
|
|
||||||
icon={VegaIconNames.TICKET}
|
|
||||||
tooltip={t('Order')}
|
|
||||||
routeId={currentRouteId}
|
|
||||||
/>
|
|
||||||
<SidebarButton
|
|
||||||
view={ViewType.Info}
|
|
||||||
icon={VegaIconNames.BREAKDOWN}
|
|
||||||
tooltip={t('Market specification')}
|
|
||||||
routeId={currentRouteId}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</nav>
|
</nav>
|
||||||
|
@ -15,7 +15,7 @@ import {
|
|||||||
useGetOnboardingStep,
|
useGetOnboardingStep,
|
||||||
useOnboardingStore,
|
useOnboardingStore,
|
||||||
} from './use-get-onboarding-step';
|
} from './use-get-onboarding-step';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
import { Links, Routes } from '../../lib/links';
|
||||||
import { useGlobalStore } from '../../stores';
|
import { useGlobalStore } from '../../stores';
|
||||||
import { useSidebar, ViewType } from '../sidebar';
|
import { useSidebar, ViewType } from '../sidebar';
|
||||||
|
|
||||||
@ -48,17 +48,18 @@ const GetStartedButton = ({ step }: { step: OnboardingStep }) => {
|
|||||||
return (
|
return (
|
||||||
<TradingAnchorButton
|
<TradingAnchorButton
|
||||||
{...buttonProps}
|
{...buttonProps}
|
||||||
href={Links[Routes.DEPOSIT]()}
|
href={Links.DEPOSIT()}
|
||||||
onClick={() => setDialogOpen(false)}
|
onClick={() => setDialogOpen(false)}
|
||||||
>
|
>
|
||||||
{t('Deposit')}
|
{t('Deposit')}
|
||||||
</TradingAnchorButton>
|
</TradingAnchorButton>
|
||||||
);
|
);
|
||||||
} else if (step >= OnboardingStep.ONBOARDING_ORDER_STEP) {
|
} else if (step >= OnboardingStep.ONBOARDING_ORDER_STEP) {
|
||||||
|
const link = marketId ? Links.MARKET(marketId) : Links.HOME();
|
||||||
return (
|
return (
|
||||||
<TradingAnchorButton
|
<TradingAnchorButton
|
||||||
{...buttonProps}
|
{...buttonProps}
|
||||||
href={marketId ? Links[Routes.MARKET](marketId) : Links[Routes.HOME]()}
|
href={link}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setViews({ type: ViewType.Order }, Routes.MARKET);
|
setViews({ type: ViewType.Order }, Routes.MARKET);
|
||||||
dismiss();
|
dismiss();
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||||
import { Routes } from '../../pages/client-router';
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import { Links } from '../../lib/links';
|
||||||
|
|
||||||
export const RiskMessage = () => {
|
export const RiskMessage = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="bg-vega-light-100 dark:bg-vega-dark-100 p-6 mb-6">
|
<div className="p-6 mb-6 bg-vega-light-100 dark:bg-vega-dark-100">
|
||||||
<ul className="list-[square] ml-4">
|
<ul className="list-[square] ml-4">
|
||||||
<li className="mb-1">
|
<li className="mb-1">
|
||||||
{t(
|
{t(
|
||||||
@ -27,7 +27,7 @@ export const RiskMessage = () => {
|
|||||||
{t(
|
{t(
|
||||||
'By using the Vega Console, you acknowledge that you have read and understood the'
|
'By using the Vega Console, you acknowledge that you have read and understood the'
|
||||||
)}{' '}
|
)}{' '}
|
||||||
<Link className="underline" to={Routes.DISCLAIMER} target="_blank">
|
<Link className="underline" to={Links.DISCLAIMER()} target="_blank">
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<span>{t('Vega Console Disclaimer')}</span>
|
<span>{t('Vega Console Disclaimer')}</span>
|
||||||
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
|
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { GetStarted } from './get-started';
|
import { GetStarted } from './get-started';
|
||||||
import { TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
|
import { TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
import { Links } from '../../lib/links';
|
||||||
import { Networks, useEnvironment } from '@vegaprotocol/environment';
|
import { Networks, useEnvironment } from '@vegaprotocol/environment';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { useTopTradedMarkets } from '../../lib/hooks/use-top-traded-markets';
|
import { useTopTradedMarkets } from '../../lib/hooks/use-top-traded-markets';
|
||||||
@ -15,9 +15,7 @@ export const WelcomeDialogContent = () => {
|
|||||||
|
|
||||||
const { data } = useTopTradedMarkets();
|
const { data } = useTopTradedMarkets();
|
||||||
const marketId = data && data[0]?.id;
|
const marketId = data && data[0]?.id;
|
||||||
const link = marketId
|
const link = marketId ? Links.MARKET(marketId) : Links.MARKETS();
|
||||||
? Links[Routes.MARKET](marketId)
|
|
||||||
: Links[Routes.MARKETS]();
|
|
||||||
|
|
||||||
const lead =
|
const lead =
|
||||||
VEGA_ENV === Networks.MAINNET
|
VEGA_ENV === Networks.MAINNET
|
||||||
|
@ -3,12 +3,10 @@ import { matchRoutes, useLocation } from 'react-router-dom';
|
|||||||
|
|
||||||
export const useGetCurrentRouteId = () => {
|
export const useGetCurrentRouteId = () => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const currentRoute = matchRoutes(routerConfig, location);
|
const matches = matchRoutes(routerConfig, location);
|
||||||
const lastRoute = currentRoute?.pop();
|
const lastRoute = matches ? matches[matches.length - 1] : undefined;
|
||||||
if (lastRoute) {
|
if (lastRoute) {
|
||||||
const {
|
const id = lastRoute.route.id;
|
||||||
route: { id },
|
|
||||||
} = lastRoute;
|
|
||||||
return id || '';
|
return id || '';
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
import { Links } from '../../lib/links';
|
||||||
|
|
||||||
export const useMarketClickHandler = (replace = false) => {
|
export const useMarketClickHandler = (replace = false) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (selectedId: string, metaKey?: boolean) => {
|
return (selectedId: string, metaKey?: boolean) => {
|
||||||
const link = Links[Routes.MARKET](selectedId);
|
const link = Links.MARKET(selectedId);
|
||||||
if (metaKey) {
|
if (metaKey) {
|
||||||
window.open(`/#${link}`, '_blank');
|
window.open(`/#${link}`, '_blank');
|
||||||
} else {
|
} else {
|
||||||
|
35
apps/trading/lib/links.ts
Normal file
35
apps/trading/lib/links.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import trimEnd from 'lodash/trimEnd';
|
||||||
|
|
||||||
|
// Make all route paths 'absolute' for easier
|
||||||
|
// href creation
|
||||||
|
export const Routes = {
|
||||||
|
HOME: '/',
|
||||||
|
MARKETS: '/markets/all',
|
||||||
|
MARKET: '/markets/:marketId',
|
||||||
|
LIQUIDITY: '/liquidity/:marketId',
|
||||||
|
PORTFOLIO: '/portfolio',
|
||||||
|
DISCLAIMER: '/disclaimer',
|
||||||
|
ASSETS: '/portfolio/assets',
|
||||||
|
DEPOSIT: '/portfolio/assets/deposit',
|
||||||
|
WITHDRAW: '/portfolio/assets/withdraw',
|
||||||
|
TRANSFER: '/portfolio/assets/transfer',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
type ConsoleLinks = {
|
||||||
|
[R in keyof typeof Routes]: (...args: string[]) => string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Links: ConsoleLinks = {
|
||||||
|
HOME: () => Routes.HOME,
|
||||||
|
MARKET: (marketId: string) =>
|
||||||
|
trimEnd(Routes.MARKET.replace(':marketId', marketId)),
|
||||||
|
MARKETS: () => Routes.MARKETS,
|
||||||
|
PORTFOLIO: () => Routes.PORTFOLIO,
|
||||||
|
LIQUIDITY: (marketId: string) =>
|
||||||
|
trimEnd(Routes.LIQUIDITY.replace(':marketId', marketId)),
|
||||||
|
DISCLAIMER: () => Routes.DISCLAIMER,
|
||||||
|
ASSETS: () => Routes.ASSETS,
|
||||||
|
DEPOSIT: () => Routes.DEPOSIT,
|
||||||
|
WITHDRAW: () => Routes.WITHDRAW,
|
||||||
|
TRANSFER: () => Routes.TRANSFER,
|
||||||
|
};
|
@ -48,8 +48,8 @@ import {
|
|||||||
} from '@vegaprotocol/proposals';
|
} from '@vegaprotocol/proposals';
|
||||||
import { ViewingBanner } from '../components/viewing-banner';
|
import { ViewingBanner } from '../components/viewing-banner';
|
||||||
import { NavHeader } from '../components/navbar/nav-header';
|
import { NavHeader } from '../components/navbar/nav-header';
|
||||||
import { Routes as AppRoutes } from './client-router';
|
|
||||||
import { Telemetry } from '../components/telemetry';
|
import { Telemetry } from '../components/telemetry';
|
||||||
|
import { Routes as AppRoutes } from '../lib/links';
|
||||||
|
|
||||||
const DEFAULT_TITLE = t('Welcome to Vega trading!');
|
const DEFAULT_TITLE = t('Welcome to Vega trading!');
|
||||||
|
|
||||||
|
@ -1,127 +1,106 @@
|
|||||||
import { Suspense } from 'react';
|
|
||||||
import type { RouteObject } from 'react-router-dom';
|
import type { RouteObject } from 'react-router-dom';
|
||||||
import { Outlet, useRoutes } from 'react-router-dom';
|
import { Navigate, Outlet, useRoutes } from 'react-router-dom';
|
||||||
import dynamic from 'next/dynamic';
|
import { lazy, Suspense } from 'react';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import trimEnd from 'lodash/trimEnd';
|
|
||||||
import { LayoutWithSidebar } from '../components/layouts';
|
import { LayoutWithSidebar } from '../components/layouts';
|
||||||
|
import { LayoutCentered } from '../components/layouts/layout-centered';
|
||||||
|
import { Home } from '../client-pages/home';
|
||||||
|
import { Liquidity } from '../client-pages/liquidity';
|
||||||
|
import { MarketsPage } from '../client-pages/markets';
|
||||||
|
import { Disclaimer } from '../client-pages/disclaimer';
|
||||||
|
import { Assets } from '../client-pages/assets';
|
||||||
import { Deposit } from '../client-pages/deposit';
|
import { Deposit } from '../client-pages/deposit';
|
||||||
import { Withdraw } from '../client-pages/withdraw';
|
import { Withdraw } from '../client-pages/withdraw';
|
||||||
import { Transfer } from '../client-pages/transfer';
|
import { Transfer } from '../client-pages/transfer';
|
||||||
|
import { Routes } from '../lib/links';
|
||||||
|
|
||||||
const LazyHome = dynamic(() => import('../client-pages/home'), {
|
// These must remain dynamically imported as pennant cannot be compiled by nextjs due to ESM
|
||||||
ssr: false,
|
// Using dynamic imports is a workaround for this until pennant is published as ESM
|
||||||
});
|
const MarketPage = lazy(() => import('../client-pages/market'));
|
||||||
|
const Portfolio = lazy(() => import('../client-pages/portfolio'));
|
||||||
|
|
||||||
const LazyLiquidity = dynamic(() => import('../client-pages/liquidity'), {
|
const NotFound = () => (
|
||||||
ssr: false,
|
<Splash>
|
||||||
});
|
<p>{t('Page not found')}</p>
|
||||||
|
</Splash>
|
||||||
const LazyMarkets = dynamic(() => import('../client-pages/markets'), {
|
);
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const LazyMarket = dynamic(() => import('../client-pages/market'), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const LazyPortfolio = dynamic(() => import('../client-pages/portfolio'), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const LazyDisclaimer = dynamic(() => import('../client-pages/disclaimer'), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export enum Routes {
|
|
||||||
HOME = '/',
|
|
||||||
MARKET = '/markets/:marketId',
|
|
||||||
MARKETS = '/markets/all',
|
|
||||||
PORTFOLIO = '/portfolio',
|
|
||||||
LIQUIDITY = '/liquidity/:marketId',
|
|
||||||
DISCLAIMER = '/disclaimer',
|
|
||||||
DEPOSIT = '/deposit',
|
|
||||||
WITHDRAW = '/withdraw',
|
|
||||||
TRANSFER = '/transfer',
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConsoleLinks = { [r in Routes]: (...args: string[]) => string };
|
|
||||||
|
|
||||||
export const Links: ConsoleLinks = {
|
|
||||||
[Routes.HOME]: () => Routes.HOME,
|
|
||||||
[Routes.MARKET]: (marketId: string) =>
|
|
||||||
trimEnd(Routes.MARKET.replace(':marketId', marketId)),
|
|
||||||
[Routes.MARKETS]: () => Routes.MARKETS,
|
|
||||||
[Routes.PORTFOLIO]: () => Routes.PORTFOLIO,
|
|
||||||
[Routes.LIQUIDITY]: (marketId: string) =>
|
|
||||||
trimEnd(Routes.LIQUIDITY.replace(':marketId', marketId)),
|
|
||||||
[Routes.DISCLAIMER]: () => Routes.DISCLAIMER,
|
|
||||||
[Routes.DEPOSIT]: () => Routes.DEPOSIT,
|
|
||||||
[Routes.WITHDRAW]: () => Routes.WITHDRAW,
|
|
||||||
[Routes.TRANSFER]: () => Routes.TRANSFER,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const routerConfig: RouteObject[] = [
|
export const routerConfig: RouteObject[] = [
|
||||||
|
// Pages that dont use the LayoutWithSidebar must come first
|
||||||
|
// to ensure they are matched before the catch all route '/*'
|
||||||
|
{
|
||||||
|
path: 'disclaimer',
|
||||||
|
element: <LayoutCentered />,
|
||||||
|
id: Routes.DISCLAIMER,
|
||||||
|
children: [{ index: true, element: <Disclaimer /> }],
|
||||||
|
},
|
||||||
|
|
||||||
|
// All other pages will use the sidebar
|
||||||
{
|
{
|
||||||
path: '/*',
|
path: '/*',
|
||||||
element: <LayoutWithSidebar />,
|
element: <LayoutWithSidebar />,
|
||||||
children: [
|
children: [
|
||||||
// all pages that require the Layout component (Sidebar)
|
|
||||||
{
|
{
|
||||||
index: true,
|
index: true,
|
||||||
element: <LazyHome />,
|
element: <Home />,
|
||||||
id: Routes.HOME,
|
id: Routes.HOME,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'markets',
|
path: 'markets',
|
||||||
element: <Outlet />,
|
element: <Outlet />,
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
index: true,
|
||||||
|
element: <Navigate to="all" />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'all',
|
path: 'all',
|
||||||
element: <LazyMarkets />,
|
element: <MarketsPage />,
|
||||||
id: Routes.MARKETS,
|
id: Routes.MARKETS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: ':marketId',
|
path: ':marketId',
|
||||||
element: <LazyMarket />,
|
element: <MarketPage />,
|
||||||
id: Routes.MARKET,
|
id: Routes.MARKET,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'portfolio',
|
path: 'portfolio',
|
||||||
element: <LazyPortfolio />,
|
|
||||||
id: Routes.PORTFOLIO,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'liquidity',
|
|
||||||
element: <Outlet />,
|
element: <Outlet />,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: ':marketId',
|
index: true,
|
||||||
element: <LazyLiquidity />,
|
element: <Portfolio />,
|
||||||
id: Routes.LIQUIDITY,
|
id: Routes.PORTFOLIO,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'assets',
|
||||||
|
element: <Assets />,
|
||||||
|
id: Routes.ASSETS,
|
||||||
|
children: [
|
||||||
|
{ index: true, element: <Navigate to="deposit" /> },
|
||||||
|
{ path: 'deposit', element: <Deposit />, id: Routes.DEPOSIT },
|
||||||
|
{ path: 'withdraw', element: <Withdraw />, id: Routes.WITHDRAW },
|
||||||
|
{ path: 'transfer', element: <Transfer />, id: Routes.TRANSFER },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'liquidity/:marketId',
|
||||||
|
element: <Liquidity />,
|
||||||
|
id: Routes.LIQUIDITY,
|
||||||
|
},
|
||||||
|
|
||||||
|
// NotFound page is here so its caught within parent '/*' route
|
||||||
|
{
|
||||||
|
path: '*',
|
||||||
|
element: <NotFound />,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: Routes.DISCLAIMER,
|
|
||||||
element: <LazyDisclaimer />,
|
|
||||||
},
|
|
||||||
{ path: Routes.DEPOSIT, element: <Deposit /> },
|
|
||||||
{ path: Routes.WITHDRAW, element: <Withdraw /> },
|
|
||||||
{ path: Routes.TRANSFER, element: <Transfer /> },
|
|
||||||
{
|
|
||||||
path: '*',
|
|
||||||
element: (
|
|
||||||
<Splash>
|
|
||||||
<p>{t('Not found')}</p>
|
|
||||||
</Splash>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ClientRouter = () => {
|
export const ClientRouter = () => {
|
||||||
@ -129,9 +108,9 @@ export const ClientRouter = () => {
|
|||||||
return (
|
return (
|
||||||
<Suspense
|
<Suspense
|
||||||
fallback={
|
fallback={
|
||||||
<div className="flex items-center justify-center w-full h-full">
|
<Splash>
|
||||||
<Loader />
|
<Loader />
|
||||||
</div>
|
</Splash>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{routes}
|
{routes}
|
||||||
|
@ -3,8 +3,8 @@ import { useUpdateNetworkParametersToasts } from '@vegaprotocol/proposals';
|
|||||||
import { useVegaTransactionToasts } from '@vegaprotocol/web3';
|
import { useVegaTransactionToasts } from '@vegaprotocol/web3';
|
||||||
import { useEthereumTransactionToasts } from '@vegaprotocol/web3';
|
import { useEthereumTransactionToasts } from '@vegaprotocol/web3';
|
||||||
import { useEthereumWithdrawApprovalsToasts } from '@vegaprotocol/web3';
|
import { useEthereumWithdrawApprovalsToasts } from '@vegaprotocol/web3';
|
||||||
import { Routes } from './client-router';
|
|
||||||
import { useReadyToWithdrawalToasts } from '@vegaprotocol/withdraws';
|
import { useReadyToWithdrawalToasts } from '@vegaprotocol/withdraws';
|
||||||
|
import { Links } from '../lib/links';
|
||||||
|
|
||||||
export const ToastsManager = () => {
|
export const ToastsManager = () => {
|
||||||
useUpdateNetworkParametersToasts();
|
useUpdateNetworkParametersToasts();
|
||||||
@ -12,7 +12,7 @@ export const ToastsManager = () => {
|
|||||||
useEthereumTransactionToasts();
|
useEthereumTransactionToasts();
|
||||||
useEthereumWithdrawApprovalsToasts();
|
useEthereumWithdrawApprovalsToasts();
|
||||||
useReadyToWithdrawalToasts({
|
useReadyToWithdrawalToasts({
|
||||||
withdrawalsLink: `${Routes.PORTFOLIO}`,
|
withdrawalsLink: Links.PORTFOLIO(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const toasts = useToasts((store) => store.toasts);
|
const toasts = useToasts((store) => store.toasts);
|
||||||
|
@ -11,7 +11,7 @@ type LinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {
|
|||||||
*/
|
*/
|
||||||
export const Link = ({ className, children, ...props }: LinkProps) => {
|
export const Link = ({ className, children, ...props }: LinkProps) => {
|
||||||
const anchorClassName = classNames(className, {
|
const anchorClassName = classNames(className, {
|
||||||
underline: typeof children === 'string',
|
'underline underline-offset-4': typeof children === 'string',
|
||||||
'cursor-pointer': props['aria-disabled'] !== true,
|
'cursor-pointer': props['aria-disabled'] !== true,
|
||||||
'opacity-50 pointer-events-none': props['aria-disabled'] === true,
|
'opacity-50 pointer-events-none': props['aria-disabled'] === true,
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user