feat(trading): add liquidity provision link to orders table (#3432)

This commit is contained in:
m.ray 2023-04-18 08:55:11 -04:00 committed by GitHub
parent 2346b2f1a0
commit 045dace274
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 125 additions and 19 deletions

View File

@ -29,7 +29,10 @@ import { LiquidityContainer } from '../liquidity/liquidity';
import { useNavigate } from 'react-router-dom';
import type { PinnedAsset } from '@vegaprotocol/accounts';
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
import {
useMarketClickHandler,
useMarketLiquidityClickHandler,
} from '../../lib/hooks/use-market-click-handler';
type MarketDependantView =
| typeof CandlesChartContainer
@ -79,6 +82,7 @@ const MarketBottomPanel = memo(
({ marketId, pinnedAsset }: BottomPanelProps) => {
const { screenSize } = useScreenDimensions();
const onMarketClick = useMarketClickHandler(true);
const onOrderTypeClick = useMarketLiquidityClickHandler(true);
return 'xxxl' === screenSize ? (
<ResizableGrid proportionalLayout minSize={200}>
@ -94,6 +98,7 @@ const MarketBottomPanel = memo(
<TradingViews.Orders
marketId={marketId}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
enforceBottomPlaceholder
/>
</VegaWalletContainer>
@ -150,6 +155,7 @@ const MarketBottomPanel = memo(
<TradingViews.Orders
marketId={marketId}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
enforceBottomPlaceholder
/>
</VegaWalletContainer>
@ -293,6 +299,7 @@ interface TradePanelsProps {
market: Market | null;
onSelect: (marketId: string, metaKey?: boolean) => void;
onMarketClick?: (marketId: string) => void;
onOrderTypeClick?: (marketId: string) => void;
onClickCollateral: () => void;
pinnedAsset?: PinnedAsset;
}
@ -303,12 +310,16 @@ export const TradePanels = ({
onClickCollateral,
pinnedAsset,
}: TradePanelsProps) => {
const onMarketClick = useMarketClickHandler(true);
const onOrderTypeClick = useMarketLiquidityClickHandler(true);
const [view, setView] = useState<TradingView>('Candles');
const renderView = () => {
const Component = memo<{
marketId: string;
onSelect: (marketId: string, metaKey?: boolean) => void;
onMarketClick?: (marketId: string) => void;
onOrderTypeClick?: (marketId: string) => void;
onClickCollateral: () => void;
pinnedAsset?: PinnedAsset;
}>(TradingViews[view]);
@ -325,6 +336,8 @@ export const TradePanels = ({
onSelect={onSelect}
onClickCollateral={onClickCollateral}
pinnedAsset={pinnedAsset}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
/>
);
};

View File

@ -19,7 +19,10 @@ import { usePageTitleStore } from '../../stores';
import { LedgerContainer } from '@vegaprotocol/ledger';
import { AccountsContainer } from '../../components/accounts-container';
import { AccountHistoryContainer } from './account-history-container';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
import {
useMarketClickHandler,
useMarketLiquidityClickHandler,
} from '../../lib/hooks/use-market-click-handler';
export const Portfolio = () => {
const { updateTitle } = usePageTitleStore((store) => ({
@ -31,6 +34,7 @@ export const Portfolio = () => {
}, [updateTitle]);
const onMarketClick = useMarketClickHandler(true);
const onOrderTypeClick = useMarketLiquidityClickHandler(true);
const wrapperClasses = 'h-full max-h-full flex flex-col';
return (
@ -54,7 +58,10 @@ export const Portfolio = () => {
</Tab>
<Tab id="orders" name={t('Orders')}>
<VegaWalletContainer>
<OrderListContainer onMarketClick={onMarketClick} />
<OrderListContainer
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
/>
</VegaWalletContainer>
</Tab>
<Tab id="fills" name={t('Fills')}>

View File

@ -19,3 +19,21 @@ export const useMarketClickHandler = (replace = false) => {
[navigate, marketId, replace, isMarketPage]
);
};
export const useMarketLiquidityClickHandler = (replace = false) => {
const navigate = useNavigate();
const { marketId } = useParams();
const { pathname } = useLocation();
const isLiquidityPage = pathname.match(/^\/liquidity\/(.+)/);
return useCallback(
(selectedId: string, metaKey?: boolean) => {
const link = Links[Routes.LIQUIDITY](selectedId);
if (metaKey) {
window.open(`/#${link}`, '_blank');
} else if (selectedId !== marketId || !isLiquidityPage) {
navigate(link, { replace });
}
},
[navigate, marketId, replace, isLiquidityPage]
);
};

View File

@ -31,7 +31,7 @@ export enum Routes {
MARKET = '/markets',
MARKETS = '/markets/all',
PORTFOLIO = '/portfolio',
LIQUIDITY = 'liquidity/:marketId',
LIQUIDITY = '/liquidity',
}
type ConsoleLinks = { [r in Routes]: (...args: string[]) => string };
@ -41,8 +41,10 @@ export const Links: ConsoleLinks = {
marketId ? trimEnd(`${Routes.MARKET}/${marketId}`, '/') : Routes.MARKET,
[Routes.MARKETS]: () => Routes.MARKETS,
[Routes.PORTFOLIO]: () => Routes.PORTFOLIO,
[Routes.LIQUIDITY]: (marketId: string) =>
Routes.LIQUIDITY.replace(':marketId', marketId),
[Routes.LIQUIDITY]: (marketId: string | null | undefined) =>
marketId
? trimEnd(`${Routes.LIQUIDITY}/${marketId}`, '/')
: Routes.LIQUIDITY,
};
const routerConfig: RouteObject[] = [
@ -70,6 +72,16 @@ const routerConfig: RouteObject[] = [
{
path: Routes.LIQUIDITY,
element: <LazyLiquidity />,
children: [
{
index: true,
element: <LazyLiquidity />,
},
{
path: ':marketId',
element: <LazyLiquidity />,
},
],
},
{
path: Routes.PORTFOLIO,

View File

@ -10,6 +10,7 @@ export * from './lib/cells/price-flash-cell';
export * from './lib/cells/vol-cell';
export * from './lib/cells/centered-grid-cell';
export * from './lib/cells/market-name-cell';
export * from './lib/cells/order-type-cell';
export * from './lib/filters/date-range-filter';
export * from './lib/filters/set-filter';

View File

@ -0,0 +1,52 @@
import type { MouseEvent } from 'react';
import { useMemo } from 'react';
import { useCallback } from 'react';
import { t } from '@vegaprotocol/i18n';
import * as Schema from '@vegaprotocol/types';
interface OrderTypeCellProps {
value?: Schema.OrderType;
data?: Schema.Order;
onClick?: (marketId: string, metaKey?: boolean) => void;
}
export const OrderTypeCell = ({
value,
data: order,
onClick,
}: OrderTypeCellProps) => {
const id = order ? order.market.id : '';
const label = useMemo(() => {
if (!order) {
return undefined;
}
if (!value) return '-';
if (order?.peggedOrder) {
return t('Pegged');
}
if (order?.liquidityProvision) {
return t('Liquidity provision');
}
return Schema.OrderTypeMapping[value];
}, [order, value]);
const handleOnClick = useCallback(
(ev: MouseEvent<HTMLButtonElement>) => {
ev.preventDefault();
ev.stopPropagation();
if (onClick) {
onClick(id, ev.metaKey || ev.ctrlKey);
}
},
[id, onClick]
);
if (!order) return null;
return order?.liquidityProvision ? (
<button onClick={handleOnClick} tabIndex={0} className="underline">
{label}
</button>
) : (
<span>{label}</span>
);
};

View File

@ -6,10 +6,12 @@ import { OrderListManager } from './order-list-manager';
export const OrderListContainer = ({
marketId,
onMarketClick,
onOrderTypeClick,
enforceBottomPlaceholder,
}: {
marketId?: string;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
onOrderTypeClick?: (marketId: string, metaKey?: boolean) => void;
enforceBottomPlaceholder?: boolean;
}) => {
const { pubKey, isReadOnly } = useVegaWallet();
@ -23,6 +25,7 @@ export const OrderListContainer = ({
partyId={pubKey}
marketId={marketId}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
isReadOnly={isReadOnly}
enforceBottomPlaceholder={enforceBottomPlaceholder}
/>

View File

@ -25,6 +25,7 @@ export interface OrderListManagerProps {
partyId: string;
marketId?: string;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
onOrderTypeClick?: (marketId: string, metaKey?: boolean) => void;
isReadOnly: boolean;
enforceBottomPlaceholder?: boolean;
}
@ -52,6 +53,7 @@ export const OrderListManager = ({
partyId,
marketId,
onMarketClick,
onOrderTypeClick,
isReadOnly,
enforceBottomPlaceholder,
}: OrderListManagerProps) => {
@ -165,6 +167,7 @@ export const OrderListManager = ({
cancel={cancel}
setEditOrder={setEditOrder}
onMarketClick={onMarketClick}
onOrderTypeClick={onOrderTypeClick}
isReadOnly={isReadOnly}
blockLoadDebounceMillis={100}
suppressLoadingOverlay

View File

@ -16,6 +16,7 @@ import {
negativeClassNames,
positiveClassNames,
MarketNameCell,
OrderTypeCell,
} from '@vegaprotocol/datagrid';
import type {
TypedDataAgGrid,
@ -31,12 +32,16 @@ export type OrderListTableProps = OrderListProps & {
cancel: (order: Order) => void;
setEditOrder: (order: Order) => void;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
onOrderTypeClick?: (marketId: string, metaKey?: boolean) => void;
isReadOnly: boolean;
};
export const OrderListTable = memo(
forwardRef<AgGridReact, OrderListTableProps>(
({ cancel, setEditOrder, onMarketClick, ...props }, ref) => {
(
{ cancel, setEditOrder, onMarketClick, onOrderTypeClick, ...props },
ref
) => {
return (
<AgGrid
ref={ref}
@ -51,7 +56,7 @@ export const OrderListTable = memo(
height: '100%',
}}
getRowId={({ data }) => data.id}
components={{ MarketNameCell }}
components={{ MarketNameCell, OrderTypeCell }}
{...props}
>
<AgGridColumn
@ -103,17 +108,9 @@ export const OrderListTable = memo(
filterParams={{
set: Schema.OrderTypeMapping,
}}
valueFormatter={({
data: order,
value,
}: VegaValueFormatterParams<Order, 'type'>) => {
if (!order) {
return undefined;
}
if (!value) return '-';
if (order?.peggedOrder) return t('Pegged');
if (order?.liquidityProvision) return t('Liquidity provision');
return Schema.OrderTypeMapping[value];
cellRenderer="OrderTypeCell"
cellRendererParams={{
onClick: onOrderTypeClick,
}}
minWidth={80}
/>