chore(trading): ag-grid upgrade (#4187)
This commit is contained in:
parent
6e9e7c2a5c
commit
43aff8e359
@ -1,15 +1,15 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
import type { AssetFieldsFragment } from '@vegaprotocol/assets';
|
import type { AssetFieldsFragment } from '@vegaprotocol/assets';
|
||||||
import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets';
|
import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
|
||||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||||
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
|
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
|
||||||
import { useRef, useLayoutEffect } from 'react';
|
import { useRef, useLayoutEffect } from 'react';
|
||||||
import { BREAKPOINT_MD } from '../../config/breakpoints';
|
import { BREAKPOINT_MD } from '../../config/breakpoints';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import type { RowClickedEvent } from 'ag-grid-community';
|
import type { RowClickedEvent, ColDef } from 'ag-grid-community';
|
||||||
|
|
||||||
type AssetsTableProps = {
|
type AssetsTableProps = {
|
||||||
data: AssetFieldsFragment[] | null;
|
data: AssetFieldsFragment[] | null;
|
||||||
@ -31,6 +31,58 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const columnDefs = useMemo<ColDef[]>(
|
||||||
|
() => [
|
||||||
|
{ headerName: t('Symbol'), field: 'symbol' },
|
||||||
|
{ headerName: t('Name'), field: 'name' },
|
||||||
|
{
|
||||||
|
flex: 2,
|
||||||
|
headerName: t('ID'),
|
||||||
|
field: 'id',
|
||||||
|
hide: window.innerWidth < BREAKPOINT_MD,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: 'type',
|
||||||
|
headerName: t('Type'),
|
||||||
|
field: 'source.__typename',
|
||||||
|
hide: window.innerWidth < BREAKPOINT_MD,
|
||||||
|
valueFormatter: ({ value }: { value?: string }) =>
|
||||||
|
value ? AssetTypeMapping[value].value : '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Status'),
|
||||||
|
field: 'status',
|
||||||
|
hide: window.innerWidth < BREAKPOINT_MD,
|
||||||
|
valueFormatter: ({ value }: { value?: string }) =>
|
||||||
|
value ? AssetStatusMapping[value].value : '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colId: 'actions',
|
||||||
|
headerName: '',
|
||||||
|
sortable: false,
|
||||||
|
filter: false,
|
||||||
|
resizable: false,
|
||||||
|
wrapText: true,
|
||||||
|
field: 'id',
|
||||||
|
cellRenderer: ({
|
||||||
|
value,
|
||||||
|
}: VegaICellRendererParams<AssetFieldsFragment, 'id'>) =>
|
||||||
|
value ? (
|
||||||
|
<ButtonLink
|
||||||
|
onClick={(e) => {
|
||||||
|
navigate(value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('View details')}
|
||||||
|
</ButtonLink>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[navigate]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@ -46,60 +98,11 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
|||||||
filterParams: { buttons: ['reset'] },
|
filterParams: { buttons: ['reset'] },
|
||||||
autoHeight: true,
|
autoHeight: true,
|
||||||
}}
|
}}
|
||||||
|
columnDefs={columnDefs}
|
||||||
suppressCellFocus={true}
|
suppressCellFocus={true}
|
||||||
onRowClicked={({ data }: RowClickedEvent) => {
|
onRowClicked={({ data }: RowClickedEvent) => {
|
||||||
navigate(data.id);
|
navigate(data.id);
|
||||||
}}
|
}}
|
||||||
>
|
|
||||||
<AgGridColumn headerName={t('Symbol')} field="symbol" />
|
|
||||||
<AgGridColumn headerName={t('Name')} field="name" />
|
|
||||||
<AgGridColumn
|
|
||||||
flex="2"
|
|
||||||
headerName={t('ID')}
|
|
||||||
field="id"
|
|
||||||
hide={window.innerWidth < BREAKPOINT_MD}
|
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
|
||||||
colId="type"
|
|
||||||
headerName={t('Type')}
|
|
||||||
field="source.__typename"
|
|
||||||
hide={window.innerWidth < BREAKPOINT_MD}
|
|
||||||
valueFormatter={({ value }: { value?: string }) =>
|
|
||||||
value && AssetTypeMapping[value].value
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Status')}
|
|
||||||
field="status"
|
|
||||||
hide={window.innerWidth < BREAKPOINT_MD}
|
|
||||||
valueFormatter={({ value }: { value?: string }) =>
|
|
||||||
value && AssetStatusMapping[value].value
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
colId="actions"
|
|
||||||
headerName=""
|
|
||||||
sortable={false}
|
|
||||||
filter={false}
|
|
||||||
resizable={false}
|
|
||||||
wrapText={true}
|
|
||||||
field="id"
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
}: VegaICellRendererParams<AssetFieldsFragment, 'id'>) =>
|
|
||||||
value ? (
|
|
||||||
<ButtonLink
|
|
||||||
onClick={(e) => {
|
|
||||||
navigate(value);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('View details')}
|
|
||||||
</ButtonLink>
|
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</AgGrid>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
import type { MarketFieldsFragment } from '@vegaprotocol/markets';
|
import type { MarketFieldsFragment } from '@vegaprotocol/markets';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
import type { ColDef } from 'ag-grid-community';
|
||||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||||
import type {
|
import type {
|
||||||
VegaICellRendererParams,
|
VegaICellRendererParams,
|
||||||
@ -39,54 +40,34 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
const columnDefs = useMemo<ColDef[]>(
|
||||||
<AgGrid
|
() => [
|
||||||
ref={gridRef}
|
{
|
||||||
rowData={data}
|
colId: 'code',
|
||||||
getRowId={({ data }: { data: MarketFieldsFragment }) => data.id}
|
headerName: t('Code'),
|
||||||
overlayNoRowsTemplate={t('This chain has no markets')}
|
field: 'tradableInstrument.instrument.code',
|
||||||
domLayout="autoHeight"
|
},
|
||||||
defaultColDef={{
|
{
|
||||||
flex: 1,
|
colId: 'name',
|
||||||
resizable: true,
|
headerName: t('Name'),
|
||||||
sortable: true,
|
field: 'tradableInstrument.instrument.name',
|
||||||
filter: true,
|
},
|
||||||
filterParams: { buttons: ['reset'] },
|
{
|
||||||
autoHeight: true,
|
headerName: t('Status'),
|
||||||
}}
|
field: 'state',
|
||||||
suppressCellFocus={true}
|
hide: window.innerWidth <= BREAKPOINT_MD,
|
||||||
onRowClicked={({ data, event }: RowClickedEvent) => {
|
valueGetter: ({
|
||||||
if ((event?.target as HTMLElement).tagName.toUpperCase() !== 'BUTTON') {
|
|
||||||
navigate(data.id);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AgGridColumn
|
|
||||||
colId="code"
|
|
||||||
headerName={t('Code')}
|
|
||||||
field="tradableInstrument.instrument.code"
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
colId="name"
|
|
||||||
headerName={t('Name')}
|
|
||||||
field="tradableInstrument.instrument.name"
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Status')}
|
|
||||||
field="state"
|
|
||||||
hide={window.innerWidth <= BREAKPOINT_MD}
|
|
||||||
valueGetter={({
|
|
||||||
data,
|
data,
|
||||||
}: VegaValueGetterParams<MarketFieldsFragment>) => {
|
}: VegaValueGetterParams<MarketFieldsFragment>) => {
|
||||||
return data?.state ? MarketStateMapping[data?.state] : '-';
|
return data?.state ? MarketStateMapping[data?.state] : '-';
|
||||||
}}
|
},
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
colId="asset"
|
colId: 'asset',
|
||||||
headerName={t('Settlement asset')}
|
headerName: t('Settlement asset'),
|
||||||
field="tradableInstrument.instrument.product.settlementAsset.symbol"
|
field: 'tradableInstrument.instrument.product.settlementAsset.symbol',
|
||||||
hide={window.innerWidth <= BREAKPOINT_MD}
|
hide: window.innerWidth <= BREAKPOINT_MD,
|
||||||
cellRenderer={({
|
cellRenderer: ({
|
||||||
data,
|
data,
|
||||||
}: VegaICellRendererParams<
|
}: VegaICellRendererParams<
|
||||||
MarketFieldsFragment,
|
MarketFieldsFragment,
|
||||||
@ -105,19 +86,19 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
|||||||
) : (
|
) : (
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
}}
|
},
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
flex={2}
|
flex: 2,
|
||||||
headerName={t('Market ID')}
|
headerName: t('Market ID'),
|
||||||
field="id"
|
field: 'id',
|
||||||
hide={window.innerWidth <= BREAKPOINT_MD}
|
hide: window.innerWidth <= BREAKPOINT_MD,
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
colId="actions"
|
colId: 'actions',
|
||||||
headerName=""
|
headerName: '',
|
||||||
field="id"
|
field: 'id',
|
||||||
cellRenderer={({
|
cellRenderer: ({
|
||||||
value,
|
value,
|
||||||
}: VegaICellRendererParams<MarketFieldsFragment, 'id'>) =>
|
}: VegaICellRendererParams<MarketFieldsFragment, 'id'>) =>
|
||||||
value ? (
|
value ? (
|
||||||
@ -126,9 +107,34 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
|||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
''
|
''
|
||||||
)
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[openAssetDetailsDialog]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AgGrid
|
||||||
|
ref={gridRef}
|
||||||
|
rowData={data}
|
||||||
|
getRowId={({ data }: { data: MarketFieldsFragment }) => data.id}
|
||||||
|
overlayNoRowsTemplate={t('This chain has no markets')}
|
||||||
|
domLayout="autoHeight"
|
||||||
|
defaultColDef={{
|
||||||
|
flex: 1,
|
||||||
|
resizable: true,
|
||||||
|
sortable: true,
|
||||||
|
filter: true,
|
||||||
|
filterParams: { buttons: ['reset'] },
|
||||||
|
autoHeight: true,
|
||||||
|
}}
|
||||||
|
columnDefs={columnDefs}
|
||||||
|
suppressCellFocus={true}
|
||||||
|
onRowClicked={({ data, event }: RowClickedEvent) => {
|
||||||
|
if ((event?.target as HTMLElement).tagName.toUpperCase() !== 'BUTTON') {
|
||||||
|
navigate(data.id);
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</AgGrid>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
||||||
import { VoteProgress } from '@vegaprotocol/proposals';
|
import { VoteProgress } from '@vegaprotocol/proposals';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
|
||||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||||
import type {
|
import type {
|
||||||
@ -9,7 +8,7 @@ import type {
|
|||||||
VegaValueFormatterParams,
|
VegaValueFormatterParams,
|
||||||
} from '@vegaprotocol/datagrid';
|
} from '@vegaprotocol/datagrid';
|
||||||
import { useLayoutEffect, useMemo, useRef, useState } from 'react';
|
import { useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||||
import type { RowClickedEvent } from 'ag-grid-community';
|
import type { RowClickedEvent, ColDef } from 'ag-grid-community';
|
||||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import {
|
import {
|
||||||
@ -64,67 +63,38 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
|||||||
title: '',
|
title: '',
|
||||||
content: null,
|
content: null,
|
||||||
});
|
});
|
||||||
|
const columnDefs = useMemo<ColDef[]>(
|
||||||
return (
|
() => [
|
||||||
<>
|
{
|
||||||
<AgGrid
|
colId: 'title',
|
||||||
ref={gridRef}
|
headerName: t('Title'),
|
||||||
rowData={data}
|
field: 'rationale.title',
|
||||||
getRowId={({ data }: { data: ProposalListFieldsFragment }) =>
|
flex: 2,
|
||||||
data.id || data.rationale.title
|
wrapText: true,
|
||||||
}
|
},
|
||||||
overlayNoRowsTemplate={t('This chain has no markets')}
|
{
|
||||||
domLayout="autoHeight"
|
colId: 'type',
|
||||||
defaultColDef={{
|
maxWidth: 180,
|
||||||
flex: 1,
|
hide: window.innerWidth <= BREAKPOINT_MD,
|
||||||
resizable: true,
|
headerName: t('Type'),
|
||||||
sortable: true,
|
field: 'terms.change.__typename',
|
||||||
filter: true,
|
},
|
||||||
filterParams: { buttons: ['reset'] },
|
{
|
||||||
autoHeight: true,
|
maxWidth: 100,
|
||||||
}}
|
headerName: t('State'),
|
||||||
suppressCellFocus={true}
|
field: 'state',
|
||||||
onRowClicked={({ data, event }: RowClickedEvent) => {
|
valueFormatter: ({
|
||||||
if (
|
|
||||||
(event?.target as HTMLElement).tagName.toUpperCase() !== 'BUTTON'
|
|
||||||
) {
|
|
||||||
const proposalPage = tokenLink(
|
|
||||||
TOKEN_PROPOSAL.replace(':id', data.id)
|
|
||||||
);
|
|
||||||
window.open(proposalPage, '_blank');
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AgGridColumn
|
|
||||||
colId="title"
|
|
||||||
headerName={t('Title')}
|
|
||||||
field="rationale.title"
|
|
||||||
flex={2}
|
|
||||||
wrapText={true}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
colId="type"
|
|
||||||
maxWidth={180}
|
|
||||||
hide={window.innerWidth <= BREAKPOINT_MD}
|
|
||||||
headerName={t('Type')}
|
|
||||||
field="terms.change.__typename"
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
maxWidth={100}
|
|
||||||
headerName={t('State')}
|
|
||||||
field="state"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
value,
|
||||||
}: VegaValueFormatterParams<ProposalListFieldsFragment, 'state'>) => {
|
}: VegaValueFormatterParams<ProposalListFieldsFragment, 'state'>) => {
|
||||||
return value ? ProposalStateMapping[value] : '-';
|
return value ? ProposalStateMapping[value] : '-';
|
||||||
}}
|
},
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
colId="voting"
|
colId: 'voting',
|
||||||
maxWidth={100}
|
maxWidth: 100,
|
||||||
hide={window.innerWidth <= BREAKPOINT_MD}
|
hide: window.innerWidth <= BREAKPOINT_MD,
|
||||||
headerName={t('Voting')}
|
headerName: t('Voting'),
|
||||||
cellRenderer={({
|
cellRenderer: ({
|
||||||
data,
|
data,
|
||||||
}: VegaICellRendererParams<ProposalListFieldsFragment>) => {
|
}: VegaICellRendererParams<ProposalListFieldsFragment>) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -144,46 +114,46 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return '-';
|
return '-';
|
||||||
}}
|
},
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
colId="cDate"
|
colId: 'cDate',
|
||||||
maxWidth={150}
|
maxWidth: 150,
|
||||||
hide={window.innerWidth <= BREAKPOINT_MD}
|
hide: window.innerWidth <= BREAKPOINT_MD,
|
||||||
headerName={t('Closing date')}
|
headerName: t('Closing date'),
|
||||||
field="terms.closingDatetime"
|
field: 'terms.closingDatetime',
|
||||||
valueFormatter={({
|
valueFormatter: ({
|
||||||
value,
|
value,
|
||||||
}: VegaValueFormatterParams<
|
}: VegaValueFormatterParams<
|
||||||
ProposalListFieldsFragment,
|
ProposalListFieldsFragment,
|
||||||
'terms.closingDatetime'
|
'terms.closingDatetime'
|
||||||
>) => {
|
>) => {
|
||||||
return value ? getDateTimeFormat().format(new Date(value)) : '-';
|
return value ? getDateTimeFormat().format(new Date(value)) : '-';
|
||||||
}}
|
},
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
colId="eDate"
|
colId: 'eDate',
|
||||||
maxWidth={150}
|
maxWidth: 150,
|
||||||
hide={window.innerWidth <= BREAKPOINT_MD}
|
hide: window.innerWidth <= BREAKPOINT_MD,
|
||||||
headerName={t('Enactment date')}
|
headerName: t('Enactment date'),
|
||||||
field="terms.enactmentDatetime"
|
field: 'terms.enactmentDatetime',
|
||||||
valueFormatter={({
|
valueFormatte: ({
|
||||||
value,
|
value,
|
||||||
}: VegaValueFormatterParams<
|
}: VegaValueFormatterParams<
|
||||||
ProposalListFieldsFragment,
|
ProposalListFieldsFragment,
|
||||||
'terms.enactmentDatetime'
|
'terms.enactmentDatetime'
|
||||||
>) => {
|
>) => {
|
||||||
return value ? getDateTimeFormat().format(new Date(value)) : '-';
|
return value ? getDateTimeFormat().format(new Date(value)) : '-';
|
||||||
}}
|
},
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
colId="actions"
|
colId: 'actions',
|
||||||
minWidth={window.innerWidth > BREAKPOINT_MD ? 221 : 80}
|
minWidth: window.innerWidth > BREAKPOINT_MD ? 221 : 80,
|
||||||
maxWidth={221}
|
maxWidth: 221,
|
||||||
sortable={false}
|
sortable: false,
|
||||||
filter={false}
|
filter: false,
|
||||||
resizable={false}
|
resizable: false,
|
||||||
cellRenderer={({
|
cellRenderer: ({
|
||||||
data,
|
data,
|
||||||
}: VegaICellRendererParams<ProposalListFieldsFragment>) => {
|
}: VegaICellRendererParams<ProposalListFieldsFragment>) => {
|
||||||
const proposalPage = tokenLink(
|
const proposalPage = tokenLink(
|
||||||
@ -199,10 +169,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="pb-1">
|
<div className="pb-1">
|
||||||
<button
|
<button className="underline max-md:hidden" onClick={openDialog}>
|
||||||
className="underline max-md:hidden"
|
|
||||||
onClick={openDialog}
|
|
||||||
>
|
|
||||||
{t('View terms')}
|
{t('View terms')}
|
||||||
</button>{' '}
|
</button>{' '}
|
||||||
<ExternalLink className="max-md:hidden" href={proposalPage}>
|
<ExternalLink className="max-md:hidden" href={proposalPage}>
|
||||||
@ -213,9 +180,42 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
|||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[requiredMajorityPercentage, tokenLink]
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AgGrid
|
||||||
|
ref={gridRef}
|
||||||
|
rowData={data}
|
||||||
|
getRowId={({ data }: { data: ProposalListFieldsFragment }) =>
|
||||||
|
data.id || data.rationale.title
|
||||||
|
}
|
||||||
|
overlayNoRowsTemplate={t('This chain has no markets')}
|
||||||
|
domLayout="autoHeight"
|
||||||
|
defaultColDef={{
|
||||||
|
flex: 1,
|
||||||
|
resizable: true,
|
||||||
|
sortable: true,
|
||||||
|
filter: true,
|
||||||
|
filterParams: { buttons: ['reset'] },
|
||||||
|
autoHeight: true,
|
||||||
|
}}
|
||||||
|
columnDefs={columnDefs}
|
||||||
|
suppressCellFocus={true}
|
||||||
|
onRowClicked={({ data, event }: RowClickedEvent) => {
|
||||||
|
if (
|
||||||
|
(event?.target as HTMLElement).tagName.toUpperCase() !== 'BUTTON'
|
||||||
|
) {
|
||||||
|
const proposalPage = tokenLink(
|
||||||
|
TOKEN_PROPOSAL.replace(':id', data.id)
|
||||||
|
);
|
||||||
|
window.open(proposalPage, '_blank');
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</AgGrid>
|
|
||||||
<JsonViewerDialog
|
<JsonViewerDialog
|
||||||
open={dialog.open}
|
open={dialog.open}
|
||||||
onChange={(isOpen) => setDialog({ ...dialog, open: isOpen })}
|
onChange={(isOpen) => setDialog({ ...dialog, open: isOpen })}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
@import 'ag-grid-community/dist/styles/ag-grid.css';
|
@import 'ag-grid-community/styles/ag-grid.css';
|
||||||
@import 'ag-grid-community/dist/styles/ag-theme-balham.css';
|
@import 'ag-grid-community/styles/ag-theme-balham.css';
|
||||||
@import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
|
|
||||||
|
|
||||||
/* You can add global styles to this file, and also import other style files */
|
/* You can add global styles to this file, and also import other style files */
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
|
6
apps/governance/__mocks__/react-markdown.js
vendored
6
apps/governance/__mocks__/react-markdown.js
vendored
@ -1,6 +0,0 @@
|
|||||||
function ReactMarkdown({ children }) {
|
|
||||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
||||||
return <>{children}</>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ReactMarkdown;
|
|
@ -1,6 +1,5 @@
|
|||||||
@import 'ag-grid-community/dist/styles/ag-grid.css';
|
@import 'ag-grid-community/styles/ag-grid.css';
|
||||||
@import 'ag-grid-community/dist/styles/ag-theme-balham.css';
|
@import 'ag-grid-community/styles/ag-theme-balham.css';
|
||||||
@import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
|
|
||||||
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
|
@ -21,11 +21,14 @@ import {
|
|||||||
HealthBar,
|
HealthBar,
|
||||||
TooltipCellComponent,
|
TooltipCellComponent,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import type { GetRowIdParams, RowClickedEvent } from 'ag-grid-community';
|
import type {
|
||||||
import 'ag-grid-community/dist/styles/ag-grid.css';
|
GetRowIdParams,
|
||||||
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
|
RowClickedEvent,
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
ColDef,
|
||||||
import { useCallback, useState } from 'react';
|
} from 'ag-grid-community';
|
||||||
|
import 'ag-grid-community/styles/ag-grid.css';
|
||||||
|
import 'ag-grid-community/styles/ag-theme-alpine.css';
|
||||||
|
import { useCallback, useState, useMemo } from 'react';
|
||||||
|
|
||||||
import { Grid } from '../../grid';
|
import { Grid } from '../../grid';
|
||||||
import { HealthDialog } from '../../health-dialog';
|
import { HealthDialog } from '../../health-dialog';
|
||||||
@ -39,6 +42,234 @@ export const MarketList = () => {
|
|||||||
const consoleLink = useLinks(DApp.Console);
|
const consoleLink = useLinks(DApp.Console);
|
||||||
|
|
||||||
const getRowId = useCallback(({ data }: GetRowIdParams) => data.id, []);
|
const getRowId = useCallback(({ data }: GetRowIdParams) => data.id, []);
|
||||||
|
const columnDefs = useMemo<ColDef[]>(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
headerName: t('Market (futures)'),
|
||||||
|
field: 'tradableInstrument.instrument.name',
|
||||||
|
cellRenderer: ({ value, data }: { value: string; data: Market }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span className="leading-3">{value}</span>
|
||||||
|
<span className="leading-3">
|
||||||
|
{
|
||||||
|
data?.tradableInstrument?.instrument?.product?.settlementAsset
|
||||||
|
?.symbol
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
minWidth: 100,
|
||||||
|
flex: 1,
|
||||||
|
headerTooltip: t('The market name and settlement asset'),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('Market Code'),
|
||||||
|
headerTooltip: t(
|
||||||
|
'The market code is a unique identifier for this market'
|
||||||
|
),
|
||||||
|
field: 'tradableInstrument.instrument.code',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('Type'),
|
||||||
|
headerTooltip: t('Type'),
|
||||||
|
field: 'tradableInstrument.instrument.product.__typename',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('Last Price'),
|
||||||
|
headerTooltip: t('Latest price for this market'),
|
||||||
|
field: 'data.markPrice',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<Market, 'data.markPrice'>) =>
|
||||||
|
value && data
|
||||||
|
? formatWithAsset(
|
||||||
|
value,
|
||||||
|
data.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
)
|
||||||
|
: '-',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('Change (24h)'),
|
||||||
|
headerTooltip: t('Change in price over the last 24h'),
|
||||||
|
cellRenderer: ({
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<Market, 'data.candles'>) => {
|
||||||
|
if (data && data.candles) {
|
||||||
|
const prices = data.candles.map((candle) => candle.close);
|
||||||
|
return (
|
||||||
|
<PriceChangeCell
|
||||||
|
candles={prices}
|
||||||
|
decimalPlaces={data?.decimalPlaces}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else return <div>{t('-')}</div>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('Volume (24h)'),
|
||||||
|
field: 'dayVolume',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<Market, 'dayVolume'>) =>
|
||||||
|
value && data
|
||||||
|
? `${addDecimalsFormatNumber(
|
||||||
|
value,
|
||||||
|
data.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
.decimals
|
||||||
|
)} (${displayChange(data.volumeChange)})`
|
||||||
|
: '-',
|
||||||
|
headerTooltip: t('The trade volume over the last 24h'),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('Total staked by LPs'),
|
||||||
|
field: 'liquidityCommitted',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<Market, 'liquidityCommitted'>) =>
|
||||||
|
data && value
|
||||||
|
? formatWithAsset(
|
||||||
|
value.toString(),
|
||||||
|
data.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
)
|
||||||
|
: '-',
|
||||||
|
headerTooltip: t('The amount of funds allocated to provide liquidity'),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('Target stake'),
|
||||||
|
field: 'target',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<Market, 'target'>) =>
|
||||||
|
data && value
|
||||||
|
? formatWithAsset(
|
||||||
|
value,
|
||||||
|
data.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
)
|
||||||
|
: '-',
|
||||||
|
headerTooltip: t(
|
||||||
|
'The ideal committed liquidity to operate the market. If total commitment currently below this level then LPs can set the fee level with new commitment.'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('% Target stake met'),
|
||||||
|
valueFormatter: ({ data }: VegaValueFormatterParams<Market, ''>) => {
|
||||||
|
if (data) {
|
||||||
|
const roundedPercentage =
|
||||||
|
parseInt(
|
||||||
|
(data.liquidityCommitted / parseFloat(data.target)).toFixed(0)
|
||||||
|
) * 100;
|
||||||
|
const display = Number.isNaN(roundedPercentage)
|
||||||
|
? 'N/A'
|
||||||
|
: formatNumberPercentage(toBigNum(roundedPercentage, 0), 0);
|
||||||
|
return display;
|
||||||
|
} else return '-';
|
||||||
|
},
|
||||||
|
headerTooltip: t('% Target stake met'),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('Fee levels'),
|
||||||
|
field: 'fees',
|
||||||
|
valueFormatter: ({ value }: VegaValueFormatterParams<Market, 'fees'>) =>
|
||||||
|
value ? `${value.factors.liquidityFee}%` : '-',
|
||||||
|
headerTooltip: t('Fee level for this market'),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('Status'),
|
||||||
|
field: 'tradingMode',
|
||||||
|
cellRenderer: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
value: Schema.MarketTradingMode;
|
||||||
|
data: Market;
|
||||||
|
}) => {
|
||||||
|
return <Status trigger={data.data?.trigger} tradingMode={value} />;
|
||||||
|
},
|
||||||
|
headerTooltip: t(
|
||||||
|
'The current market status - those below the target stake mark are most in need of liquidity'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerComponent: () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<span>{t('Health')}</span>{' '}
|
||||||
|
<button
|
||||||
|
onClick={() => setIsHealthDialogOpen(true)}
|
||||||
|
aria-label={t('open tooltip')}
|
||||||
|
>
|
||||||
|
<Icon name="info-sign" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
field: 'tradingMode',
|
||||||
|
cellRenderer: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
value: Schema.MarketTradingMode;
|
||||||
|
data: Market;
|
||||||
|
}) => (
|
||||||
|
<HealthBar
|
||||||
|
target={data.target}
|
||||||
|
decimals={
|
||||||
|
data.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
.decimals
|
||||||
|
}
|
||||||
|
levels={data.feeLevels}
|
||||||
|
intent={intentForStatus(value)}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
sortable: false,
|
||||||
|
cellStyle: { overflow: 'unset' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Age'),
|
||||||
|
field: 'marketTimestamps.open',
|
||||||
|
headerTooltip: t('Age of the market'),
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
}: VegaValueFormatterParams<Market, 'marketTimestamps.open'>) => {
|
||||||
|
return value ? formatDistanceToNow(new Date(value)) : '-';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Closing Time'),
|
||||||
|
field: 'tradableInstrument.instrument.metadata.tags',
|
||||||
|
headerTooltip: t('Closing time of the market'),
|
||||||
|
valueFormatter: ({ data }: VegaValueFormatterParams<Market, ''>) => {
|
||||||
|
let expiry;
|
||||||
|
if (data?.tradableInstrument.instrument.metadata.tags) {
|
||||||
|
expiry = getExpiryDate(
|
||||||
|
data?.tradableInstrument.instrument.metadata.tags,
|
||||||
|
data?.marketTimestamps.close,
|
||||||
|
data?.state
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return expiry ? expiry : '-';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||||
@ -64,258 +295,11 @@ export const MarketList = () => {
|
|||||||
cellClass: ['flex', 'flex-col', 'justify-center'],
|
cellClass: ['flex', 'flex-col', 'justify-center'],
|
||||||
tooltipComponent: TooltipCellComponent,
|
tooltipComponent: TooltipCellComponent,
|
||||||
}}
|
}}
|
||||||
|
columnDefs={columnDefs}
|
||||||
getRowId={getRowId}
|
getRowId={getRowId}
|
||||||
isRowClickable
|
isRowClickable
|
||||||
tooltipShowDelay={500}
|
tooltipShowDelay={500}
|
||||||
>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Market (futures)')}
|
|
||||||
field="tradableInstrument.instrument.name"
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: {
|
|
||||||
value: string;
|
|
||||||
data: Market;
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<span className="leading-3">{value}</span>
|
|
||||||
<span className="leading-3">
|
|
||||||
{
|
|
||||||
data?.tradableInstrument?.instrument?.product
|
|
||||||
?.settlementAsset?.symbol
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
minWidth={100}
|
|
||||||
flex="1"
|
|
||||||
headerTooltip={t('The market name and settlement asset')}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Market Code')}
|
|
||||||
headerTooltip={t(
|
|
||||||
'The market code is a unique identifier for this market'
|
|
||||||
)}
|
|
||||||
field="tradableInstrument.instrument.code"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Type')}
|
|
||||||
headerTooltip={t('Type')}
|
|
||||||
field="tradableInstrument.instrument.product.__typename"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Last Price')}
|
|
||||||
headerTooltip={t('Latest price for this market')}
|
|
||||||
field="data.markPrice"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<Market, 'data.markPrice'>) =>
|
|
||||||
value && data
|
|
||||||
? formatWithAsset(
|
|
||||||
value,
|
|
||||||
data.tradableInstrument.instrument.product.settlementAsset
|
|
||||||
)
|
|
||||||
: '-'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Change (24h)')}
|
|
||||||
headerTooltip={t('Change in price over the last 24h')}
|
|
||||||
cellRenderer={({
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<Market, 'data.candles'>) => {
|
|
||||||
if (data && data.candles) {
|
|
||||||
const prices = data.candles.map((candle) => candle.close);
|
|
||||||
return (
|
|
||||||
<PriceChangeCell
|
|
||||||
candles={prices}
|
|
||||||
decimalPlaces={data?.decimalPlaces}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else return <div>{t('-')}</div>;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Volume (24h)')}
|
|
||||||
field="dayVolume"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<Market, 'dayVolume'>) =>
|
|
||||||
value && data
|
|
||||||
? `${addDecimalsFormatNumber(
|
|
||||||
value,
|
|
||||||
data.tradableInstrument.instrument.product.settlementAsset
|
|
||||||
.decimals
|
|
||||||
)} (${displayChange(data.volumeChange)})`
|
|
||||||
: '-'
|
|
||||||
}
|
|
||||||
headerTooltip={t('The trade volume over the last 24h')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Total staked by LPs')}
|
|
||||||
field="liquidityCommitted"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<Market, 'liquidityCommitted'>) =>
|
|
||||||
data && value
|
|
||||||
? formatWithAsset(
|
|
||||||
value.toString(),
|
|
||||||
data.tradableInstrument.instrument.product.settlementAsset
|
|
||||||
)
|
|
||||||
: '-'
|
|
||||||
}
|
|
||||||
headerTooltip={t(
|
|
||||||
'The amount of funds allocated to provide liquidity'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Target stake')}
|
|
||||||
field="target"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<Market, 'target'>) =>
|
|
||||||
data && value
|
|
||||||
? formatWithAsset(
|
|
||||||
value,
|
|
||||||
data.tradableInstrument.instrument.product.settlementAsset
|
|
||||||
)
|
|
||||||
: '-'
|
|
||||||
}
|
|
||||||
headerTooltip={t(
|
|
||||||
'The ideal committed liquidity to operate the market. If total commitment currently below this level then LPs can set the fee level with new commitment.'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('% Target stake met')}
|
|
||||||
valueFormatter={({
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<Market, ''>) => {
|
|
||||||
if (data) {
|
|
||||||
const roundedPercentage =
|
|
||||||
parseInt(
|
|
||||||
(data.liquidityCommitted / parseFloat(data.target)).toFixed(
|
|
||||||
0
|
|
||||||
)
|
|
||||||
) * 100;
|
|
||||||
const display = Number.isNaN(roundedPercentage)
|
|
||||||
? 'N/A'
|
|
||||||
: formatNumberPercentage(toBigNum(roundedPercentage, 0), 0);
|
|
||||||
return display;
|
|
||||||
} else return '-';
|
|
||||||
}}
|
|
||||||
headerTooltip={t('% Target stake met')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Fee levels')}
|
|
||||||
field="fees"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<Market, 'fees'>) =>
|
|
||||||
value ? `${value.factors.liquidityFee}%` : '-'
|
|
||||||
}
|
|
||||||
headerTooltip={t('Fee level for this market')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Status')}
|
|
||||||
field="tradingMode"
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: {
|
|
||||||
value: Schema.MarketTradingMode;
|
|
||||||
data: Market;
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<Status trigger={data.data?.trigger} tradingMode={value} />
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
headerTooltip={t(
|
|
||||||
'The current market status - those below the target stake mark are most in need of liquidity'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerComponent={() => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<span>{t('Health')}</span>{' '}
|
|
||||||
<button
|
|
||||||
onClick={() => setIsHealthDialogOpen(true)}
|
|
||||||
aria-label={t('open tooltip')}
|
|
||||||
>
|
|
||||||
<Icon name="info-sign" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
field="tradingMode"
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: {
|
|
||||||
value: Schema.MarketTradingMode;
|
|
||||||
data: Market;
|
|
||||||
}) => (
|
|
||||||
<HealthBar
|
|
||||||
target={data.target}
|
|
||||||
decimals={
|
|
||||||
data.tradableInstrument.instrument.product.settlementAsset
|
|
||||||
.decimals
|
|
||||||
}
|
|
||||||
levels={data.feeLevels}
|
|
||||||
intent={intentForStatus(value)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
sortable={false}
|
|
||||||
cellStyle={{ overflow: 'unset' }}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Age')}
|
|
||||||
field="marketTimestamps.open"
|
|
||||||
headerTooltip={t('Age of the market')}
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<Market, 'marketTimestamps.open'>) => {
|
|
||||||
return value ? formatDistanceToNow(new Date(value)) : '-';
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Closing Time')}
|
|
||||||
field="tradableInstrument.instrument.metadata.tags"
|
|
||||||
headerTooltip={t('Closing time of the market')}
|
|
||||||
valueFormatter={({
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<Market, ''>) => {
|
|
||||||
let expiry;
|
|
||||||
if (data?.tradableInstrument.instrument.metadata.tags) {
|
|
||||||
expiry = getExpiryDate(
|
|
||||||
data?.tradableInstrument.instrument.metadata.tags,
|
|
||||||
data?.marketTimestamps.close,
|
|
||||||
data?.state
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return expiry ? expiry : '-';
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<HealthDialog
|
<HealthDialog
|
||||||
isOpen={isHealthDialogOpen}
|
isOpen={isHealthDialogOpen}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
|
||||||
|
|
||||||
import type { GetRowIdParams } from 'ag-grid-community';
|
import type { GetRowIdParams, ColDef } from 'ag-grid-community';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
@ -36,6 +35,75 @@ export const LPProvidersGrid = ({
|
|||||||
};
|
};
|
||||||
}) => {
|
}) => {
|
||||||
const getRowId = useCallback(({ data }: GetRowIdParams) => data.party.id, []);
|
const getRowId = useCallback(({ data }: GetRowIdParams) => data.party.id, []);
|
||||||
|
const columnDefs = useMemo<ColDef[]>(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
headerName: t('LPs'),
|
||||||
|
field: 'party.id',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 100,
|
||||||
|
headerTooltip: t('Liquidity providers'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Duration'),
|
||||||
|
valueFormatter: formatToHours,
|
||||||
|
field: 'createdAt',
|
||||||
|
headerTooltip: t('Time in market'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Equity-like share'),
|
||||||
|
field: 'equityLikeShare',
|
||||||
|
valueFormatter: ({ value }: { value?: string | null }) => {
|
||||||
|
return value
|
||||||
|
? `${parseFloat(parseFloat(value).toFixed(2)) * 100}%`
|
||||||
|
: '';
|
||||||
|
},
|
||||||
|
headerTooltip: t(
|
||||||
|
'The share of the markets liquidity held - the earlier you commit liquidity the greater % fees you earn'
|
||||||
|
),
|
||||||
|
minWidth: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('committed bond'),
|
||||||
|
field: 'commitmentAmount',
|
||||||
|
valueFormatter: ({ value }: { value?: string | null }) =>
|
||||||
|
value ? formatWithAsset(value, settlementAsset) : '0',
|
||||||
|
headerTooltip: t('The amount of funds allocated to provide liquidity'),
|
||||||
|
minWidth: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Margin Req.'),
|
||||||
|
field: 'margin',
|
||||||
|
headerTooltip: t(
|
||||||
|
'Margin required for arising positions based on liquidity commitment'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('24h Fees'),
|
||||||
|
field: 'fees',
|
||||||
|
headerTooltip: t(
|
||||||
|
'Total fees earned by the liquidity provider in the last 24 hours'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Fee level'),
|
||||||
|
valueFormatter: ({ value }: { value?: string | null }) => `${value}%`,
|
||||||
|
field: 'fee',
|
||||||
|
headerTooltip: t(
|
||||||
|
"The market's liquidity fee, or the percentage of a trade's value which is collected from the price taker for every trade"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
headerName: t('APY'),
|
||||||
|
field: 'apy',
|
||||||
|
headerTooltip: t(
|
||||||
|
'An annualised estimate based on the total liquidity provision fees and maker fees collected by liquidity providers, the maximum margin needed and maximum commitment (bond) over the course of 7 epochs'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[settlementAsset]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Grid
|
||||||
@ -49,74 +117,9 @@ export const LPProvidersGrid = ({
|
|||||||
tooltipComponent: TooltipCellComponent,
|
tooltipComponent: TooltipCellComponent,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
}}
|
}}
|
||||||
|
columnDefs={columnDefs}
|
||||||
getRowId={getRowId}
|
getRowId={getRowId}
|
||||||
rowHeight={92}
|
rowHeight={92}
|
||||||
>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('LPs')}
|
|
||||||
field="party.id"
|
|
||||||
flex="1"
|
|
||||||
minWidth={100}
|
|
||||||
headerTooltip={t('Liquidity providers')}
|
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Duration')}
|
|
||||||
valueFormatter={formatToHours}
|
|
||||||
field="createdAt"
|
|
||||||
headerTooltip={t('Time in market')}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Equity-like share')}
|
|
||||||
field="equityLikeShare"
|
|
||||||
valueFormatter={({ value }: { value?: string | null }) => {
|
|
||||||
return value
|
|
||||||
? `${parseFloat(parseFloat(value).toFixed(2)) * 100}%`
|
|
||||||
: '';
|
|
||||||
}}
|
|
||||||
headerTooltip={t(
|
|
||||||
'The share of the markets liquidity held - the earlier you commit liquidity the greater % fees you earn'
|
|
||||||
)}
|
|
||||||
minWidth={140}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('committed bond')}
|
|
||||||
field="commitmentAmount"
|
|
||||||
valueFormatter={({ value }: { value?: string | null }) =>
|
|
||||||
value ? formatWithAsset(value, settlementAsset) : '0'
|
|
||||||
}
|
|
||||||
headerTooltip={t('The amount of funds allocated to provide liquidity')}
|
|
||||||
minWidth={140}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Margin Req.')}
|
|
||||||
field="margin"
|
|
||||||
headerTooltip={t(
|
|
||||||
'Margin required for arising positions based on liquidity commitment'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('24h Fees')}
|
|
||||||
field="fees"
|
|
||||||
headerTooltip={t(
|
|
||||||
'Total fees earned by the liquidity provider in the last 24 hours'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Fee level')}
|
|
||||||
valueFormatter={({ value }: { value?: string | null }) => `${value}%`}
|
|
||||||
field="fee"
|
|
||||||
headerTooltip={t(
|
|
||||||
"The market's liquidity fee, or the percentage of a trade's value which is collected from the price taker for every trade"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('APY')}
|
|
||||||
field="apy"
|
|
||||||
headerTooltip={t(
|
|
||||||
'An annualised estimate based on the total liquidity provision fees and maker fees collected by liquidity providers, the maximum margin needed and maximum commitment (bond) over the course of 7 epochs'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { useRef, useCallback, useEffect } from 'react';
|
import { useRef, useCallback, useEffect } from 'react';
|
||||||
import type { ReactNode } from 'react';
|
|
||||||
import { AgGridReact } from 'ag-grid-react';
|
import { AgGridReact } from 'ag-grid-react';
|
||||||
import type {
|
import type {
|
||||||
AgGridReactProps,
|
AgGridReactProps,
|
||||||
@ -7,18 +6,17 @@ import type {
|
|||||||
AgGridReact as AgGridReactType,
|
AgGridReact as AgGridReactType,
|
||||||
} from 'ag-grid-react';
|
} from 'ag-grid-react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import 'ag-grid-community/dist/styles/ag-grid.css';
|
import 'ag-grid-community/styles/ag-grid.css';
|
||||||
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
|
import 'ag-grid-community/styles/ag-theme-alpine.css';
|
||||||
|
|
||||||
import './grid.scss';
|
import './grid.scss';
|
||||||
|
|
||||||
type Props = (AgGridReactProps | AgReactUiProps) & {
|
type Props = (AgGridReactProps | AgReactUiProps) & {
|
||||||
isRowClickable?: boolean;
|
isRowClickable?: boolean;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
children: ReactNode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Grid = ({ isRowClickable, children, ...props }: Props) => {
|
export const Grid = ({ isRowClickable, ...props }: Props) => {
|
||||||
const gridRef = useRef<AgGridReactType | null>(null);
|
const gridRef = useRef<AgGridReactType | null>(null);
|
||||||
|
|
||||||
const resizeGrid = useCallback(() => {
|
const resizeGrid = useCallback(() => {
|
||||||
@ -44,8 +42,6 @@ export const Grid = ({ isRowClickable, children, ...props }: Props) => {
|
|||||||
onGridReady={handleOnGridReady}
|
onGridReady={handleOnGridReady}
|
||||||
suppressRowClickSelection
|
suppressRowClickSelection
|
||||||
{...props}
|
{...props}
|
||||||
>
|
/>
|
||||||
{children}
|
|
||||||
</AgGridReact>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -90,7 +90,7 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
|
|||||||
cy.getByTestId('All').click();
|
cy.getByTestId('All').click();
|
||||||
|
|
||||||
cy.get(`[row-id="${partiallyFilledId}"]`)
|
cy.get(`[row-id="${partiallyFilledId}"]`)
|
||||||
.eq(1)
|
.eq(0)
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.get(`[col-id='${orderStatus}']`).should(
|
cy.get(`[col-id='${orderStatus}']`).should(
|
||||||
'have.text',
|
'have.text',
|
||||||
|
@ -108,7 +108,7 @@ describe('positions', { tags: '@regression', testIsolation: true }, () => {
|
|||||||
cy.get(
|
cy.get(
|
||||||
'[row-id="02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65-market-2"]'
|
'[row-id="02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65-market-2"]'
|
||||||
)
|
)
|
||||||
.eq(1)
|
.eq(0)
|
||||||
.within(() => {
|
.within(() => {
|
||||||
emptyCells.forEach((cell) => {
|
emptyCells.forEach((cell) => {
|
||||||
cy.get(`[col-id="${cell}"]`).should('contain.text', '-');
|
cy.get(`[col-id="${cell}"]`).should('contain.text', '-');
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
@import 'ag-grid-community/dist/styles/ag-grid.css';
|
@import 'ag-grid-community/styles/ag-grid.css';
|
||||||
@import 'ag-grid-community/dist/styles/ag-theme-balham.css';
|
@import 'ag-grid-community/styles/ag-theme-balham.css';
|
||||||
@import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
|
|
||||||
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
|
@ -44,47 +44,44 @@ describe('AccountsTable', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should apply correct formatting', async () => {
|
it('should apply correct formatting', async () => {
|
||||||
await act(async () => {
|
const { container } = render(
|
||||||
render(
|
|
||||||
<AccountTable
|
<AccountTable
|
||||||
rowData={singleRowData}
|
rowData={singleRowData}
|
||||||
onClickAsset={() => null}
|
onClickAsset={() => null}
|
||||||
isReadOnly={false}
|
isReadOnly={false}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
|
||||||
const cells = await screen.findAllByRole('gridcell');
|
const cells = await screen.findAllByRole('gridcell');
|
||||||
const expectedValues = ['tBTC', '1,256.00', '1,256.00', '2,512.00', ''];
|
const expectedValues = ['tBTC', '1,256.00', '1,256.00', '2,512.00', ''];
|
||||||
cells.forEach((cell, i) => {
|
cells.forEach((cell, i) => {
|
||||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||||
});
|
});
|
||||||
const rows = await screen.findAllByRole('row');
|
const rows = container.querySelector('.ag-center-cols-container');
|
||||||
expect(rows.length).toBe(6);
|
expect(rows?.childElementCount).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should apply correct formatting in view as user mode', async () => {
|
it('should apply correct formatting in view as user mode', async () => {
|
||||||
await act(async () => {
|
const { container } = render(
|
||||||
render(
|
|
||||||
<AccountTable
|
<AccountTable
|
||||||
rowData={singleRowData}
|
rowData={singleRowData}
|
||||||
onClickAsset={() => null}
|
onClickAsset={() => null}
|
||||||
isReadOnly={true}
|
isReadOnly={true}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
|
||||||
const cells = await screen.findAllByRole('gridcell');
|
const cells = await screen.findAllByRole('gridcell');
|
||||||
const expectedValues = ['tBTC', '1,256.00', '1,256.00', '2,512.00', ''];
|
const expectedValues = ['tBTC', '1,256.00', '1,256.00', '2,512.00', ''];
|
||||||
expect(cells.length).toBe(expectedValues.length);
|
expect(cells.length).toBe(expectedValues.length);
|
||||||
cells.forEach((cell, i) => {
|
cells.forEach((cell, i) => {
|
||||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||||
});
|
});
|
||||||
const rows = await screen.findAllByRole('row');
|
const rows = container.querySelector('.ag-center-cols-container');
|
||||||
expect(rows.length).toBe(6);
|
expect(rows?.childElementCount).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not add first asset as pinned', async () => {
|
it('should add asset as pinned', async () => {
|
||||||
await act(async () => {
|
const { container, rerender } = render(
|
||||||
render(
|
|
||||||
<AccountTable
|
<AccountTable
|
||||||
rowData={singleRowData}
|
rowData={singleRowData}
|
||||||
onClickAsset={() => null}
|
onClickAsset={() => null}
|
||||||
@ -97,9 +94,29 @@ describe('AccountsTable', () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
await screen.findAllByRole('rowgroup');
|
||||||
const rows = await screen.findAllByRole('row');
|
let rows = container.querySelector('.ag-center-cols-container');
|
||||||
expect(rows.length).toBe(6);
|
expect(rows?.childElementCount).toBe(0);
|
||||||
|
let pinnedRows = container.querySelector('.ag-floating-top-container');
|
||||||
|
expect(pinnedRows?.childElementCount ?? 0).toBe(1);
|
||||||
|
|
||||||
|
rerender(
|
||||||
|
<AccountTable
|
||||||
|
rowData={singleRowData}
|
||||||
|
onClickAsset={() => null}
|
||||||
|
isReadOnly={false}
|
||||||
|
pinnedAsset={{
|
||||||
|
decimals: 5,
|
||||||
|
id: '',
|
||||||
|
symbol: 'tBTC',
|
||||||
|
name: 'tBTC',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
rows = container.querySelector('.ag-center-cols-container');
|
||||||
|
expect(rows?.childElementCount ?? 0).toBe(1);
|
||||||
|
pinnedRows = container.querySelector('.ag-floating-top-container');
|
||||||
|
expect(pinnedRows?.childElementCount ?? 0).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get correct account data', () => {
|
it('should get correct account data', () => {
|
||||||
|
@ -17,7 +17,7 @@ import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
|
|||||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||||
import type {
|
import type {
|
||||||
IGetRowsParams,
|
IGetRowsParams,
|
||||||
RowNode,
|
IRowNode,
|
||||||
RowHeightParams,
|
RowHeightParams,
|
||||||
ColDef,
|
ColDef,
|
||||||
} from 'ag-grid-community';
|
} from 'ag-grid-community';
|
||||||
@ -45,8 +45,8 @@ export const percentageValue = (part: string, total: string) => {
|
|||||||
export const accountValuesComparator = (
|
export const accountValuesComparator = (
|
||||||
valueA: string,
|
valueA: string,
|
||||||
valueB: string,
|
valueB: string,
|
||||||
nodeA: RowNode,
|
nodeA: IRowNode,
|
||||||
nodeB: RowNode
|
nodeB: IRowNode
|
||||||
) => {
|
) => {
|
||||||
if (isNumeric(valueA) && isNumeric(valueB)) {
|
if (isNumeric(valueA) && isNumeric(valueB)) {
|
||||||
const a = toBigNum(valueA, nodeA.data.asset?.decimals);
|
const a = toBigNum(valueA, nodeA.data.asset?.decimals);
|
||||||
@ -83,20 +83,22 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
onClickDeposit,
|
onClickDeposit,
|
||||||
onClickBreakdown,
|
onClickBreakdown,
|
||||||
rowData,
|
rowData,
|
||||||
|
isReadOnly,
|
||||||
|
pinnedAsset,
|
||||||
...props
|
...props
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const pinnedAsset = useMemo(() => {
|
const pinnedRow = useMemo(() => {
|
||||||
if (!props.pinnedAsset) {
|
if (!pinnedAsset) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const currentPinnedAssetRow = rowData?.find(
|
const currentPinnedAssetRow = rowData?.find(
|
||||||
(row) => row.asset.id === props.pinnedAsset?.id
|
(row) => row.asset.id === pinnedAsset?.id
|
||||||
);
|
);
|
||||||
if (!currentPinnedAssetRow) {
|
if (!currentPinnedAssetRow) {
|
||||||
return {
|
return {
|
||||||
asset: props.pinnedAsset,
|
asset: pinnedAsset,
|
||||||
available: '0',
|
available: '0',
|
||||||
used: '0',
|
used: '0',
|
||||||
total: '0',
|
total: '0',
|
||||||
@ -104,7 +106,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
return currentPinnedAssetRow;
|
return currentPinnedAssetRow;
|
||||||
}, [props.pinnedAsset, rowData]);
|
}, [pinnedAsset, rowData]);
|
||||||
|
|
||||||
const { getRowHeight } = props;
|
const { getRowHeight } = props;
|
||||||
|
|
||||||
@ -112,17 +114,17 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
(params: RowHeightParams) => {
|
(params: RowHeightParams) => {
|
||||||
if (
|
if (
|
||||||
params.node.rowPinned &&
|
params.node.rowPinned &&
|
||||||
params.data.asset.id === props.pinnedAsset?.id &&
|
params.data.asset.id === pinnedAsset?.id &&
|
||||||
new BigNumber(params.data.total).isLessThanOrEqualTo(0)
|
new BigNumber(params.data.total).isLessThanOrEqualTo(0)
|
||||||
) {
|
) {
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
return getRowHeight ? getRowHeight(params) : undefined;
|
return getRowHeight ? getRowHeight(params) : undefined;
|
||||||
},
|
},
|
||||||
[props.pinnedAsset?.id, getRowHeight]
|
[pinnedAsset?.id, getRowHeight]
|
||||||
);
|
);
|
||||||
|
|
||||||
const showDepositButton = pinnedAsset?.balance === '0';
|
const showDepositButton = pinnedRow?.balance === '0';
|
||||||
|
|
||||||
const colDefs = useMemo(() => {
|
const colDefs = useMemo(() => {
|
||||||
const defs: ColDef[] = [
|
const defs: ColDef[] = [
|
||||||
@ -266,7 +268,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
</CenteredGridCellWrapper>
|
</CenteredGridCellWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return props.isReadOnly ? null : (
|
return isReadOnly ? null : (
|
||||||
<AccountsActionsDropdown
|
<AccountsActionsDropdown
|
||||||
assetId={assetId}
|
assetId={assetId}
|
||||||
assetContractAddress={
|
assetContractAddress={
|
||||||
@ -294,13 +296,11 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
onClickBreakdown,
|
onClickBreakdown,
|
||||||
onClickDeposit,
|
onClickDeposit,
|
||||||
onClickWithdraw,
|
onClickWithdraw,
|
||||||
props.isReadOnly,
|
isReadOnly,
|
||||||
showDepositButton,
|
showDepositButton,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const data = rowData?.filter(
|
const data = rowData?.filter((data) => data.asset.id !== pinnedAsset?.id);
|
||||||
(data) => data.asset.id !== props.pinnedAsset?.id
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
@ -318,7 +318,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
}}
|
}}
|
||||||
columnDefs={colDefs}
|
columnDefs={colDefs}
|
||||||
getRowHeight={getPinnedAssetRowHeight}
|
getRowHeight={getPinnedAssetRowHeight}
|
||||||
pinnedTopRowData={pinnedAsset ? [pinnedAsset] : undefined}
|
pinnedTopRowData={pinnedRow ? [pinnedRow] : undefined}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ export * from './lib/cells/numeric-cell';
|
|||||||
export * from './lib/cells/price-cell';
|
export * from './lib/cells/price-cell';
|
||||||
export * from './lib/cells/price-change-cell';
|
export * from './lib/cells/price-change-cell';
|
||||||
export * from './lib/cells/price-flash-cell';
|
export * from './lib/cells/price-flash-cell';
|
||||||
export * from './lib/cells/vol-cell';
|
|
||||||
export * from './lib/cells/centered-grid-cell';
|
export * from './lib/cells/centered-grid-cell';
|
||||||
export * from './lib/cells/market-name-cell';
|
export * from './lib/cells/market-name-cell';
|
||||||
export * from './lib/cells/order-type-cell';
|
export * from './lib/cells/order-type-cell';
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { BID_COLOR, ASK_COLOR } from './vol-cell';
|
|
||||||
import { addDecimalsFixedFormatNumber } from '@vegaprotocol/utils';
|
import { addDecimalsFixedFormatNumber } from '@vegaprotocol/utils';
|
||||||
import { NumericCell } from './numeric-cell';
|
import { NumericCell } from './numeric-cell';
|
||||||
|
import { theme } from '@vegaprotocol/tailwindcss-config';
|
||||||
|
|
||||||
|
const BID_COLOR = theme.colors.vega.green.DEFAULT;
|
||||||
|
const ASK_COLOR = theme.colors.vega.pink.DEFAULT;
|
||||||
export interface CumulativeVolProps {
|
export interface CumulativeVolProps {
|
||||||
ask?: number;
|
ask?: number;
|
||||||
bid?: number;
|
bid?: number;
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import { VolCell } from './vol-cell';
|
|
||||||
import * as tailwind from '@vegaprotocol/tailwindcss-config';
|
|
||||||
|
|
||||||
describe('VolCell', () => {
|
|
||||||
const significantPart = '12,345';
|
|
||||||
const decimalPart = '67';
|
|
||||||
const props = {
|
|
||||||
value: 1234567,
|
|
||||||
valueFormatted: `${significantPart}.${decimalPart}`,
|
|
||||||
type: 'ask' as const,
|
|
||||||
testId: 'cell',
|
|
||||||
};
|
|
||||||
|
|
||||||
it('Displays formatted value', () => {
|
|
||||||
render(<VolCell {...props} />);
|
|
||||||
expect(screen.getByTestId(props.testId)).toHaveTextContent(
|
|
||||||
props.valueFormatted
|
|
||||||
);
|
|
||||||
expect(screen.getByText(decimalPart)).toBeInTheDocument();
|
|
||||||
expect(screen.getByText(decimalPart)).toHaveClass('opacity-60');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Displays 0', () => {
|
|
||||||
render(<VolCell {...props} value={0} valueFormatted="0.00" />);
|
|
||||||
expect(screen.getByTestId(props.testId)).toHaveTextContent('0.00');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Displays - if value is not a number', () => {
|
|
||||||
render(<VolCell {...props} value={null} valueFormatted="" />);
|
|
||||||
expect(screen.getByTestId(props.testId)).toHaveTextContent('-');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders bid volume bar', () => {
|
|
||||||
render(<VolCell {...props} type="bid" />);
|
|
||||||
expect(screen.getByTestId('vol-bar')).toHaveClass('left-0'); // renders bid bars from the left
|
|
||||||
expect(screen.getByTestId('vol-bar')).toHaveStyle({
|
|
||||||
backgroundColor: tailwind.theme.colors.vega.green.DEFAULT,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders ask volume bar', () => {
|
|
||||||
render(<VolCell {...props} type="ask" />);
|
|
||||||
expect(screen.getByTestId('vol-bar')).toHaveClass('right-0'); // renders ask bars from the right
|
|
||||||
expect(screen.getByTestId('vol-bar')).toHaveStyle({
|
|
||||||
backgroundColor: tailwind.theme.colors.vega.pink.DEFAULT,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,50 +0,0 @@
|
|||||||
import { memo } from 'react';
|
|
||||||
import type { ICellRendererParams } from 'ag-grid-community';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { theme } from '@vegaprotocol/tailwindcss-config';
|
|
||||||
import { NumericCell } from './numeric-cell';
|
|
||||||
|
|
||||||
export interface VolCellProps {
|
|
||||||
value: number | bigint | null | undefined;
|
|
||||||
valueFormatted: string;
|
|
||||||
relativeValue?: number;
|
|
||||||
type: 'ask' | 'bid';
|
|
||||||
testId?: string;
|
|
||||||
}
|
|
||||||
export interface IVolCellProps extends ICellRendererParams {
|
|
||||||
value: number | bigint | null | undefined;
|
|
||||||
valueFormatted: Omit<VolCellProps, 'value'>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const BID_COLOR = theme.colors.vega.green.DEFAULT;
|
|
||||||
export const ASK_COLOR = theme.colors.vega.pink.DEFAULT;
|
|
||||||
|
|
||||||
export const VolCell = memo(
|
|
||||||
({ value, valueFormatted, relativeValue, type, testId }: VolCellProps) => {
|
|
||||||
if ((!value && value !== 0) || isNaN(Number(value))) {
|
|
||||||
return <div data-testid={testId || 'vol'}>-</div>;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className="relative" data-testid={testId || 'vol'}>
|
|
||||||
<div
|
|
||||||
data-testid="vol-bar"
|
|
||||||
className={classNames(
|
|
||||||
'h-full absolute top-0 opacity-40 dark:opacity-100',
|
|
||||||
{
|
|
||||||
'left-0': type === 'bid',
|
|
||||||
'right-0': type === 'ask',
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
style={{
|
|
||||||
width: relativeValue ? `${relativeValue}%` : '0%',
|
|
||||||
backgroundColor: type === 'bid' ? BID_COLOR : ASK_COLOR,
|
|
||||||
opacity: 0.6,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<NumericCell value={value} valueFormatted={valueFormatted} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
VolCell.displayName = 'VolCell';
|
|
@ -7,6 +7,6 @@ export const COL_DEFS = {
|
|||||||
minWidth: 45,
|
minWidth: 45,
|
||||||
maxWidth: 45,
|
maxWidth: 45,
|
||||||
type: 'rightAligned',
|
type: 'rightAligned',
|
||||||
pinned: 'right',
|
pinned: 'right' as const,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -4,18 +4,17 @@ import type {
|
|||||||
ValueFormatterParams,
|
ValueFormatterParams,
|
||||||
ValueGetterParams,
|
ValueGetterParams,
|
||||||
} from 'ag-grid-community';
|
} from 'ag-grid-community';
|
||||||
import type { IDatasource, IGetRowsParams, RowNode } from 'ag-grid-community';
|
import type { IDatasource, IGetRowsParams } from 'ag-grid-community';
|
||||||
import type { AgGridReactProps } from 'ag-grid-react';
|
import type { AgGridReactProps } from 'ag-grid-react';
|
||||||
|
|
||||||
type Field = string | readonly string[];
|
type Field = string | readonly string[];
|
||||||
|
|
||||||
type RowHelper<TObj, TRow, TField extends Field> = Omit<
|
type RowHelper<TObj, TRow, TField extends Field> = Omit<
|
||||||
TObj,
|
TObj,
|
||||||
'data' | 'value' | 'node'
|
'data' | 'value'
|
||||||
> & {
|
> & {
|
||||||
data?: TRow;
|
data?: TRow;
|
||||||
value?: Get<TRow, TField>;
|
value?: Get<TRow, TField>;
|
||||||
node: (Omit<RowNode, 'data'> & { data?: TRow }) | null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type VegaValueFormatterParams<TRow, TField extends Field> = RowHelper<
|
export type VegaValueFormatterParams<TRow, TField extends Field> = RowHelper<
|
||||||
@ -24,12 +23,8 @@ export type VegaValueFormatterParams<TRow, TField extends Field> = RowHelper<
|
|||||||
TField
|
TField
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type VegaValueGetterParams<TRow> = Omit<
|
export type VegaValueGetterParams<TRow> = Omit<ValueGetterParams, 'data'> & {
|
||||||
ValueGetterParams,
|
|
||||||
'data' | 'node'
|
|
||||||
> & {
|
|
||||||
data?: TRow;
|
data?: TRow;
|
||||||
node: (Omit<RowNode, 'data'> & { data?: TRow }) | null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type VegaICellRendererParams<TRow, TField extends Field = string> = Omit<
|
export type VegaICellRendererParams<TRow, TField extends Field = string> = Omit<
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { forwardRef } from 'react';
|
import { forwardRef, useMemo } from 'react';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
|
||||||
import {
|
import {
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
getDateTimeFormat,
|
getDateTimeFormat,
|
||||||
truncateByChars,
|
truncateByChars,
|
||||||
isNumeric,
|
isNumeric,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
|
import type { ColDef } from 'ag-grid-community';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||||
import type {
|
import type {
|
||||||
@ -21,51 +21,46 @@ export const DepositsTable = forwardRef<
|
|||||||
AgGridReact,
|
AgGridReact,
|
||||||
TypedDataAgGrid<DepositFieldsFragment>
|
TypedDataAgGrid<DepositFieldsFragment>
|
||||||
>((props, ref) => {
|
>((props, ref) => {
|
||||||
return (
|
const columnDefs = useMemo<ColDef[]>(
|
||||||
<AgGrid
|
() => [
|
||||||
ref={ref}
|
{ headerName: 'Asset', field: 'asset.symbol' },
|
||||||
defaultColDef={{ flex: 1 }}
|
{
|
||||||
style={{ width: '100%', height: '100%' }}
|
headerName: 'Amount',
|
||||||
{...props}
|
field: 'amount',
|
||||||
>
|
valueFormatter: ({
|
||||||
<AgGridColumn headerName="Asset" field="asset.symbol" />
|
|
||||||
<AgGridColumn
|
|
||||||
headerName="Amount"
|
|
||||||
field="amount"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
value,
|
||||||
data,
|
data,
|
||||||
}: VegaValueFormatterParams<DepositFieldsFragment, 'amount'>) => {
|
}: VegaValueFormatterParams<DepositFieldsFragment, 'amount'>) => {
|
||||||
return isNumeric(value) && data
|
return isNumeric(value) && data
|
||||||
? addDecimalsFormatNumber(value, data.asset.decimals)
|
? addDecimalsFormatNumber(value, data.asset.decimals)
|
||||||
: null;
|
: '';
|
||||||
}}
|
},
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
headerName="Created at"
|
headerName: 'Created at',
|
||||||
field="createdTimestamp"
|
field: 'createdTimestamp',
|
||||||
valueFormatter={({
|
valueFormatter: ({
|
||||||
value,
|
value,
|
||||||
}: VegaValueFormatterParams<
|
}: VegaValueFormatterParams<
|
||||||
DepositFieldsFragment,
|
DepositFieldsFragment,
|
||||||
'createdTimestamp'
|
'createdTimestamp'
|
||||||
>) => {
|
>) => {
|
||||||
return value ? getDateTimeFormat().format(new Date(value)) : '';
|
return value ? getDateTimeFormat().format(new Date(value)) : '';
|
||||||
}}
|
},
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
headerName="Status"
|
headerName: 'Status',
|
||||||
field="status"
|
field: 'status',
|
||||||
valueFormatter={({
|
valueFormatter: ({
|
||||||
value,
|
value,
|
||||||
}: VegaValueFormatterParams<DepositFieldsFragment, 'status'>) => {
|
}: VegaValueFormatterParams<DepositFieldsFragment, 'status'>) => {
|
||||||
return value ? DepositStatusMapping[value] : '';
|
return value ? DepositStatusMapping[value] : '';
|
||||||
}}
|
},
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
headerName="Tx hash"
|
headerName: 'Tx hash',
|
||||||
field="txHash"
|
field: 'txHash',
|
||||||
cellRenderer={({
|
cellRenderer: ({
|
||||||
value,
|
value,
|
||||||
data,
|
data,
|
||||||
}: VegaICellRendererParams<DepositFieldsFragment, 'txHash'>) => {
|
}: VegaICellRendererParams<DepositFieldsFragment, 'txHash'>) => {
|
||||||
@ -76,9 +71,19 @@ export const DepositsTable = forwardRef<
|
|||||||
{truncateByChars(value)}
|
{truncateByChars(value)}
|
||||||
</EtherscanLink>
|
</EtherscanLink>
|
||||||
);
|
);
|
||||||
}}
|
},
|
||||||
flex={1}
|
flex: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<AgGrid
|
||||||
|
ref={ref}
|
||||||
|
defaultColDef={{ flex: 1 }}
|
||||||
|
columnDefs={columnDefs}
|
||||||
|
style={{ width: '100%', height: '100%' }}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
</AgGrid>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
import type {
|
import type {
|
||||||
AgGridReact,
|
AgGridReact,
|
||||||
AgGridReactProps,
|
AgGridReactProps,
|
||||||
AgReactUiProps,
|
AgReactUiProps,
|
||||||
} from 'ag-grid-react';
|
} from 'ag-grid-react';
|
||||||
import type { ITooltipParams } from 'ag-grid-community';
|
import type { ITooltipParams, ColDef } from 'ag-grid-community';
|
||||||
import {
|
import {
|
||||||
addDecimal,
|
addDecimal,
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
@ -13,7 +14,6 @@ import {
|
|||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
|
||||||
import {
|
import {
|
||||||
AgGridLazy as AgGrid,
|
AgGridLazy as AgGrid,
|
||||||
positiveClassNames,
|
positiveClassNames,
|
||||||
@ -43,29 +43,19 @@ export type Props = (AgGridReactProps | AgReactUiProps) & {
|
|||||||
|
|
||||||
export const FillsTable = forwardRef<AgGridReact, Props>(
|
export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||||
({ partyId, onMarketClick, ...props }, ref) => {
|
({ partyId, onMarketClick, ...props }, ref) => {
|
||||||
return (
|
const columnDefs = useMemo<ColDef[]>(
|
||||||
<AgGrid
|
() => [
|
||||||
ref={ref}
|
{
|
||||||
overlayNoRowsTemplate={t('No fills')}
|
headerName: t('Market'),
|
||||||
defaultColDef={{ resizable: true }}
|
field: 'market.tradableInstrument.instrument.name',
|
||||||
style={{ width: '100%', height: '100%' }}
|
cellRenderer: 'MarketNameCell',
|
||||||
getRowId={({ data }) => data?.id}
|
cellRendererParams: { idPath: 'market.id', onMarketClick },
|
||||||
tooltipShowDelay={0}
|
},
|
||||||
tooltipHideDelay={2000}
|
{
|
||||||
components={{ MarketNameCell }}
|
headerName: t('Size'),
|
||||||
{...props}
|
type: 'rightAligned',
|
||||||
>
|
field: 'size',
|
||||||
<AgGridColumn
|
cellClassRules: {
|
||||||
headerName={t('Market')}
|
|
||||||
field="market.tradableInstrument.instrument.name"
|
|
||||||
cellRenderer="MarketNameCell"
|
|
||||||
cellRendererParams={{ idPath: 'market.id', onMarketClick }}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Size')}
|
|
||||||
type="rightAligned"
|
|
||||||
field="size"
|
|
||||||
cellClassRules={{
|
|
||||||
[positiveClassNames]: ({ data }: { data: Trade }) => {
|
[positiveClassNames]: ({ data }: { data: Trade }) => {
|
||||||
const partySide = getPartySide(data, partyId);
|
const partySide = getPartySide(data, partyId);
|
||||||
return partySide === 'buyer';
|
return partySide === 'buyer';
|
||||||
@ -74,48 +64,47 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
|||||||
const partySide = getPartySide(data, partyId);
|
const partySide = getPartySide(data, partyId);
|
||||||
return partySide === 'seller';
|
return partySide === 'seller';
|
||||||
},
|
},
|
||||||
}}
|
},
|
||||||
valueFormatter={formatSize(partyId)}
|
valueFormatter: formatSize(partyId),
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
headerName={t('Price')}
|
headerName: t('Price'),
|
||||||
field="price"
|
field: 'price',
|
||||||
valueFormatter={formatPrice}
|
valueFormatter: formatPrice,
|
||||||
type="rightAligned"
|
type: 'rightAligned',
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
headerName={t('Notional')}
|
headerName: t('Notional'),
|
||||||
field="price"
|
field: 'price',
|
||||||
valueFormatter={formatTotal}
|
valueFormatter: formatTotal,
|
||||||
type="rightAligned"
|
type: 'rightAligned',
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
headerName={t('Role')}
|
headerName: t('Role'),
|
||||||
field="aggressor"
|
field: 'aggressor',
|
||||||
valueFormatter={formatRole(partyId)}
|
valueFormatter: formatRole(partyId),
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
headerName={t('Fee')}
|
headerName: t('Fee'),
|
||||||
field="market.tradableInstrument.instrument.product"
|
field: 'market.tradableInstrument.instrument.product',
|
||||||
valueFormatter={formatFee(partyId)}
|
valueFormatter: formatFee(partyId),
|
||||||
type="rightAligned"
|
type: 'rightAligned',
|
||||||
tooltipField="market.tradableInstrument.instrument.product"
|
tooltipField: 'market.tradableInstrument.instrument.product',
|
||||||
tooltipComponent={FeesBreakdownTooltip}
|
tooltipComponent: FeesBreakdownTooltip,
|
||||||
tooltipComponentParams={{ partyId }}
|
tooltipComponentParams: { partyId },
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
headerName={t('Date')}
|
headerName: t('Date'),
|
||||||
field="createdAt"
|
field: 'createdAt',
|
||||||
valueFormatter={({
|
valueFormatter: ({
|
||||||
value,
|
value,
|
||||||
}: VegaValueFormatterParams<Trade, 'createdAt'>) => {
|
}: VegaValueFormatterParams<Trade, 'createdAt'>) => {
|
||||||
return value ? getDateTimeFormat().format(new Date(value)) : '';
|
return value ? getDateTimeFormat().format(new Date(value)) : '';
|
||||||
}}
|
},
|
||||||
/>
|
},
|
||||||
<AgGridColumn
|
{
|
||||||
colId="fill-actions"
|
colId: 'fill-actions',
|
||||||
{...COL_DEFS.actions}
|
cellRenderer: ({ data }: VegaICellRendererParams<Trade, 'id'>) => {
|
||||||
cellRenderer={({ data }: VegaICellRendererParams<Trade, 'id'>) => {
|
|
||||||
if (!data) return null;
|
if (!data) return null;
|
||||||
return (
|
return (
|
||||||
<FillActionsDropdown
|
<FillActionsDropdown
|
||||||
@ -124,9 +113,25 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
|||||||
tradeId={data.id}
|
tradeId={data.id}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}}
|
},
|
||||||
|
...COL_DEFS.actions,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[onMarketClick, partyId]
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<AgGrid
|
||||||
|
ref={ref}
|
||||||
|
columnDefs={columnDefs}
|
||||||
|
overlayNoRowsTemplate={t('No fills')}
|
||||||
|
defaultColDef={{ resizable: true }}
|
||||||
|
style={{ width: '100%', height: '100%' }}
|
||||||
|
getRowId={({ data }) => data?.id}
|
||||||
|
tooltipShowDelay={0}
|
||||||
|
tooltipHideDelay={2000}
|
||||||
|
components={{ MarketNameCell }}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
</AgGrid>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -15,15 +15,15 @@ import {
|
|||||||
SetFilter,
|
SetFilter,
|
||||||
} from '@vegaprotocol/datagrid';
|
} from '@vegaprotocol/datagrid';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
|
||||||
import type * as Types from '@vegaprotocol/types';
|
import type * as Types from '@vegaprotocol/types';
|
||||||
|
import type { ColDef } from 'ag-grid-community';
|
||||||
import {
|
import {
|
||||||
AccountTypeMapping,
|
AccountTypeMapping,
|
||||||
DescriptionTransferTypeMapping,
|
DescriptionTransferTypeMapping,
|
||||||
TransferTypeMapping,
|
TransferTypeMapping,
|
||||||
} from '@vegaprotocol/types';
|
} from '@vegaprotocol/types';
|
||||||
import type { LedgerEntry } from './ledger-entries-data-provider';
|
import type { LedgerEntry } from './ledger-entries-data-provider';
|
||||||
import { forwardRef } from 'react';
|
import { forwardRef, useMemo } from 'react';
|
||||||
import { formatRFC3339, subDays } from 'date-fns';
|
import { formatRFC3339, subDays } from 'date-fns';
|
||||||
|
|
||||||
export const TransferTooltipCellComponent = ({
|
export const TransferTooltipCellComponent = ({
|
||||||
@ -47,6 +47,143 @@ type LedgerEntryProps = TypedDataAgGrid<LedgerEntry>;
|
|||||||
|
|
||||||
export const LedgerTable = forwardRef<AgGridReact, LedgerEntryProps>(
|
export const LedgerTable = forwardRef<AgGridReact, LedgerEntryProps>(
|
||||||
(props, ref) => {
|
(props, ref) => {
|
||||||
|
const columnDefs = useMemo<ColDef[]>(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
headerName: t('Sender'),
|
||||||
|
field: 'fromAccountPartyId',
|
||||||
|
cellRenderer: ({
|
||||||
|
value,
|
||||||
|
}: VegaValueFormatterParams<LedgerEntry, 'fromAccountPartyId'>) =>
|
||||||
|
truncateByChars(value || ''),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Account type'),
|
||||||
|
filter: SetFilter,
|
||||||
|
filterParams: {
|
||||||
|
set: AccountTypeMapping,
|
||||||
|
},
|
||||||
|
field: 'fromAccountType',
|
||||||
|
cellRenderer: ({
|
||||||
|
value,
|
||||||
|
}: VegaValueFormatterParams<LedgerEntry, 'fromAccountType'>) =>
|
||||||
|
value ? AccountTypeMapping[value] : '-',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Market'),
|
||||||
|
field: 'marketSender.tradableInstrument.instrument.code',
|
||||||
|
cellRenderer: ({
|
||||||
|
value,
|
||||||
|
}: VegaValueFormatterParams<
|
||||||
|
LedgerEntry,
|
||||||
|
'marketSender.tradableInstrument.instrument.code'
|
||||||
|
>) => value || '-',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Receiver'),
|
||||||
|
field: 'toAccountPartyId',
|
||||||
|
cellRenderer: ({
|
||||||
|
value,
|
||||||
|
}: VegaValueFormatterParams<LedgerEntry, 'toAccountPartyId'>) =>
|
||||||
|
truncateByChars(value || ''),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Account type'),
|
||||||
|
filter: SetFilter,
|
||||||
|
filterParams: {
|
||||||
|
set: AccountTypeMapping,
|
||||||
|
},
|
||||||
|
field: 'toAccountType',
|
||||||
|
cellRenderer: ({
|
||||||
|
value,
|
||||||
|
}: VegaValueFormatterParams<LedgerEntry, 'toAccountType'>) =>
|
||||||
|
value ? AccountTypeMapping[value] : '-',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Market'),
|
||||||
|
field: 'marketReceiver.tradableInstrument.instrument.code',
|
||||||
|
cellRenderer: ({
|
||||||
|
value,
|
||||||
|
}: VegaValueFormatterParams<
|
||||||
|
LedgerEntry,
|
||||||
|
'marketReceiver.tradableInstrument.instrument.code'
|
||||||
|
>) => value || '-',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Transfer type'),
|
||||||
|
field: 'transferType',
|
||||||
|
tooltipField: 'transferType',
|
||||||
|
filter: SetFilter,
|
||||||
|
filterParams: {
|
||||||
|
set: TransferTypeMapping,
|
||||||
|
},
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
}: VegaValueFormatterParams<LedgerEntry, 'transferType'>) =>
|
||||||
|
value ? TransferTypeMapping[value] : '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Quantity'),
|
||||||
|
field: 'quantity',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<LedgerEntry, 'quantity'>) => {
|
||||||
|
const assetDecimalPlaces = data?.asset?.decimals || 0;
|
||||||
|
return value
|
||||||
|
? addDecimalsFormatNumber(value, assetDecimalPlaces)
|
||||||
|
: '';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Asset'),
|
||||||
|
field: 'assetId',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<LedgerEntry, 'asset'>) =>
|
||||||
|
data?.asset?.symbol || '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Sender account balance'),
|
||||||
|
field: 'fromAccountBalance',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<LedgerEntry, 'fromAccountBalance'>) => {
|
||||||
|
const assetDecimalPlaces = data?.asset?.decimals || 0;
|
||||||
|
return value
|
||||||
|
? addDecimalsFormatNumber(value, assetDecimalPlaces)
|
||||||
|
: '';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Receiver account balance'),
|
||||||
|
field: 'toAccountBalance',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<LedgerEntry, 'toAccountBalance'>) => {
|
||||||
|
const assetDecimalPlaces = data?.asset?.decimals || 0;
|
||||||
|
return value
|
||||||
|
? addDecimalsFormatNumber(value, assetDecimalPlaces)
|
||||||
|
: '';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Vega time'),
|
||||||
|
field: 'vegaTime',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
}: VegaValueFormatterParams<LedgerEntry, 'vegaTime'>) =>
|
||||||
|
value ? getDateTimeFormat().format(fromNanoSeconds(value)) : '-',
|
||||||
|
filterParams: dateRangeFilterParams,
|
||||||
|
filter: DateRangeFilter,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{ width: '100%', height: '100%' }}
|
||||||
@ -61,148 +198,9 @@ export const LedgerTable = forwardRef<AgGridReact, LedgerEntryProps>(
|
|||||||
buttons: ['reset'],
|
buttons: ['reset'],
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
columnDefs={columnDefs}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Sender')}
|
|
||||||
field="fromAccountPartyId"
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<LedgerEntry, 'fromAccountPartyId'>) =>
|
|
||||||
truncateByChars(value || '')
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Account type')}
|
|
||||||
filter={SetFilter}
|
|
||||||
filterParams={{
|
|
||||||
set: AccountTypeMapping,
|
|
||||||
}}
|
|
||||||
field="fromAccountType"
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<LedgerEntry, 'fromAccountType'>) =>
|
|
||||||
value ? AccountTypeMapping[value] : '-'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Market')}
|
|
||||||
field="marketSender.tradableInstrument.instrument.code"
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<
|
|
||||||
LedgerEntry,
|
|
||||||
'marketSender.tradableInstrument.instrument.code'
|
|
||||||
>) => value || '-'}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Receiver')}
|
|
||||||
field="toAccountPartyId"
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<LedgerEntry, 'toAccountPartyId'>) =>
|
|
||||||
truncateByChars(value || '')
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Account type')}
|
|
||||||
filter={SetFilter}
|
|
||||||
filterParams={{
|
|
||||||
set: AccountTypeMapping,
|
|
||||||
}}
|
|
||||||
field="toAccountType"
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<LedgerEntry, 'toAccountType'>) =>
|
|
||||||
value ? AccountTypeMapping[value] : '-'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Market')}
|
|
||||||
field="marketReceiver.tradableInstrument.instrument.code"
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<
|
|
||||||
LedgerEntry,
|
|
||||||
'marketReceiver.tradableInstrument.instrument.code'
|
|
||||||
>) => value || '-'}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Transfer type')}
|
|
||||||
field="transferType"
|
|
||||||
tooltipField="transferType"
|
|
||||||
filter={SetFilter}
|
|
||||||
filterParams={{
|
|
||||||
set: TransferTypeMapping,
|
|
||||||
}}
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<LedgerEntry, 'transferType'>) =>
|
|
||||||
value ? TransferTypeMapping[value] : ''
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Quantity')}
|
|
||||||
field="quantity"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<LedgerEntry, 'quantity'>) => {
|
|
||||||
const assetDecimalPlaces = data?.asset?.decimals || 0;
|
|
||||||
return value
|
|
||||||
? addDecimalsFormatNumber(value, assetDecimalPlaces)
|
|
||||||
: value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Asset')}
|
|
||||||
field="assetId"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<LedgerEntry, 'asset'>) =>
|
|
||||||
data?.asset?.symbol || value
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Sender account balance')}
|
|
||||||
field="fromAccountBalance"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<LedgerEntry, 'fromAccountBalance'>) => {
|
|
||||||
const assetDecimalPlaces = data?.asset?.decimals || 0;
|
|
||||||
return value
|
|
||||||
? addDecimalsFormatNumber(value, assetDecimalPlaces)
|
|
||||||
: value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Receiver account balance')}
|
|
||||||
field="toAccountBalance"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<LedgerEntry, 'toAccountBalance'>) => {
|
|
||||||
const assetDecimalPlaces = data?.asset?.decimals || 0;
|
|
||||||
return value
|
|
||||||
? addDecimalsFormatNumber(value, assetDecimalPlaces)
|
|
||||||
: value;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Vega time')}
|
|
||||||
field="vegaTime"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<LedgerEntry, 'vegaTime'>) =>
|
|
||||||
value ? getDateTimeFormat().format(fromNanoSeconds(value)) : '-'
|
|
||||||
}
|
|
||||||
filterParams={dateRangeFilterParams}
|
|
||||||
filter={DateRangeFilter}
|
|
||||||
flex={1}
|
|
||||||
/>
|
|
||||||
</AgGrid>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -188,7 +188,7 @@ export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
|
|||||||
<AgGrid
|
<AgGrid
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{ width: '100%', height: '100%' }}
|
||||||
overlayNoRowsTemplate={t('No liquidity provisions')}
|
overlayNoRowsTemplate={t('No liquidity provisions')}
|
||||||
getRowId={({ data }) => data.id}
|
getRowId={({ data }: { data: LiquidityProvisionData }) => data.id || ''}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
tooltipShowDelay={500}
|
tooltipShowDelay={500}
|
||||||
defaultColDef={{
|
defaultColDef={{
|
||||||
|
@ -67,6 +67,7 @@ export const liquidityProviderFeeShareQuery = (
|
|||||||
|
|
||||||
export const liquidityFields: LiquidityProvisionFieldsFragment[] = [
|
export const liquidityFields: LiquidityProvisionFieldsFragment[] = [
|
||||||
{
|
{
|
||||||
|
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
|
||||||
party: {
|
party: {
|
||||||
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
|
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
|
||||||
accountsConnection: {
|
accountsConnection: {
|
||||||
@ -92,6 +93,7 @@ export const liquidityFields: LiquidityProvisionFieldsFragment[] = [
|
|||||||
__typename: 'LiquidityProvision',
|
__typename: 'LiquidityProvision',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 'cc464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
|
||||||
party: {
|
party: {
|
||||||
id: 'cc464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
|
id: 'cc464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
|
||||||
accountsConnection: {
|
accountsConnection: {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
import { useMemo } from 'react';
|
||||||
|
import type { ColDef } from 'ag-grid-community';
|
||||||
import { forwardRef } from 'react';
|
import { forwardRef } from 'react';
|
||||||
import type {
|
import type {
|
||||||
VegaICellRendererParams,
|
VegaICellRendererParams,
|
||||||
@ -47,7 +48,79 @@ interface Props extends AgGridReactProps {
|
|||||||
onClick?: (price?: string) => void;
|
onClick?: (price?: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TradesTable = forwardRef<AgGridReact, Props>((props, ref) => {
|
export const TradesTable = forwardRef<AgGridReact, Props>(
|
||||||
|
({ onClick, ...props }, ref) => {
|
||||||
|
const columnDefs = useMemo<ColDef[]>(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
headerName: t('Price'),
|
||||||
|
field: 'price',
|
||||||
|
type: 'rightAligned',
|
||||||
|
width: 130,
|
||||||
|
cellClass: changeCellClass,
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<Trade, 'price'>) => {
|
||||||
|
if (!value || !data?.market) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return addDecimalsFormatNumber(value, data.market.decimalPlaces);
|
||||||
|
},
|
||||||
|
cellRenderer: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaICellRendererParams<Trade, 'price'>) => {
|
||||||
|
if (!data?.market || !value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
onClick &&
|
||||||
|
onClick(addDecimal(value, data.market?.decimalPlaces || 0))
|
||||||
|
}
|
||||||
|
className="hover:dark:bg-neutral-800 hover:bg-neutral-200"
|
||||||
|
>
|
||||||
|
{addDecimalsFormatNumber(value, data.market.decimalPlaces)}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Size'),
|
||||||
|
field: 'size',
|
||||||
|
width: 125,
|
||||||
|
type: 'rightAligned',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<Trade, 'size'>) => {
|
||||||
|
if (!value || !data?.market) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return addDecimalsFormatNumber(
|
||||||
|
value,
|
||||||
|
data.market.positionDecimalPlaces
|
||||||
|
);
|
||||||
|
},
|
||||||
|
cellRenderer: NumericCell,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Created at'),
|
||||||
|
field: 'createdAt',
|
||||||
|
type: 'rightAligned',
|
||||||
|
width: 170,
|
||||||
|
cellClass: 'text-right',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
}: VegaValueFormatterParams<Trade, 'createdAt'>) => {
|
||||||
|
return value && getDateTimeFormat().format(new Date(value));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[onClick]
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{ width: '100%', height: '100%' }}
|
||||||
@ -56,76 +129,9 @@ export const TradesTable = forwardRef<AgGridReact, Props>((props, ref) => {
|
|||||||
defaultColDef={{
|
defaultColDef={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
}}
|
}}
|
||||||
|
columnDefs={columnDefs}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Price')}
|
|
||||||
field="price"
|
|
||||||
type="rightAligned"
|
|
||||||
width={130}
|
|
||||||
cellClass={changeCellClass}
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<Trade, 'price'>) => {
|
|
||||||
if (!value || !data?.market) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return addDecimalsFormatNumber(value, data.market.decimalPlaces);
|
|
||||||
}}
|
|
||||||
cellRenderer={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaICellRendererParams<Trade, 'price'>) => {
|
|
||||||
if (!data?.market || !value) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
onClick={() =>
|
|
||||||
props.onClick &&
|
|
||||||
props.onClick(
|
|
||||||
addDecimal(value, data.market?.decimalPlaces || 0)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="hover:dark:bg-neutral-800 hover:bg-neutral-200"
|
|
||||||
>
|
|
||||||
{addDecimalsFormatNumber(value, data.market.decimalPlaces)}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
);
|
||||||
headerName={t('Size')}
|
|
||||||
field="size"
|
|
||||||
width={125}
|
|
||||||
type="rightAligned"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<Trade, 'size'>) => {
|
|
||||||
if (!value || !data?.market) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return addDecimalsFormatNumber(
|
);
|
||||||
value,
|
|
||||||
data.market.positionDecimalPlaces
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
cellRenderer={NumericCell}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Created at')}
|
|
||||||
field="createdAt"
|
|
||||||
type="rightAligned"
|
|
||||||
width={170}
|
|
||||||
cellClass="text-right"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
}: VegaValueFormatterParams<Trade, 'createdAt'>) => {
|
|
||||||
return value && getDateTimeFormat().format(new Date(value));
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</AgGrid>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState, useMemo } from 'react';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
import type { ColDef } from 'ag-grid-community';
|
||||||
import {
|
import {
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
convertToCountdownString,
|
convertToCountdownString,
|
||||||
@ -34,20 +34,111 @@ import * as Schema from '@vegaprotocol/types';
|
|||||||
import type { TimestampedWithdrawals } from './use-ready-to-complete-withdrawals-toast';
|
import type { TimestampedWithdrawals } from './use-ready-to-complete-withdrawals-toast';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export const WithdrawalsTable = (
|
export const WithdrawalsTable = ({
|
||||||
props: TypedDataAgGrid<WithdrawalFieldsFragment> & {
|
delayed,
|
||||||
|
ready,
|
||||||
|
...props
|
||||||
|
}: TypedDataAgGrid<WithdrawalFieldsFragment> & {
|
||||||
ready?: TimestampedWithdrawals;
|
ready?: TimestampedWithdrawals;
|
||||||
delayed?: TimestampedWithdrawals;
|
delayed?: TimestampedWithdrawals;
|
||||||
}
|
}) => {
|
||||||
) => {
|
|
||||||
const gridRef = useRef<AgGridReact | null>(null);
|
const gridRef = useRef<AgGridReact | null>(null);
|
||||||
const createWithdrawApproval = useEthWithdrawApprovalsStore(
|
const createWithdrawApproval = useEthWithdrawApprovalsStore(
|
||||||
(store) => store.create
|
(store) => store.create
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const columnDefs = useMemo<ColDef[]>(
|
||||||
|
() => [
|
||||||
|
{ headerName: 'Asset', field: 'asset.symbol' },
|
||||||
|
{
|
||||||
|
headerName: t('Amount'),
|
||||||
|
field: 'amount',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<WithdrawalFieldsFragment, 'amount'>) => {
|
||||||
|
return isNumeric(value) && data?.asset
|
||||||
|
? addDecimalsFormatNumber(value, data.asset.decimals)
|
||||||
|
: '';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Recipient'),
|
||||||
|
field: 'details.receiverAddress',
|
||||||
|
cellRenderer: 'RecipientCell',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<
|
||||||
|
WithdrawalFieldsFragment,
|
||||||
|
'details.receiverAddress'
|
||||||
|
>) => {
|
||||||
|
if (!data) return '';
|
||||||
|
if (!value) return '-';
|
||||||
|
return truncateByChars(value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Created'),
|
||||||
|
field: 'createdTimestamp',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<
|
||||||
|
WithdrawalFieldsFragment,
|
||||||
|
'createdTimestamp'
|
||||||
|
>) =>
|
||||||
|
data
|
||||||
|
? value
|
||||||
|
? getDateTimeFormat().format(new Date(value))
|
||||||
|
: '-'
|
||||||
|
: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Completed'),
|
||||||
|
field: 'withdrawnTimestamp',
|
||||||
|
valueFormatter: ({
|
||||||
|
value,
|
||||||
|
data,
|
||||||
|
}: VegaValueFormatterParams<
|
||||||
|
WithdrawalFieldsFragment,
|
||||||
|
'withdrawnTimestamp'
|
||||||
|
>) =>
|
||||||
|
data
|
||||||
|
? value
|
||||||
|
? getDateTimeFormat().format(new Date(value))
|
||||||
|
: '-'
|
||||||
|
: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Status'),
|
||||||
|
field: 'status',
|
||||||
|
cellRenderer: 'StatusCell',
|
||||||
|
cellRendererParams: { ready, delayed },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Transaction'),
|
||||||
|
field: 'txHash',
|
||||||
|
flex: 2,
|
||||||
|
type: 'rightAligned',
|
||||||
|
cellRendererParams: {
|
||||||
|
complete: (withdrawal: WithdrawalFieldsFragment) => {
|
||||||
|
createWithdrawApproval(withdrawal);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cellRendererSelector: ({
|
||||||
|
data,
|
||||||
|
}: VegaICellRendererParams<WithdrawalFieldsFragment>) => ({
|
||||||
|
component: data?.txHash ? 'EtherscanLinkCell' : 'CompleteCell',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[createWithdrawApproval, delayed, ready]
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
overlayNoRowsTemplate={t('No withdrawals')}
|
overlayNoRowsTemplate={t('No withdrawals')}
|
||||||
|
columnDefs={columnDefs}
|
||||||
defaultColDef={{ flex: 1 }}
|
defaultColDef={{ flex: 1 }}
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{ width: '100%', height: '100%' }}
|
||||||
components={{
|
components={{
|
||||||
@ -59,93 +150,7 @@ export const WithdrawalsTable = (
|
|||||||
suppressCellFocus
|
suppressCellFocus
|
||||||
ref={gridRef}
|
ref={gridRef}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
|
||||||
<AgGridColumn headerName="Asset" field="asset.symbol" />
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Amount')}
|
|
||||||
field="amount"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<WithdrawalFieldsFragment, 'amount'>) => {
|
|
||||||
return isNumeric(value) && data?.asset
|
|
||||||
? addDecimalsFormatNumber(value, data.asset.decimals)
|
|
||||||
: '';
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Recipient')}
|
|
||||||
field="details.receiverAddress"
|
|
||||||
cellRenderer="RecipientCell"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<
|
|
||||||
WithdrawalFieldsFragment,
|
|
||||||
'details.receiverAddress'
|
|
||||||
>) => {
|
|
||||||
if (!data) return null;
|
|
||||||
if (!value) return '-';
|
|
||||||
return truncateByChars(value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Created')}
|
|
||||||
field="createdTimestamp"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<
|
|
||||||
WithdrawalFieldsFragment,
|
|
||||||
'createdTimestamp'
|
|
||||||
>) =>
|
|
||||||
data
|
|
||||||
? value
|
|
||||||
? getDateTimeFormat().format(new Date(value))
|
|
||||||
: '-'
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Completed')}
|
|
||||||
field="withdrawnTimestamp"
|
|
||||||
valueFormatter={({
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
}: VegaValueFormatterParams<
|
|
||||||
WithdrawalFieldsFragment,
|
|
||||||
'withdrawnTimestamp'
|
|
||||||
>) =>
|
|
||||||
data
|
|
||||||
? value
|
|
||||||
? getDateTimeFormat().format(new Date(value))
|
|
||||||
: '-'
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Status')}
|
|
||||||
field="status"
|
|
||||||
cellRendererParams={{ ready: props.ready, delayed: props.delayed }}
|
|
||||||
cellRenderer="StatusCell"
|
|
||||||
/>
|
|
||||||
<AgGridColumn
|
|
||||||
headerName={t('Transaction')}
|
|
||||||
field="txHash"
|
|
||||||
flex={2}
|
|
||||||
type="rightAligned"
|
|
||||||
cellRendererParams={{
|
|
||||||
complete: (withdrawal: WithdrawalFieldsFragment) => {
|
|
||||||
createWithdrawApproval(withdrawal);
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
cellRendererSelector={({
|
|
||||||
data,
|
|
||||||
}: VegaICellRendererParams<WithdrawalFieldsFragment>) => ({
|
|
||||||
component: data?.txHash ? 'EtherscanLinkCell' : 'CompleteCell',
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</AgGrid>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,8 +46,8 @@
|
|||||||
"@web3-react/metamask": "^8.1.2-beta.0",
|
"@web3-react/metamask": "^8.1.2-beta.0",
|
||||||
"@web3-react/walletconnect": "8.1.3-beta.0",
|
"@web3-react/walletconnect": "8.1.3-beta.0",
|
||||||
"@web3-react/walletconnect-v2": "^8.1.3-beta.0",
|
"@web3-react/walletconnect-v2": "^8.1.3-beta.0",
|
||||||
"ag-grid-community": "^27.0.1",
|
"ag-grid-community": "^29.3.5",
|
||||||
"ag-grid-react": "^27.0.1",
|
"ag-grid-react": "^29.3.5",
|
||||||
"allotment": "1.18.1",
|
"allotment": "1.18.1",
|
||||||
"alpha-lyrae": "vegaprotocol/alpha-lyrae",
|
"alpha-lyrae": "vegaprotocol/alpha-lyrae",
|
||||||
"apollo": "^2.33.9",
|
"apollo": "^2.33.9",
|
||||||
|
16
yarn.lock
16
yarn.lock
@ -8809,15 +8809,15 @@ aes-js@^3.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a"
|
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a"
|
||||||
integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==
|
integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==
|
||||||
|
|
||||||
ag-grid-community@^27.0.1:
|
ag-grid-community@^29.3.5:
|
||||||
version "27.3.0"
|
version "29.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/ag-grid-community/-/ag-grid-community-27.3.0.tgz#b1e94a58026aaf2f0cd7920e35833325b5e762c7"
|
resolved "https://registry.yarnpkg.com/ag-grid-community/-/ag-grid-community-29.3.5.tgz#16897896d10fa3ecac79279aad50d3aaa17c5f33"
|
||||||
integrity sha512-R5oZMXEHXnOLrmhn91J8lR0bv6IAnRcU6maO+wKLMJxffRWaAYFAuw1jt7bdmcKCv8c65F6LEBx4ykSOALa9vA==
|
integrity sha512-LxUo21f2/CH31ACEs1C7Q/ggGGI1fQPSTB4aY5OThmM+lBkygZ7QszBE8jpfgWOIjvjdtcdIeQbmbjkHeMsA7A==
|
||||||
|
|
||||||
ag-grid-react@^27.0.1:
|
ag-grid-react@^29.3.5:
|
||||||
version "27.3.0"
|
version "29.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/ag-grid-react/-/ag-grid-react-27.3.0.tgz#fe06647653f8b0b349b8e613aab8ea2e07915562"
|
resolved "https://registry.yarnpkg.com/ag-grid-react/-/ag-grid-react-29.3.5.tgz#0eae8934d372c7751e98789542fc663aee0ad6ad"
|
||||||
integrity sha512-2bs9YfJ/shvBZQLLjny4NFvht+ic6VtpTPO0r3bHHOhlL3Fjx2rGvS6AHSwfvu+kJacHCta30PjaEbX8T3UDyw==
|
integrity sha512-Eg0GJ8hEBuxdVaN5g+qITOzhw0MGL9avL0Oaajr+p7QRtq2pIFHLZSknWsCBzUTjidiu75WZMKwlZjtGEuafdQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
prop-types "^15.8.1"
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user