feat(trading): deposit to trade collateral tab pinned row (#2921)
This commit is contained in:
parent
989a0456c0
commit
c22fec97b4
@ -96,7 +96,15 @@ export const MarketPage = () => {
|
|||||||
|
|
||||||
const tradeView = useMemo(() => {
|
const tradeView = useMemo(() => {
|
||||||
if (w > 960) {
|
if (w > 960) {
|
||||||
return <TradeGrid market={data} onSelect={onSelect} />;
|
return (
|
||||||
|
<TradeGrid
|
||||||
|
market={data}
|
||||||
|
onSelect={onSelect}
|
||||||
|
pinnedAsset={
|
||||||
|
data?.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<TradePanels
|
<TradePanels
|
||||||
|
@ -28,6 +28,7 @@ import { NO_MARKET } from './constants';
|
|||||||
import { LiquidityContainer } from '../liquidity/liquidity';
|
import { LiquidityContainer } from '../liquidity/liquidity';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
import { Links, Routes } from '../../pages/client-router';
|
||||||
|
import type { PinnedAsset } from '@vegaprotocol/accounts';
|
||||||
|
|
||||||
type MarketDependantView =
|
type MarketDependantView =
|
||||||
| typeof CandlesChartContainer
|
| typeof CandlesChartContainer
|
||||||
@ -65,14 +66,17 @@ type TradingView = keyof typeof TradingViews;
|
|||||||
interface TradeGridProps {
|
interface TradeGridProps {
|
||||||
market: Market | null;
|
market: Market | null;
|
||||||
onSelect: (marketId: string) => void;
|
onSelect: (marketId: string) => void;
|
||||||
|
pinnedAsset?: PinnedAsset;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MainGrid = ({
|
const MainGrid = ({
|
||||||
marketId,
|
marketId,
|
||||||
onSelect,
|
onSelect,
|
||||||
|
pinnedAsset,
|
||||||
}: {
|
}: {
|
||||||
marketId: string;
|
marketId: string;
|
||||||
onSelect?: (marketId: string) => void;
|
onSelect?: (marketId: string) => void;
|
||||||
|
pinnedAsset?: PinnedAsset;
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const onMarketClick = (marketId: string) => {
|
const onMarketClick = (marketId: string) => {
|
||||||
@ -175,7 +179,7 @@ const MainGrid = ({
|
|||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="accounts" name={t('Collateral')}>
|
<Tab id="accounts" name={t('Collateral')}>
|
||||||
<VegaWalletContainer>
|
<VegaWalletContainer>
|
||||||
<TradingViews.Collateral />
|
<TradingViews.Collateral pinnedAsset={pinnedAsset} />
|
||||||
</VegaWalletContainer>
|
</VegaWalletContainer>
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
@ -186,11 +190,19 @@ const MainGrid = ({
|
|||||||
};
|
};
|
||||||
const MainGridWrapped = memo(MainGrid);
|
const MainGridWrapped = memo(MainGrid);
|
||||||
|
|
||||||
export const TradeGrid = ({ market, onSelect }: TradeGridProps) => {
|
export const TradeGrid = ({
|
||||||
|
market,
|
||||||
|
onSelect,
|
||||||
|
pinnedAsset,
|
||||||
|
}: TradeGridProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="h-full grid grid-rows-[min-content_1fr]">
|
<div className="h-full grid grid-rows-[min-content_1fr]">
|
||||||
<TradeMarketHeader market={market} onSelect={onSelect} />
|
<TradeMarketHeader market={market} onSelect={onSelect} />
|
||||||
<MainGridWrapped marketId={market?.id || ''} onSelect={onSelect} />
|
<MainGridWrapped
|
||||||
|
marketId={market?.id || ''}
|
||||||
|
onSelect={onSelect}
|
||||||
|
pinnedAsset={pinnedAsset}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -214,12 +226,14 @@ interface TradePanelsProps {
|
|||||||
onSelect: (marketId: string) => void;
|
onSelect: (marketId: string) => void;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string) => void;
|
||||||
onClickCollateral: () => void;
|
onClickCollateral: () => void;
|
||||||
|
pinnedAsset?: PinnedAsset;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TradePanels = ({
|
export const TradePanels = ({
|
||||||
market,
|
market,
|
||||||
onSelect,
|
onSelect,
|
||||||
onClickCollateral,
|
onClickCollateral,
|
||||||
|
pinnedAsset,
|
||||||
}: TradePanelsProps) => {
|
}: TradePanelsProps) => {
|
||||||
const [view, setView] = useState<TradingView>('Candles');
|
const [view, setView] = useState<TradingView>('Candles');
|
||||||
const renderView = () => {
|
const renderView = () => {
|
||||||
@ -228,6 +242,7 @@ export const TradePanels = ({
|
|||||||
onSelect: (marketId: string) => void;
|
onSelect: (marketId: string) => void;
|
||||||
onMarketClick?: (marketId: string) => void;
|
onMarketClick?: (marketId: string) => void;
|
||||||
onClickCollateral: () => void;
|
onClickCollateral: () => void;
|
||||||
|
pinnedAsset?: PinnedAsset;
|
||||||
}>(TradingViews[view]);
|
}>(TradingViews[view]);
|
||||||
|
|
||||||
if (!Component) {
|
if (!Component) {
|
||||||
@ -241,6 +256,7 @@ export const TradePanels = ({
|
|||||||
marketId={market?.id}
|
marketId={market?.id}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
onClickCollateral={onClickCollateral}
|
onClickCollateral={onClickCollateral}
|
||||||
|
pinnedAsset={pinnedAsset}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -5,10 +5,15 @@ import { useWithdrawalDialog } from '@vegaprotocol/withdraws';
|
|||||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
|
import type { PinnedAsset } from '@vegaprotocol/accounts';
|
||||||
import { AccountManager, useTransferDialog } from '@vegaprotocol/accounts';
|
import { AccountManager, useTransferDialog } from '@vegaprotocol/accounts';
|
||||||
import { useDepositDialog } from '@vegaprotocol/deposits';
|
import { useDepositDialog } from '@vegaprotocol/deposits';
|
||||||
|
|
||||||
export const AccountsContainer = () => {
|
export const AccountsContainer = ({
|
||||||
|
pinnedAsset,
|
||||||
|
}: {
|
||||||
|
pinnedAsset?: PinnedAsset;
|
||||||
|
}) => {
|
||||||
const { pubKey, isReadOnly } = useVegaWallet();
|
const { pubKey, isReadOnly } = useVegaWallet();
|
||||||
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
||||||
const openWithdrawalDialog = useWithdrawalDialog((store) => store.open);
|
const openWithdrawalDialog = useWithdrawalDialog((store) => store.open);
|
||||||
@ -39,6 +44,7 @@ export const AccountsContainer = () => {
|
|||||||
onClickWithdraw={openWithdrawalDialog}
|
onClickWithdraw={openWithdrawalDialog}
|
||||||
onClickDeposit={openDepositDialog}
|
onClickDeposit={openDepositDialog}
|
||||||
isReadOnly={isReadOnly}
|
isReadOnly={isReadOnly}
|
||||||
|
pinnedAsset={pinnedAsset}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{!isReadOnly && (
|
{!isReadOnly && (
|
||||||
|
@ -4,6 +4,7 @@ import type { AgGridReact } from 'ag-grid-react';
|
|||||||
import { useRef, useMemo, memo } from 'react';
|
import { useRef, useMemo, memo } from 'react';
|
||||||
import type { AccountFields } from './accounts-data-provider';
|
import type { AccountFields } from './accounts-data-provider';
|
||||||
import { aggregatedAccountsDataProvider } from './accounts-data-provider';
|
import { aggregatedAccountsDataProvider } from './accounts-data-provider';
|
||||||
|
import type { PinnedAsset } from './accounts-table';
|
||||||
import { AccountTable } from './accounts-table';
|
import { AccountTable } from './accounts-table';
|
||||||
|
|
||||||
interface AccountManagerProps {
|
interface AccountManagerProps {
|
||||||
@ -12,6 +13,7 @@ interface AccountManagerProps {
|
|||||||
onClickWithdraw?: (assetId?: string) => void;
|
onClickWithdraw?: (assetId?: string) => void;
|
||||||
onClickDeposit?: (assetId?: string) => void;
|
onClickDeposit?: (assetId?: string) => void;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
|
pinnedAsset?: PinnedAsset;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AccountManager = ({
|
export const AccountManager = ({
|
||||||
@ -20,6 +22,7 @@ export const AccountManager = ({
|
|||||||
onClickDeposit,
|
onClickDeposit,
|
||||||
partyId,
|
partyId,
|
||||||
isReadOnly,
|
isReadOnly,
|
||||||
|
pinnedAsset,
|
||||||
}: AccountManagerProps) => {
|
}: AccountManagerProps) => {
|
||||||
const gridRef = useRef<AgGridReact | null>(null);
|
const gridRef = useRef<AgGridReact | null>(null);
|
||||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||||
@ -41,6 +44,7 @@ export const AccountManager = ({
|
|||||||
onClickWithdraw={onClickWithdraw}
|
onClickWithdraw={onClickWithdraw}
|
||||||
isReadOnly={isReadOnly}
|
isReadOnly={isReadOnly}
|
||||||
noRowsOverlayComponent={() => null}
|
noRowsOverlayComponent={() => null}
|
||||||
|
pinnedAsset={pinnedAsset}
|
||||||
/>
|
/>
|
||||||
<div className="pointer-events-none absolute inset-0">
|
<div className="pointer-events-none absolute inset-0">
|
||||||
<AsyncRenderer
|
<AsyncRenderer
|
||||||
@ -48,7 +52,7 @@ export const AccountManager = ({
|
|||||||
noDataCondition={(data) => !(data && data.length)}
|
noDataCondition={(data) => !(data && data.length)}
|
||||||
error={error}
|
error={error}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
noDataMessage={t('No accounts')}
|
noDataMessage={pinnedAsset ? ' ' : t('No accounts')}
|
||||||
reload={reload}
|
reload={reload}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -72,7 +72,28 @@ describe('AccountsTable', () => {
|
|||||||
cells.forEach((cell, i) => {
|
cells.forEach((cell, i) => {
|
||||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||||
});
|
});
|
||||||
|
const rows = await screen.findAllByRole('row');
|
||||||
|
expect(rows.length).toBe(6);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should add first asset as pinned', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
render(
|
||||||
|
<AccountTable
|
||||||
|
rowData={singleRowData}
|
||||||
|
onClickAsset={() => null}
|
||||||
|
isReadOnly={false}
|
||||||
|
pinnedAsset={{
|
||||||
|
decimals: 5,
|
||||||
|
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||||
|
symbol: 'tBTC',
|
||||||
|
name: 'tBTC',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
const rows = await screen.findAllByRole('row');
|
||||||
|
expect(rows.length).toBe(9);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get correct account data', () => {
|
it('should get correct account data', () => {
|
||||||
@ -121,3 +142,4 @@ it('should get correct account data', () => {
|
|||||||
];
|
];
|
||||||
expect(result).toEqual(expected);
|
expect(result).toEqual(expected);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { forwardRef, useState } from 'react';
|
import { forwardRef, useMemo, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
isNumeric,
|
isNumeric,
|
||||||
@ -14,6 +14,8 @@ import type { AgGridReact, AgGridReactProps } from 'ag-grid-react';
|
|||||||
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
|
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
|
||||||
import BreakdownTable from './breakdown-table';
|
import BreakdownTable from './breakdown-table';
|
||||||
import type { AccountFields } from './accounts-data-provider';
|
import type { AccountFields } from './accounts-data-provider';
|
||||||
|
import type { Asset } from '@vegaprotocol/types';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
|
||||||
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
|
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
|
||||||
successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void;
|
successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void;
|
||||||
@ -23,6 +25,8 @@ export interface Datasource extends IDatasource {
|
|||||||
getRows(params: GetRowsParams): void;
|
getRows(params: GetRowsParams): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type PinnedAsset = Pick<Asset, 'symbol' | 'name' | 'id' | 'decimals'>;
|
||||||
|
|
||||||
export interface AccountTableProps extends AgGridReactProps {
|
export interface AccountTableProps extends AgGridReactProps {
|
||||||
rowData?: AccountFields[] | null;
|
rowData?: AccountFields[] | null;
|
||||||
datasource?: Datasource;
|
datasource?: Datasource;
|
||||||
@ -30,12 +34,33 @@ export interface AccountTableProps extends AgGridReactProps {
|
|||||||
onClickWithdraw?: (assetId: string) => void;
|
onClickWithdraw?: (assetId: string) => void;
|
||||||
onClickDeposit?: (assetId: string) => void;
|
onClickDeposit?: (assetId: string) => void;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
|
pinnedAsset?: PinnedAsset;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||||
({ onClickAsset, onClickWithdraw, onClickDeposit, ...props }, ref) => {
|
({ onClickAsset, onClickWithdraw, onClickDeposit, ...props }, ref) => {
|
||||||
const [openBreakdown, setOpenBreakdown] = useState(false);
|
const [openBreakdown, setOpenBreakdown] = useState(false);
|
||||||
const [breakdown, setBreakdown] = useState<AccountFields[] | null>(null);
|
const [breakdown, setBreakdown] = useState<AccountFields[] | null>(null);
|
||||||
|
const pinnedAssetId = props.pinnedAsset?.id;
|
||||||
|
|
||||||
|
const pinnedAssetRow = useMemo(() => {
|
||||||
|
const currentPinnedAssetRow = props.rowData?.find(
|
||||||
|
(row) => row.asset.id === pinnedAssetId
|
||||||
|
);
|
||||||
|
if (!currentPinnedAssetRow) {
|
||||||
|
if (props.pinnedAsset) {
|
||||||
|
return {
|
||||||
|
asset: props.pinnedAsset,
|
||||||
|
available: '0',
|
||||||
|
used: '0',
|
||||||
|
deposited: '0',
|
||||||
|
balance: '0',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentPinnedAssetRow;
|
||||||
|
}, [pinnedAssetId, props.pinnedAsset, props.rowData]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AgGrid
|
<AgGrid
|
||||||
@ -51,6 +76,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
sortable: true,
|
sortable: true,
|
||||||
}}
|
}}
|
||||||
{...props}
|
{...props}
|
||||||
|
pinnedTopRowData={pinnedAssetRow ? [pinnedAssetRow] : undefined}
|
||||||
>
|
>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Asset')}
|
headerName={t('Asset')}
|
||||||
@ -138,7 +164,24 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
cellRenderer={({
|
cellRenderer={({
|
||||||
data,
|
data,
|
||||||
}: VegaICellRendererParams<AccountFields>) => {
|
}: VegaICellRendererParams<AccountFields>) => {
|
||||||
return data ? (
|
if (!data) return null;
|
||||||
|
else {
|
||||||
|
if (
|
||||||
|
data.asset.id === pinnedAssetId &&
|
||||||
|
new BigNumber(data.deposited).isLessThanOrEqualTo(0)
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<ButtonLink
|
||||||
|
data-testid="deposit"
|
||||||
|
onClick={() => {
|
||||||
|
onClickDeposit && onClickDeposit(data.asset.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('Deposit to trade')}
|
||||||
|
</ButtonLink>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
<>
|
<>
|
||||||
<ButtonLink
|
<ButtonLink
|
||||||
data-testid="breakdown"
|
data-testid="breakdown"
|
||||||
@ -168,7 +211,8 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
{t('Withdraw')}
|
{t('Withdraw')}
|
||||||
</ButtonLink>
|
</ButtonLink>
|
||||||
</>
|
</>
|
||||||
) : null;
|
);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
Loading…
Reference in New Issue
Block a user