Compare commits

..
Author SHA1 Message Date
Dariusz Majcherczyk 9b08e9bada test: revert nonparallel tests option 2023-03-06 17:05:26 +01:00
Matthew Russell f54a629179 feat(positions): positions losses and maintenance warnings (#2985) 2023-03-06 16:01:31 +00:00
dexturr 56f48671cc chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-06 12:09:18 +00:00
Bartłomiej Głownia a65ee358ff fix(market-depth): orderbook row height calculation (#3068) 2023-03-06 10:21:45 +00:00
dexturr 7b8d814724 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-06 06:07:28 +00:00
dexturr cd237dc491 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-06 00:17:15 +00:00
dexturr 9ad00adc5a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-05 18:07:24 +00:00
Bartłomiej Głownia fab055bb34 chore(orders): fix order table rows flickering on filter change (#3088) 2023-03-05 14:08:16 +00:00
15 changed files with 475 additions and 100 deletions
+1 -3
View File
@@ -16,8 +16,6 @@ jobs:
strategy:
fail-fast: false
matrix:
# run copies of the current job in parallel
containers: [1, 2]
project: ${{ fromJSON(inputs.projects) }}
runs-on: self-hosted-runner
timeout-minutes: 30
@@ -66,7 +64,7 @@ jobs:
######
- name: Run Cypress tests
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --parallel --browser chrome --env.grepTags="${{ inputs.tags }}"
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome --env.grepTags="${{ inputs.tags }}"
working-directory: frontend-monorepo
env:
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
+125 -37
View File
@@ -104,7 +104,7 @@
"tranche_end": "2023-04-06T00:00:00.000Z",
"total_added": "14099",
"total_removed": "0",
"locked_amount": "14099",
"locked_amount": "13868.6594825268810079",
"deposits": [
{
"amount": "30",
@@ -2761,7 +2761,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "86666.297",
"total_removed": "0",
"locked_amount": "65176.5262830255815971938",
"locked_amount": "64938.8287936033066636389",
"deposits": [
{
"amount": "86666.297",
@@ -2827,7 +2827,7 @@
"tranche_end": "2023-06-01T00:00:00.000Z",
"total_added": "2500",
"total_removed": "0",
"locked_amount": "1201.84914911477425",
"locked_amount": "1188.09809981684975",
"deposits": [
{
"amount": "2500",
@@ -2948,7 +2948,7 @@
"tranche_end": "2023-09-01T00:00:00.000Z",
"total_added": "17500",
"total_removed": "0",
"locked_amount": "17071.49899984903325",
"locked_amount": "16976.28793025362225",
"deposits": [
{
"amount": "12500",
@@ -3214,8 +3214,8 @@
"tranche_start": "2023-02-01T00:00:00.000Z",
"tranche_end": "2023-08-01T00:00:00.000Z",
"total_added": "37500",
"total_removed": "3592.567813575",
"locked_amount": "30765.45954189687",
"total_removed": "3639.24714135",
"locked_amount": "30558.054212707185",
"deposits": [
{
"amount": "7500",
@@ -3254,6 +3254,11 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xee973a9efc7b88b292763a64b9e4a8fa4907826bc4b0d8f4099e1c2836bf725a"
},
{
"amount": "46.679327775",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xe31bf92bdb6d99596efda0366e9f57c53be81a3025ab5a6267cbf03380091800"
},
{
"amount": "142.173112275",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -3332,6 +3337,12 @@
"tranche_id": 34,
"tx": "0xee973a9efc7b88b292763a64b9e4a8fa4907826bc4b0d8f4099e1c2836bf725a"
},
{
"amount": "46.679327775",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 34,
"tx": "0xe31bf92bdb6d99596efda0366e9f57c53be81a3025ab5a6267cbf03380091800"
},
{
"amount": "142.173112275",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -3370,8 +3381,8 @@
}
],
"total_tokens": "7500",
"withdrawn_tokens": "1317.454630875",
"remaining_tokens": "6182.545369125"
"withdrawn_tokens": "1364.13395865",
"remaining_tokens": "6135.86604135"
},
{
"address": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
@@ -3403,7 +3414,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "129999.45",
"total_removed": "0",
"locked_amount": "65117.06090361731705922",
"locked_amount": "64879.58028324589941117",
"deposits": [
{
"amount": "129999.45",
@@ -3469,7 +3480,7 @@
"tranche_end": "2023-09-03T00:00:00.000Z",
"total_added": "62600",
"total_removed": "0",
"locked_amount": "31127.570110350074902",
"locked_amount": "30955.878652968038482",
"deposits": [
{
"amount": "10000",
@@ -3662,7 +3673,7 @@
"tranche_end": "2023-09-17T00:00:00.000Z",
"total_added": "5000",
"total_removed": "0",
"locked_amount": "2678.00846651446",
"locked_amount": "2664.295091324201",
"deposits": [
{
"amount": "5000",
@@ -3873,7 +3884,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "97499.58",
"total_removed": "0",
"locked_amount": "7095.9724407567620120928",
"locked_amount": "6863.026074492837718089",
"deposits": [
{
"amount": "97499.58",
@@ -3906,7 +3917,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "135173.4239508",
"total_removed": "98230.390980249184455396",
"locked_amount": "9698.969257979610092860239144",
"locked_amount": "9380.571791809224940956129324",
"deposits": [
{
"amount": "135173.4239508",
@@ -3952,7 +3963,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "32499.86",
"total_removed": "0",
"locked_amount": "2985.1530649368303627188",
"locked_amount": "2887.156551418174054713",
"deposits": [
{
"amount": "32499.86",
@@ -3985,7 +3996,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "10833.29",
"total_removed": "0",
"locked_amount": "971.6383553972626017448",
"locked_amount": "939.741441182597763073",
"deposits": [
{
"amount": "10833.29",
@@ -4018,7 +4029,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "22749.93",
"total_removed": "4720.860935375",
"locked_amount": "3632.2011839823285106251",
"locked_amount": "3512.9633946007858719399",
"deposits": [
{
"amount": "6500",
@@ -4169,8 +4180,8 @@
"tranche_start": "2022-11-01T00:00:00.000Z",
"tranche_end": "2023-05-01T00:00:00.000Z",
"total_added": "22500",
"total_removed": "5129.59781685",
"locked_amount": "7022.811636740331",
"total_removed": "5176.28289975",
"locked_amount": "6898.368439226519325",
"deposits": [
{
"amount": "7500",
@@ -4209,6 +4220,11 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xb7cd37bdd9d1dc5374fe1690824f423396fc7dff3379d8564086784dd81593e6"
},
{
"amount": "46.6850829",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x1ddeafc5b8ca978a842bdf2edf5e5590f99923e2e540b734b9589f4bc4657b35"
},
{
"amount": "142.17311235",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -4342,6 +4358,12 @@
"tranche_id": 33,
"tx": "0xb7cd37bdd9d1dc5374fe1690824f423396fc7dff3379d8564086784dd81593e6"
},
{
"amount": "46.6850829",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 33,
"tx": "0x1ddeafc5b8ca978a842bdf2edf5e5590f99923e2e540b734b9589f4bc4657b35"
},
{
"amount": "142.17311235",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -4452,8 +4474,8 @@
}
],
"total_tokens": "7500",
"withdrawn_tokens": "5129.59781685",
"remaining_tokens": "2370.40218315"
"withdrawn_tokens": "5176.28289975",
"remaining_tokens": "2323.71710025"
},
{
"address": "0x2539b51EbDE65a75672aBcfE9439a706a99D18D1",
@@ -4478,7 +4500,7 @@
"tranche_end": "2023-06-02T00:00:00.000Z",
"total_added": "1939928.38",
"total_removed": "928642.9598472029154",
"locked_amount": "470337.591899267535399138",
"locked_amount": "465016.998755833268669054",
"deposits": [
{
"amount": "1852091.69",
@@ -36869,7 +36891,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "3732368.4671",
"total_removed": "618385.665327542135993",
"locked_amount": "747246.449321474747218746536",
"locked_amount": "739070.550093799918600823126",
"deposits": [
{
"amount": "1998.95815",
@@ -38228,8 +38250,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "15870102.715470999700000001",
"total_removed": "588017.53786729124922952",
"locked_amount": "7949375.5171270928679546620247167076926196",
"total_removed": "588645.45995589773910452",
"locked_amount": "7920384.3034086642682516019633546259610706",
"deposits": [
{
"amount": "16249.93",
@@ -38808,6 +38830,16 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x8fd3fb0a52476d4c1c2ecdf8eb9cd4a8899acffc8ae08b98f1a2414c21078a2b"
},
{
"amount": "533.559150572712",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x4d1d66d256c15cf4e9dac71da10e817cddd26761b348519b40b9a8066f81b2a2"
},
{
"amount": "94.362938033777875",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xa7e962b98ed06faceaf876c50efca7276439f25eeb25ec574e88767fa0c5fb30"
},
{
"amount": "535.4042378778335",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -40625,6 +40657,18 @@
"tranche_id": 2,
"tx": "0x8fd3fb0a52476d4c1c2ecdf8eb9cd4a8899acffc8ae08b98f1a2414c21078a2b"
},
{
"amount": "533.559150572712",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 2,
"tx": "0x4d1d66d256c15cf4e9dac71da10e817cddd26761b348519b40b9a8066f81b2a2"
},
{
"amount": "94.362938033777875",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 2,
"tx": "0xa7e962b98ed06faceaf876c50efca7276439f25eeb25ec574e88767fa0c5fb30"
},
{
"amount": "535.4042378778335",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -41839,8 +41883,8 @@
}
],
"total_tokens": "259998.8875",
"withdrawn_tokens": "129334.021397852055125",
"remaining_tokens": "130664.866102147944875"
"withdrawn_tokens": "129961.943486458545",
"remaining_tokens": "130036.944013541455"
},
{
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
@@ -44113,8 +44157,8 @@
"tranche_start": "2021-11-05T00:00:00.000Z",
"tranche_end": "2023-05-05T00:00:00.000Z",
"total_added": "14597706.0446472999",
"total_removed": "5579839.116192283022462656",
"locked_amount": "1617367.493879510666726929279426626",
"total_removed": "5580710.615452109580396656",
"locked_amount": "1590602.990485304826063424761930942",
"deposits": [
{
"amount": "129284.449",
@@ -44368,6 +44412,16 @@
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x36fe352f02dc3716d4530a39337d348f5e6e493d48c1c8d72bfb533f36cdebcf"
},
{
"amount": "740.226257938888461",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x36f0caba9152dedc13a67b7d1aee4d50bf7ac78a7f9649baf62a71af6887c5d2"
},
{
"amount": "131.273001887669473",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x8636472fc307ddde44f9a3deca4a1f79fc49ae3741a3025c2b1dbc2cffc7e927"
},
{
"amount": "800.792718381487871",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@@ -47377,6 +47431,18 @@
"tranche_id": 3,
"tx": "0x36fe352f02dc3716d4530a39337d348f5e6e493d48c1c8d72bfb533f36cdebcf"
},
{
"amount": "740.226257938888461",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0x36f0caba9152dedc13a67b7d1aee4d50bf7ac78a7f9649baf62a71af6887c5d2"
},
{
"amount": "131.273001887669473",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0x8636472fc307ddde44f9a3deca4a1f79fc49ae3741a3025c2b1dbc2cffc7e927"
},
{
"amount": "800.792718381487871",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@@ -49893,8 +49959,8 @@
}
],
"total_tokens": "359123.469575",
"withdrawn_tokens": "318736.13986177614744925",
"remaining_tokens": "40387.32971322385255075"
"withdrawn_tokens": "319607.63912160270538325",
"remaining_tokens": "39515.83045339729461675"
},
{
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
@@ -51238,7 +51304,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "5778205.3912159303",
"total_removed": "3077573.36197477479025324",
"locked_amount": "322128.275048778237455632753579815",
"locked_amount": "311553.4578873581959790921124072965",
"deposits": [
{
"amount": "552496.6455",
@@ -53309,8 +53375,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "472355.6199999996",
"total_removed": "35033.4420916090685",
"locked_amount": "118405.471337794798654878618569256",
"total_removed": "35108.9309805010685",
"locked_amount": "117109.953369737365406394633789936",
"deposits": [
{
"amount": "3000",
@@ -59969,6 +60035,16 @@
"user": "0xf751033D4e6864a88Be93E36258246F26AEf577c",
"tx": "0x2f4a8c1de411b2a4c858e06633748bd342c23e0ad30910fc30d562f59c86de36"
},
{
"amount": "41.084474888",
"user": "0xD27929d68ac0E5fd5C919A5eb5968C1D06D3Fb83",
"tx": "0xe3f5009fa2adff80e693976889890af035747c6cba3a68ce54295c9e5cb5e51f"
},
{
"amount": "34.404414004",
"user": "0x7C8D2D8BcFffcD48dBcb65C5Bb7588B66dcD22bb",
"tx": "0x0f8f46d485aa188ed4dc215d004a6edb9af15f9cf22a0fb5544cd61a84357872"
},
{
"amount": "57.900076104",
"user": "0x96d882E908C06cD697Ea07266Fb8D14ae129A50b",
@@ -74071,6 +74147,12 @@
}
],
"withdrawals": [
{
"amount": "34.404414004",
"user": "0x7C8D2D8BcFffcD48dBcb65C5Bb7588B66dcD22bb",
"tranche_id": 5,
"tx": "0x0f8f46d485aa188ed4dc215d004a6edb9af15f9cf22a0fb5544cd61a84357872"
},
{
"amount": "21.74094368",
"user": "0x7C8D2D8BcFffcD48dBcb65C5Bb7588B66dcD22bb",
@@ -74109,8 +74191,8 @@
}
],
"total_tokens": "400",
"withdrawn_tokens": "265.545192792",
"remaining_tokens": "134.454807208"
"withdrawn_tokens": "299.949606796",
"remaining_tokens": "100.050393204"
},
{
"address": "0xc56F9f1d5f124655FA9CB8f85C7701E13a2fBF4D",
@@ -81612,6 +81694,12 @@
}
],
"withdrawals": [
{
"amount": "41.084474888",
"user": "0xD27929d68ac0E5fd5C919A5eb5968C1D06D3Fb83",
"tranche_id": 5,
"tx": "0xe3f5009fa2adff80e693976889890af035747c6cba3a68ce54295c9e5cb5e51f"
},
{
"amount": "39.564687976",
"user": "0xD27929d68ac0E5fd5C919A5eb5968C1D06D3Fb83",
@@ -81668,8 +81756,8 @@
}
],
"total_tokens": "400",
"withdrawn_tokens": "258.68491882",
"remaining_tokens": "141.31508118"
"withdrawn_tokens": "299.769393708",
"remaining_tokens": "100.230606292"
},
{
"address": "0xF5037DDA4A660d67560200f45380FF8364e35540",
+1 -2
View File
@@ -61,10 +61,9 @@ export const SetFilter = forwardRef((props: IFilterParams, ref) => {
<div className="ag-filter-body-wrapper">
<fieldset className="ag-simple-filter-body-wrapper">
{Object.keys(props.colDef.filterParams.set).map((key) => (
<label className="flex">
<label className="flex" key={key}>
<input
type="checkbox"
key={key}
value={key}
className="mr-1"
checked={value.includes(key)}
+5 -4
View File
@@ -88,9 +88,9 @@ const getRowsToRender = (
return selectedRows;
};
// 17px of row height plus 5px gap
export const gridGap = 5;
export const rowHeight = 22;
// 17px of row height plus 4px gap
export const gridGap = 4;
export const rowHeight = 21;
// top padding to make space for header
const headerPadding = 30;
// bottom padding to make space for footer
@@ -393,7 +393,8 @@ export const Orderbook = ({
numberOfRows * rowHeight +
headerPadding +
footerPadding +
-viewportHeight
-viewportHeight -
gridGap
)
);
if (scrollTopRef.current !== priceCenterScrollOffset) {
@@ -1,7 +1,7 @@
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { truncateByChars } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { useRef, useState } from 'react';
import { useCallback, useRef, useState } from 'react';
import type {
BodyScrollEvent,
BodyScrollEndEvent,
@@ -98,38 +98,60 @@ export const OrderListManager = ({
scrolledToTop,
});
const onBodyScrollEnd = (event: BodyScrollEndEvent) => {
if (event.top === 0) {
addNewRows();
}
};
const onBodyScrollEnd = useCallback(
(event: BodyScrollEndEvent) => {
if (event.top === 0) {
addNewRows();
}
},
[addNewRows]
);
const onBodyScroll = (event: BodyScrollEvent) => {
const onBodyScroll = useCallback((event: BodyScrollEvent) => {
scrolledToTop.current = event.top <= 0;
};
}, []);
const onFilterChanged = (event: FilterChangedEvent) => {
const updatedFilter = event.api.getFilterModel();
if (Object.keys(updatedFilter).length) {
setFilter(updatedFilter);
} else if (filter) {
setFilter(undefined);
}
};
const onFilterChanged = useCallback(
(event: FilterChangedEvent) => {
const updatedFilter = event.api.getFilterModel();
if (Object.keys(updatedFilter).length) {
setFilter(updatedFilter);
} else {
setFilter(undefined);
}
},
[setFilter]
);
const onSortChange = (event: SortChangedEvent) => {
const sort = event.columnApi
.getColumnState()
.sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0))
.reduce((acc, col) => {
if (col.sort) {
const { colId, sort } = col;
acc.push({ colId, sort });
}
return acc;
}, [] as { colId: string; sort: string }[]);
setSort(sort.length > 0 ? sort : undefined);
};
const onSortChange = useCallback(
(event: SortChangedEvent) => {
const sort = event.columnApi
.getColumnState()
.sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0))
.reduce((acc, col) => {
if (col.sort) {
const { colId, sort } = col;
acc.push({ colId, sort });
}
return acc;
}, [] as { colId: string; sort: string }[]);
setSort(sort.length > 0 ? sort : undefined);
},
[setSort]
);
const onCancel = useCallback(
(order: Order) => {
if (!order.market) return;
create({
orderCancellation: {
orderId: order.id,
marketId: order.market.id,
},
});
},
[create]
);
return (
<>
@@ -143,15 +165,7 @@ export const OrderListManager = ({
onBodyScroll={onBodyScroll}
onFilterChanged={onFilterChanged}
onSortChanged={onSortChange}
cancel={(order: Order) => {
if (!order.market) return;
create({
orderCancellation: {
orderId: order.id,
marketId: order.market.id,
},
});
}}
cancel={onCancel}
setEditOrder={setEditOrder}
onMarketClick={onMarketClick}
isReadOnly={isReadOnly}
@@ -91,6 +91,9 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
data,
node,
}: VegaValueFormatterParams<Order, 'size'>) => {
if (!data) {
return undefined;
}
if (!data?.market || !isNumeric(value)) {
return '-';
}
@@ -116,6 +119,9 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
value,
node,
}: VegaValueFormatterParams<Order, 'type'>) => {
if (!order) {
return undefined;
}
if (!value) return '-';
if (order?.peggedOrder) return t('Pegged');
if (order?.liquidityProvision) return t('Liquidity provision');
@@ -162,6 +168,9 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
value,
node,
}: VegaValueFormatterParams<Order, 'remaining'>) => {
if (!data) {
return undefined;
}
if (!data?.market || !isNumeric(value) || !isNumeric(data.size)) {
return '-';
}
@@ -184,6 +193,9 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
data,
node,
}: VegaValueFormatterParams<Order, 'price'>) => {
if (!data) {
return undefined;
}
if (
!data?.market ||
data.type === Schema.OrderType.TYPE_MARKET ||
@@ -237,6 +249,9 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
data,
value,
}: VegaICellRendererParams<Order, 'updatedAt'>) => {
if (!data) {
return undefined;
}
return (
<span data-value={value}>
{value ? getDateTimeFormat().format(new Date(value)) : '-'}
+4
View File
@@ -4,6 +4,8 @@ fragment PositionFields on Position {
unrealisedPNL
averageEntryPrice
updatedAt
positionStatus
lossSocializationAmount
market {
id
}
@@ -30,6 +32,8 @@ subscription PositionsSubscription($partyId: ID!) {
averageEntryPrice
updatedAt
marketId
lossSocializationAmount
positionStatus
}
}
+7 -3
View File
@@ -3,21 +3,21 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type PositionFieldsFragment = { __typename?: 'Position', realisedPNL: string, openVolume: string, unrealisedPNL: string, averageEntryPrice: string, updatedAt?: any | null, market: { __typename?: 'Market', id: string } };
export type PositionFieldsFragment = { __typename?: 'Position', realisedPNL: string, openVolume: string, unrealisedPNL: string, averageEntryPrice: string, updatedAt?: any | null, positionStatus: Types.PositionStatus, lossSocializationAmount: string, market: { __typename?: 'Market', id: string } };
export type PositionsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type PositionsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, positionsConnection?: { __typename?: 'PositionConnection', edges?: Array<{ __typename?: 'PositionEdge', node: { __typename?: 'Position', realisedPNL: string, openVolume: string, unrealisedPNL: string, averageEntryPrice: string, updatedAt?: any | null, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
export type PositionsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, positionsConnection?: { __typename?: 'PositionConnection', edges?: Array<{ __typename?: 'PositionEdge', node: { __typename?: 'Position', realisedPNL: string, openVolume: string, unrealisedPNL: string, averageEntryPrice: string, updatedAt?: any | null, positionStatus: Types.PositionStatus, lossSocializationAmount: string, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
export type PositionsSubscriptionSubscriptionVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type PositionsSubscriptionSubscription = { __typename?: 'Subscription', positions: Array<{ __typename?: 'PositionUpdate', realisedPNL: string, openVolume: string, unrealisedPNL: string, averageEntryPrice: string, updatedAt?: any | null, marketId: string }> };
export type PositionsSubscriptionSubscription = { __typename?: 'Subscription', positions: Array<{ __typename?: 'PositionUpdate', realisedPNL: string, openVolume: string, unrealisedPNL: string, averageEntryPrice: string, updatedAt?: any | null, marketId: string, lossSocializationAmount: string, positionStatus: Types.PositionStatus }> };
export type MarginFieldsFragment = { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string, asset: { __typename?: 'Asset', id: string }, market: { __typename?: 'Market', id: string } };
@@ -42,6 +42,8 @@ export const PositionFieldsFragmentDoc = gql`
unrealisedPNL
averageEntryPrice
updatedAt
positionStatus
lossSocializationAmount
market {
id
}
@@ -112,6 +114,8 @@ export const PositionsSubscriptionDocument = gql`
averageEntryPrice
updatedAt
marketId
lossSocializationAmount
positionStatus
}
}
`;
@@ -6,6 +6,7 @@ import type {
MarginFieldsFragment,
} from './__generated__/Positions';
import { getMetrics, rejoinPositionData } from './positions-data-providers';
import { PositionStatus } from '@vegaprotocol/types';
const accounts = [
{
@@ -78,6 +79,8 @@ const positions: PositionFieldsFragment[] = [
__typename: 'Market',
id: '5e6035fe6a6df78c9ec44b333c231e63d357acef0a0620d2c243f5865d1dc0d8',
},
lossSocializationAmount: '0',
positionStatus: PositionStatus.POSITION_STATUS_UNSPECIFIED,
},
{
__typename: 'Position',
@@ -90,6 +93,8 @@ const positions: PositionFieldsFragment[] = [
__typename: 'Market',
id: '10c4b1114d2f6fda239b73d018bca55888b6018f0ac70029972a17fea0a6a56e',
},
lossSocializationAmount: '100',
positionStatus: PositionStatus.POSITION_STATUS_ORDERS_CLOSED,
},
];
@@ -225,6 +230,10 @@ describe('getMetrics && rejoinPositionData', () => {
expect(metrics[0].totalBalance).toEqual('926178496');
expect(metrics[0].unrealisedPNL).toEqual('43804770');
expect(metrics[0].updatedAt).toEqual('2022-07-28T14:53:54.725477Z');
expect(metrics[0].lossSocializationAmount).toEqual(
positions[0].lossSocializationAmount
);
expect(metrics[0].status).toEqual(positions[0].positionStatus);
expect(metrics[1].assetSymbol).toEqual('tDAI');
expect(metrics[1].averageEntryPrice).toEqual('840158');
@@ -248,5 +257,9 @@ describe('getMetrics && rejoinPositionData', () => {
expect(metrics[1].totalBalance).toEqual('896098819');
expect(metrics[1].unrealisedPNL).toEqual('-9112700');
expect(metrics[1].updatedAt).toEqual('2022-07-28T15:09:34.441143Z');
expect(metrics[1].lossSocializationAmount).toEqual(
positions[1].lossSocializationAmount
);
expect(metrics[1].status).toEqual(positions[1].positionStatus);
});
});
@@ -24,6 +24,7 @@ import {
PositionsSubscriptionDocument,
} from './__generated__/Positions';
import { marginsDataProvider } from './margin-data-provider';
import type { PositionStatus } from '@vegaprotocol/types';
type PositionMarginLevel = Pick<
MarginFieldsFragment,
@@ -38,6 +39,8 @@ interface PositionRejoined {
updatedAt?: string | null;
market: MarketMaybeWithData | null;
margins: PositionMarginLevel | null;
lossSocializationAmount: string | null;
status: PositionStatus;
}
export interface Position {
@@ -62,6 +65,8 @@ export interface Position {
unrealisedPNL: string;
searchPrice: string | undefined;
updatedAt: string | null;
lossSocializationAmount: string;
status: PositionStatus;
}
export interface Data {
@@ -178,6 +183,8 @@ export const getMetrics = (
? searchPrice.multipliedBy(10 ** marketDecimalPlaces).toFixed(0)
: undefined,
updatedAt: position.updatedAt || null,
lossSocializationAmount: position.lossSocializationAmount || '0',
status: position.status,
});
});
return metrics;
@@ -201,6 +208,8 @@ export const update = (
openVolume: delta.openVolume,
averageEntryPrice: delta.averageEntryPrice,
updatedAt: delta.updatedAt,
lossSocializationAmount: delta.lossSocializationAmount,
positionStatus: delta.positionStatus,
};
} else {
draft.unshift({
@@ -267,6 +276,8 @@ export const rejoinPositionData = (
market:
marketsData?.find((market) => market.id === node.market.id) || null,
margins: upgradeMarginsConnection(node.market.id, margins),
lossSocializationAmount: node.lossSocializationAmount,
status: node.positionStatus,
};
});
}
+101 -2
View File
@@ -1,8 +1,11 @@
import type { RenderResult } from '@testing-library/react';
import { act, render, screen } from '@testing-library/react';
import PositionsTable from './positions-table';
import { act, render, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import PositionsTable, { OpenVolumeCell, PNLCell } from './positions-table';
import type { Position } from './positions-data-providers';
import * as Schema from '@vegaprotocol/types';
import { PositionStatus, PositionStatusMapping } from '@vegaprotocol/types';
import type { ICellRendererParams } from 'ag-grid-community';
const singleRow: Position = {
marketName: 'ETH/BTC (31 july 2022)',
@@ -26,6 +29,8 @@ const singleRow: Position = {
searchPrice: '0',
updatedAt: '2022-07-27T15:02:58.400Z',
marginAccountBalance: '12345600',
status: PositionStatus.POSITION_STATUS_UNSPECIFIED,
lossSocializationAmount: '0',
};
const singleRowData = [singleRow];
@@ -219,3 +224,97 @@ it('do not display close button if openVolume is zero', async () => {
const cells = screen.getAllByRole('gridcell');
expect(cells[12].textContent).toEqual('');
});
describe('PNLCell', () => {
const props = {
data: undefined,
valueFormatted: '100',
};
it('renders a dash if no data', () => {
render(<PNLCell {...(props as ICellRendererParams)} />);
expect(screen.getByText('-')).toBeInTheDocument();
});
it('renders value if no loss socialisation has occurred', () => {
const props = {
data: {
...singleRow,
lossSocialisationAmount: '0',
},
valueFormatted: '100',
};
render(<PNLCell {...(props as ICellRendererParams)} />);
expect(screen.getByText(props.valueFormatted)).toBeInTheDocument();
expect(screen.queryByRole('img')).not.toBeInTheDocument();
});
it('renders value with warning tooltip if loss socialisation occurred', async () => {
const props = {
data: {
...singleRow,
lossSocializationAmount: '500',
decimals: 2,
},
valueFormatted: '100',
};
render(<PNLCell {...(props as ICellRendererParams)} />);
const content = screen.getByText(props.valueFormatted);
expect(content).toBeInTheDocument();
expect(screen.getByRole('img')).toBeInTheDocument();
await userEvent.hover(content);
const tooltip = await screen.findByRole('tooltip');
expect(tooltip).toBeInTheDocument();
expect(
// using within as radix renders tooltip content twice
within(tooltip).getByText('Lifetime loss socialisation deductions: 5.00')
).toBeInTheDocument();
});
});
describe('OpenVolumeCell', () => {
const props = {
data: undefined,
valueFormatted: '100',
};
it('renders a dash if no data', () => {
render(<OpenVolumeCell {...(props as ICellRendererParams)} />);
expect(screen.getByText('-')).toBeInTheDocument();
});
it('renders value if no status is normal', () => {
const props = {
data: {
...singleRow,
status: PositionStatus.POSITION_STATUS_UNSPECIFIED,
},
valueFormatted: '100',
};
render(<OpenVolumeCell {...(props as ICellRendererParams)} />);
expect(screen.getByText(props.valueFormatted)).toBeInTheDocument();
expect(screen.queryByRole('img')).not.toBeInTheDocument();
});
it('renders status with warning tooltip if not normal', async () => {
const props = {
data: {
...singleRow,
status: PositionStatus.POSITION_STATUS_ORDERS_CLOSED,
},
valueFormatted: '100',
};
render(<OpenVolumeCell {...(props as ICellRendererParams)} />);
const content = screen.getByText(props.valueFormatted);
expect(content).toBeInTheDocument();
expect(screen.getByRole('img')).toBeInTheDocument();
await userEvent.hover(content);
const tooltip = await screen.findByRole('tooltip');
expect(tooltip).toBeInTheDocument();
expect(
// using within as radix renders tooltip content twice
within(tooltip).getByText(
`Status: ${PositionStatusMapping[props.data.status]}`
)
).toBeInTheDocument();
});
});
+120 -10
View File
@@ -1,6 +1,6 @@
import classNames from 'classnames';
import { forwardRef } from 'react';
import type { CSSProperties } from 'react';
import type { CSSProperties, ReactNode } from 'react';
import type { CellRendererSelectorResult } from 'ag-grid-community';
import type {
VegaValueFormatterParams,
@@ -15,6 +15,15 @@ import {
signedNumberCssClass,
signedNumberCssClassRules,
} from '@vegaprotocol/datagrid';
import {
ButtonLink,
Tooltip,
TooltipCellComponent,
Link,
ExternalLink,
Icon,
ProgressBarCell,
} from '@vegaprotocol/ui-toolkit';
import {
volumePrefix,
toBigNum,
@@ -27,13 +36,9 @@ import { AgGridColumn } from 'ag-grid-react';
import type { AgGridReact } from 'ag-grid-react';
import type { Position } from './positions-data-providers';
import * as Schema from '@vegaprotocol/types';
import {
ButtonLink,
Link,
ProgressBarCell,
TooltipCellComponent,
} from '@vegaprotocol/ui-toolkit';
import { getRowId } from './use-positions-data';
import { PositionStatus, PositionStatusMapping } from '@vegaprotocol/types';
import { useEnvironment } from '@vegaprotocol/environment';
interface Props extends TypedDataAgGrid<Position> {
onClose?: (data: Position) => void;
@@ -167,6 +172,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
)
);
}}
cellRenderer={OpenVolumeCell}
/>
<AgGridColumn
headerName={t('Mark price')}
@@ -311,7 +317,6 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
}}
valueFormatter={({
data,
node,
}: VegaValueFormatterParams<Position, 'marginAccountBalance'>):
| string
| undefined => {
@@ -329,7 +334,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
field="realisedPNL"
type="rightAligned"
cellClassRules={signedNumberCssClassRules}
cellClass="text-right font-mono"
cellClass="font-mono text-right"
filter="agNumberColumnFilter"
valueGetter={({
data,
@@ -348,13 +353,14 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
headerTooltip={t(
'Profit or loss is realised whenever your position is reduced to zero and the margin is released back to your collateral balance. P&L excludes any fees paid.'
)}
cellRenderer={PNLCell}
/>
<AgGridColumn
headerName={t('Unrealised PNL')}
field="unrealisedPNL"
type="rightAligned"
cellClassRules={signedNumberCssClassRules}
cellClass="text-right font-mono"
cellClass="font-mono text-right"
filter="agNumberColumnFilter"
valueGetter={({
data,
@@ -373,6 +379,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
headerTooltip={t(
'Unrealised profit is the current profit on your open position. Margin is still allocated to your position.'
)}
cellRenderer={PNLCell}
/>
<AgGridColumn
headerName={t('Updated')}
@@ -409,3 +416,106 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
);
export default PositionsTable;
export const PNLCell = ({
valueFormatted,
data,
}: VegaICellRendererParams<Position, 'realisedPNL'>) => {
const { VEGA_DOCS_URL } = useEnvironment();
if (!data) {
return <>-</>;
}
const losses = parseInt(data?.lossSocializationAmount ?? '0');
if (losses <= 0) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{valueFormatted}</>;
}
const lossesFormatted = addDecimalsFormatNumber(
data.lossSocializationAmount,
data.decimals
);
return (
<WarningCell
tooltipContent={
<>
<p className="mb-2">
{t('Lifetime loss socialisation deductions: %s', lossesFormatted)}
</p>
{VEGA_DOCS_URL && (
<ExternalLink href={VEGA_DOCS_URL}>
{t('Read more about loss socialisation')}
</ExternalLink>
)}
</>
}
>
{valueFormatted}
</WarningCell>
);
};
export const OpenVolumeCell = ({
valueFormatted,
data,
}: VegaICellRendererParams<Position, 'openVolume'>) => {
const { VEGA_DOCS_URL } = useEnvironment();
if (!data) {
return <>-</>;
}
if (data.status === PositionStatus.POSITION_STATUS_UNSPECIFIED) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{valueFormatted}</>;
}
return (
<WarningCell
tooltipContent={
<>
<p className="mb-2">
{t('Your position was affected by market conditions')}
</p>
<p className="mb-2">
{t(
'Status: %s',
PositionStatusMapping[
PositionStatus.POSITION_STATUS_ORDERS_CLOSED
]
)}
</p>
{VEGA_DOCS_URL && (
<ExternalLink href={VEGA_DOCS_URL}>
{t('Read more about position resolution')}
</ExternalLink>
)}
</>
}
>
{valueFormatted}
</WarningCell>
);
};
const WarningCell = ({
children,
tooltipContent,
}: {
children: ReactNode;
tooltipContent: ReactNode;
}) => {
return (
<Tooltip description={tooltipContent}>
<div className="w-full flex items-center justify-between underline decoration-dashed underline-offest-2">
<span className="text-black dark:text-white mr-1">
<Icon name="warning-sign" size={3} />
</span>
<span className="text-ellipsis overflow-hidden">{children}</span>
</div>
</Tooltip>
);
};
+8 -1
View File
@@ -1,3 +1,4 @@
import { PositionStatus } from '@vegaprotocol/types';
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
import type {
@@ -58,6 +59,8 @@ const positionFields: PositionFieldsFragment[] = [
id: 'market-0',
__typename: 'Market',
},
lossSocializationAmount: '0',
positionStatus: PositionStatus.POSITION_STATUS_UNSPECIFIED,
},
{
__typename: 'Position',
@@ -70,8 +73,11 @@ const positionFields: PositionFieldsFragment[] = [
id: 'market-1',
__typename: 'Market',
},
lossSocializationAmount: '0',
positionStatus: PositionStatus.POSITION_STATUS_UNSPECIFIED,
},
{
__typename: 'Position',
realisedPNL: '230000',
openVolume: '1',
unrealisedPNL: '-22519',
@@ -81,7 +87,8 @@ const positionFields: PositionFieldsFragment[] = [
id: 'market-2',
__typename: 'Market',
},
__typename: 'Position',
lossSocializationAmount: '0',
positionStatus: PositionStatus.POSITION_STATUS_UNSPECIFIED,
},
];
+3
View File
@@ -1 +1,4 @@
import '@testing-library/jest-dom';
import ResizeObserver from 'resize-observer-polyfill';
global.ResizeObserver = ResizeObserver;
+9
View File
@@ -12,6 +12,7 @@ import type {
OrderStatus,
OrderTimeInForce,
OrderType,
PositionStatus,
ProposalRejectionReason,
ProposalState,
Side,
@@ -445,3 +446,11 @@ export const DispatchMetricLabels: DispatchMetricLabel = {
DISPATCH_METRIC_MAKER_FEES_RECEIVED: 'Price maker fees earned',
DISPATCH_METRIC_MARKET_VALUE: 'Total market Value',
};
export const PositionStatusMapping: {
[T in PositionStatus]: string;
} = {
POSITION_STATUS_CLOSED_OUT: 'Closed by network',
POSITION_STATUS_ORDERS_CLOSED: 'Maintained by network',
POSITION_STATUS_UNSPECIFIED: 'Normal',
};