Compare commits

..
140 changed files with 1691 additions and 2068 deletions
@@ -4,8 +4,9 @@ import {
getMarketExpiryDateFormatted,
} from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import type { MarketInfoWithData } from '@vegaprotocol/market-info';
import type { MarketInfoNoCandlesQuery } from '@vegaprotocol/market-info';
import { MarketInfoTable } from '@vegaprotocol/market-info';
import pick from 'lodash/pick';
import {
MarketStateMapping,
MarketTradingModeMapping,
@@ -16,7 +17,11 @@ import BigNumber from 'bignumber.js';
import { useMemo } from 'react';
import { Link } from 'react-router-dom';
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
export const MarketDetails = ({
market,
}: {
market: MarketInfoNoCandlesQuery['market'];
}) => {
const quoteUnit = market?.tradableInstrument.instrument.product.quoteName;
const assetId = useMemo(
() => market?.tradableInstrument.instrument.product?.settlementAsset.id,
@@ -27,9 +32,7 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
if (!market) return null;
const keyDetails = {
decimalPlaces: market.decimalPlaces,
positionDecimalPlaces: market.positionDecimalPlaces,
tradingMode: market.tradingMode,
...pick(market, 'decimalPlaces', 'positionDecimalPlaces', 'tradingMode'),
state: MarketStateMapping[market.state],
};
const assetDecimals =
+1 -1
View File
@@ -21,7 +21,7 @@ type NavStore = {
hide: () => void;
};
export const useNavStore = create<NavStore>((set, get) => ({
export const useNavStore = create<NavStore>()((set, get) => ({
open: false,
toggle: () => set({ open: !get().open }),
hide: () => set({ open: false }),
@@ -12,7 +12,6 @@ export const Proposals = () => {
const { data, loading, error } = useDataProvider({
dataProvider: proposalsDataProvider,
variables: {},
});
useDocumentTitle([t('Governance Proposals')]);
@@ -1,14 +1,14 @@
import { t } from '@vegaprotocol/i18n';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
import { useState } from 'react';
import { useMemo, useState } from 'react';
import { useParams } from 'react-router-dom';
import { MarketDetails } from '../../components/markets/market-details';
import { useScrollToLocation } from '../../hooks/scroll-to-location';
import { useDocumentTitle } from '../../hooks/use-document-title';
import compact from 'lodash/compact';
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
import { marketInfoProvider } from '@vegaprotocol/market-info';
import { marketInfoNoCandlesDataProvider } from '@vegaprotocol/market-info';
import { PageTitle } from '../../components/page-helpers/page-title';
export const MarketPage = () => {
@@ -16,17 +16,24 @@ export const MarketPage = () => {
const { marketId } = useParams<{ marketId: string }>();
const variables = useMemo(
() => ({
marketId,
}),
[marketId]
);
const { data, loading, error } = useDataProvider({
dataProvider: marketInfoProvider,
dataProvider: marketInfoNoCandlesDataProvider,
skipUpdates: true,
variables: {
marketId: marketId || '',
skip: !marketId,
},
variables,
});
useDocumentTitle(
compact(['Market details', data?.tradableInstrument.instrument.name])
compact([
'Market details',
data?.market?.tradableInstrument.instrument.name,
])
);
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
@@ -36,10 +43,10 @@ export const MarketPage = () => {
<section className="relative">
<PageTitle
data-testid="markets-heading"
title={data?.tradableInstrument.instrument.name || ''}
title={data?.market?.tradableInstrument.instrument.name || ''}
actions={
<Button
disabled={!data}
disabled={!data?.market}
size="xs"
onClick={() => setDialogOpen(true)}
>
@@ -53,14 +60,14 @@ export const MarketPage = () => {
loading={loading}
error={error}
>
{data && <MarketDetails market={data} />}
<MarketDetails market={data?.market} />
</AsyncRenderer>
</section>
<JsonViewerDialog
open={dialogOpen}
onChange={(isOpen) => setDialogOpen(isOpen)}
title={data?.tradableInstrument.instrument.name || ''}
content={data}
title={data?.market?.tradableInstrument.instrument.name || ''}
content={data?.market}
/>
</>
);
@@ -13,7 +13,6 @@ export const MarketsPage = () => {
const { data, loading, error } = useDataProvider({
dataProvider: marketsProvider,
variables: undefined,
skipUpdates: true,
});
@@ -9,26 +9,28 @@ export type PendingTxsStore = {
resetPendingTxs: () => void;
};
export const usePendingBalancesStore = create<PendingTxsStore>((set, get) => ({
pendingBalances: [],
addPendingTxs: (event: Event[]) => {
set({
pendingBalances: uniqBy(
[...get().pendingBalances, ...event],
'transactionHash'
),
});
},
removePendingTx: (event: Event) => {
set({
pendingBalances: [
...get().pendingBalances.filter(
({ transactionHash }) => transactionHash !== event.transactionHash
export const usePendingBalancesStore = create<PendingTxsStore>()(
(set, get) => ({
pendingBalances: [],
addPendingTxs: (event: Event[]) => {
set({
pendingBalances: uniqBy(
[...get().pendingBalances, ...event],
'transactionHash'
),
],
});
},
resetPendingTxs: () => {
set({ pendingBalances: [] });
},
}));
});
},
removePendingTx: (event: Event) => {
set({
pendingBalances: [
...get().pendingBalances.filter(
({ transactionHash }) => transactionHash !== event.transactionHash
),
],
});
},
resetPendingTxs: () => {
set({ pendingBalances: [] });
},
})
);
@@ -38,7 +38,7 @@ export interface RefreshBalances {
vestingAssociatedBalance: BigNumber;
}
export const useBalances = create<BalancesStore>((set) => ({
export const useBalances = create<BalancesStore>()((set) => ({
associationBreakdown: {
stakingAssociations: {},
vestingAssociations: {},
@@ -1,7 +1,7 @@
import { toBigNum } from '@vegaprotocol/utils';
import type { TrancheServiceResponse } from '@vegaprotocol/smart-contracts';
import type BigNumber from 'bignumber.js';
import create from 'zustand';
import { create } from 'zustand';
import { ENV } from '../../config';
export interface Tranche {
@@ -36,7 +36,7 @@ export type TranchesStore = {
const secondsToDate = (seconds: number) => new Date(seconds * 1000);
export const useTranches = create<TranchesStore>((set) => ({
export const useTranches = create<TranchesStore>()((set) => ({
tranches: null,
loading: false,
error: null,
+22 -25
View File
@@ -1,5 +1,4 @@
import type ethers from 'ethers';
import type { GetState, SetState } from 'zustand';
import { create } from 'zustand';
export interface TxData {
@@ -16,27 +15,25 @@ interface TransactionStore {
remove: (tx: TxData) => void;
}
export const useTransactionStore = create(
(set: SetState<TransactionStore>, get: GetState<TransactionStore>) => ({
transactions: [],
add: (tx) => {
const { transactions } = get();
set({ transactions: [...transactions, tx] });
},
update: (tx) => {
const { transactions } = get();
set({
transactions: [
...transactions.filter((t) => t.tx.hash !== tx.tx.hash),
tx,
],
});
},
remove: (tx) => {
const { transactions } = get();
set({
transactions: transactions.filter((t) => t.tx.hash !== tx.tx.hash),
});
},
})
);
export const useTransactionStore = create<TransactionStore>()((set, get) => ({
transactions: [],
add: (tx) => {
const { transactions } = get();
set({ transactions: [...transactions, tx] });
},
update: (tx) => {
const { transactions } = get();
set({
transactions: [
...transactions.filter((t) => t.tx.hash !== tx.tx.hash),
tx,
],
});
},
remove: (tx) => {
const { transactions } = get();
set({
transactions: transactions.filter((t) => t.tx.hash !== tx.tx.hash),
});
},
}));
@@ -1,4 +1,5 @@
import { useParams } from 'react-router-dom';
import { useMemo } from 'react';
import { makeDerivedDataProvider } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { useDataProvider } from '@vegaprotocol/react-helpers';
@@ -42,7 +43,7 @@ const useMarketDetails = (marketId: string | undefined) => {
const { data, loading, error } = useDataProvider({
dataProvider: lpDataProvider,
skipUpdates: true,
variables: { marketId: marketId || '' },
variables: useMemo(() => ({ marketId }), [marketId]),
});
const liquidityProviders = data?.liquidityProviders || [];
@@ -39,11 +39,14 @@ export const Last24hVolume = ({
[marketId, yTimestamp]
);
const variables24hAgo = {
marketId: marketId,
interval: Schema.Interval.INTERVAL_I1D,
since: yTimestamp,
};
const variables24hAgo = useMemo(
() => ({
marketId: marketId,
interval: Schema.Interval.INTERVAL_I1D,
since: yTimestamp,
}),
[marketId, yTimestamp]
);
const throttledSetCandles = useRef(
throttle((data: Candle[]) => {
@@ -61,7 +64,7 @@ export const Last24hVolume = ({
[throttledSetCandles]
);
const { data, error } = useDataProvider({
const { data, error } = useDataProvider<Candle[], Candle>({
dataProvider: marketCandlesProvider,
variables: variables,
update,
@@ -85,7 +88,7 @@ export const Last24hVolume = ({
[throttledSetVolumeChange]
);
useDataProvider({
useDataProvider<Candle[], Candle>({
dataProvider: marketCandlesProvider,
update: updateCandle24hAgo,
variables: variables24hAgo,
+70 -335
View File
@@ -115,7 +115,7 @@
"tranche_end": "2023-04-06T00:00:00.000Z",
"total_added": "14099",
"total_removed": "0",
"locked_amount": "12162.8773547640385333",
"locked_amount": "12845.7134438470736744",
"deposits": [
{
"amount": "30",
@@ -2772,7 +2772,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "86666.297",
"total_removed": "0",
"locked_amount": "64048.2869723021614118096",
"locked_amount": "64404.7768689454615673836",
"deposits": [
{
"amount": "86666.297",
@@ -2838,7 +2838,7 @@
"tranche_end": "2023-06-01T00:00:00.000Z",
"total_added": "2500",
"total_removed": "0",
"locked_amount": "1136.57932056369565",
"locked_amount": "1157.2026353276355",
"deposits": [
{
"amount": "2500",
@@ -2959,7 +2959,7 @@
"tranche_end": "2023-09-01T00:00:00.000Z",
"total_added": "17500",
"total_removed": "0",
"locked_amount": "16619.57638259863175",
"locked_amount": "16762.3704206924315",
"deposits": [
{
"amount": "12500",
@@ -3226,7 +3226,7 @@
"tranche_end": "2023-08-01T00:00:00.000Z",
"total_added": "37500",
"total_removed": "3720.2151432",
"locked_amount": "29781.0030118170675",
"locked_amount": "30092.06184775936125",
"deposits": [
{
"amount": "7500",
@@ -3436,7 +3436,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "129999.45",
"total_removed": "0",
"locked_amount": "63989.85096930441024387",
"locked_amount": "64346.015613772301177895",
"deposits": [
{
"amount": "129999.45",
@@ -3502,7 +3502,7 @@
"tranche_end": "2023-09-03T00:00:00.000Z",
"total_added": "62600",
"total_removed": "0",
"locked_amount": "30312.63070142060129",
"locked_amount": "30570.1271943176011",
"deposits": [
{
"amount": "10000",
@@ -3695,7 +3695,7 @@
"tranche_end": "2023-09-17T00:00:00.000Z",
"total_added": "5000",
"total_removed": "0",
"locked_amount": "2612.917459411466",
"locked_amount": "2633.484271943176",
"deposits": [
{
"amount": "5000",
@@ -3906,7 +3906,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "97499.58",
"total_removed": "0",
"locked_amount": "5990.2844995508528472834",
"locked_amount": "6339.6488375364585926712",
"deposits": [
{
"amount": "97499.58",
@@ -3939,7 +3939,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "135173.4239508",
"total_removed": "98230.390980249184455396",
"locked_amount": "8187.6847314107206565101429512",
"locked_amount": "8665.205466200317294112311476",
"deposits": [
{
"amount": "135173.4239508",
@@ -3985,7 +3985,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "32499.86",
"total_removed": "0",
"locked_amount": "2520.0092422809283331812",
"locked_amount": "2666.9807860720642474196",
"deposits": [
{
"amount": "32499.86",
@@ -4018,7 +4018,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "10833.29",
"total_removed": "0",
"locked_amount": "820.2385547715821026331",
"locked_amount": "868.0763660974942076085",
"deposits": [
{
"amount": "10833.29",
@@ -4051,7 +4051,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "22749.93",
"total_removed": "4720.860935375",
"locked_amount": "3066.2349147087707630196",
"locked_amount": "3245.0633378272258072119",
"deposits": [
{
"amount": "6500",
@@ -4203,7 +4203,7 @@
"tranche_end": "2023-05-01T00:00:00.000Z",
"total_added": "22500",
"total_removed": "5257.2509016",
"locked_amount": "6432.1377186924486",
"locked_amount": "6618.773020257828",
"deposits": [
{
"amount": "7500",
@@ -4533,7 +4533,7 @@
"tranche_end": "2023-06-02T00:00:00.000Z",
"total_added": "1939928.38",
"total_removed": "928642.9598472029154",
"locked_amount": "445083.2135068917618794644",
"locked_amount": "453062.8421701724988668568",
"deposits": [
{
"amount": "1852091.69",
@@ -7507,15 +7507,10 @@
"tranche_id": 10,
"tranche_start": "2021-07-15T23:37:11.000Z",
"tranche_end": "2021-07-15T23:37:11.000Z",
"total_added": "6359302.299000000000000001",
"total_removed": "6313483.280000000000000001",
"total_added": "6259302.299000000000000001",
"total_removed": "6213483.280000000000000001",
"locked_amount": "0",
"deposits": [
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
"tx": "0xf82d4ea9a92b8374c542a9cff94581e511ca54ee70eb0f65436727ac473aeb75"
},
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
@@ -8043,11 +8038,6 @@
}
],
"withdrawals": [
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
"tx": "0xf82d4ea9a92b8374c542a9cff94581e511ca54ee70eb0f65436727ac473aeb75"
},
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
@@ -8518,12 +8508,6 @@
{
"address": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
"deposits": [
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
"tranche_id": 10,
"tx": "0xf82d4ea9a92b8374c542a9cff94581e511ca54ee70eb0f65436727ac473aeb75"
},
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
@@ -8712,12 +8696,6 @@
}
],
"withdrawals": [
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
"tranche_id": 10,
"tx": "0xf82d4ea9a92b8374c542a9cff94581e511ca54ee70eb0f65436727ac473aeb75"
},
{
"amount": "100000",
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
@@ -8899,8 +8877,8 @@
"tx": "0xac16a4ce688d40a482a59914d68c3a676592f8804ee8f0781b66a4ba5ccfbdfc"
}
],
"total_tokens": "3156651",
"withdrawn_tokens": "3156651",
"total_tokens": "3056651",
"withdrawn_tokens": "3056651",
"remaining_tokens": "0"
},
{
@@ -9965,7 +9943,7 @@
"tranche_start": "2021-09-03T00:00:00.000Z",
"tranche_end": "2022-09-03T00:00:00.000Z",
"total_added": "55431.000000000000000003",
"total_removed": "44310.21518131551",
"total_removed": "44298.21518131551",
"locked_amount": "0",
"deposits": [
{
@@ -20245,11 +20223,6 @@
"user": "0x4043fD11285B4f98A0f7b383D973a17F03e23EC5",
"tx": "0xa3689042534a1b09c39510c3a9da4f5838c77e88df0dd7dd76415b759d9ad377"
},
{
"amount": "12",
"user": "0xCeE1b5DF292f5EA23798271f8e1374D911Fb4DE0",
"tx": "0xfc74f691ee45ff735fd4df873755059973385f62772d50a85d9cc1e5ba53e528"
},
{
"amount": "12",
"user": "0x1D92cb812FdeDF1a5aFE3c5080B2D3Ec102694c6",
@@ -35756,17 +35729,10 @@
"tx": "0xd03e666dd6a358145f291e4ceec193352614d00727ed8910a4cad16374fffa43"
}
],
"withdrawals": [
{
"amount": "12",
"user": "0xCeE1b5DF292f5EA23798271f8e1374D911Fb4DE0",
"tranche_id": 11,
"tx": "0xfc74f691ee45ff735fd4df873755059973385f62772d50a85d9cc1e5ba53e528"
}
],
"withdrawals": [],
"total_tokens": "12",
"withdrawn_tokens": "12",
"remaining_tokens": "0"
"withdrawn_tokens": "0",
"remaining_tokens": "12"
},
{
"address": "0x2dd204e9cC4D41C68f2bb7Aa3b8Ce49884e482f5",
@@ -37303,8 +37269,8 @@
"tranche_start": "2022-03-05T00:00:00.000Z",
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "3732368.4671",
"total_removed": "700133.348465855088393",
"locked_amount": "708439.26237307499947324745",
"total_removed": "618385.665327542135993",
"locked_amount": "720701.17341691302668589937",
"deposits": [
{
"amount": "1998.95815",
@@ -37478,16 +37444,6 @@
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
"tx": "0xcba878ae28c2c84219f8281dc2a57d0d9b6c99b7920900d5344c76aabe8f1e84"
},
{
"amount": "52343.18016",
"user": "0x93b478148FF792B00076B7EdC89Db1FdE7772079",
"tx": "0x282e2c8a2d0f87b31d99e0be5d955c1c1a5b69ff43364630a130a1222fb6d06c"
},
{
"amount": "29404.5029783129524",
"user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
"tx": "0x166702670ca700f8d8957a5264ec47f6bcf67609682512d11dabc14276add0fb"
},
{
"amount": "16659.576193025747093",
"user": "0xB523235B6c7C74DDB26b10E78bFb2d0Cb63Ae289",
@@ -38166,12 +38122,6 @@
}
],
"withdrawals": [
{
"amount": "29404.5029783129524",
"user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
"tranche_id": 1,
"tx": "0x166702670ca700f8d8957a5264ec47f6bcf67609682512d11dabc14276add0fb"
},
{
"amount": "20348.9930984908397",
"user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
@@ -38198,8 +38148,8 @@
}
],
"total_tokens": "112323.67",
"withdrawn_tokens": "90743.8609743760004",
"remaining_tokens": "21579.8090256239996"
"withdrawn_tokens": "61339.357996063048",
"remaining_tokens": "50984.312003936952"
},
{
"address": "0x3D7944C81794Bc621076958cA0dC0F0b31BDc3e2",
@@ -38576,12 +38526,6 @@
}
],
"withdrawals": [
{
"amount": "52343.18016",
"user": "0x93b478148FF792B00076B7EdC89Db1FdE7772079",
"tranche_id": 1,
"tx": "0x282e2c8a2d0f87b31d99e0be5d955c1c1a5b69ff43364630a130a1222fb6d06c"
},
{
"amount": "34960.394886",
"user": "0x93b478148FF792B00076B7EdC89Db1FdE7772079",
@@ -38608,8 +38552,8 @@
}
],
"total_tokens": "200000",
"withdrawn_tokens": "161559.866074",
"remaining_tokens": "38440.133926"
"withdrawn_tokens": "109216.685914",
"remaining_tokens": "90783.314086"
},
{
"address": "0xB523235B6c7C74DDB26b10E78bFb2d0Cb63Ae289",
@@ -38685,8 +38629,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "15870102.715470999700000001",
"total_removed": "793600.92623784996367452",
"locked_amount": "7811767.7238676202344110090429647253595566",
"total_removed": "589571.49512571875997952",
"locked_amount": "7855247.6731391336068375002475321149851311",
"deposits": [
{
"amount": "16249.93",
@@ -39290,46 +39234,6 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x16288057d0947efbbbc6ca61d6864ecfd4eb7949ddc1a934a05474ddbe453d4b"
},
{
"amount": "536.260884812357375",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x18cda39375506d544e7a7b9fa9137aa3887b2abac598b151502a2c4eb1835f37"
},
{
"amount": "19140.8654581272429",
"user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
"tx": "0xcfc7eefc60479d3e8470ea1c5d673a12e2417c9b9b3ebf4bf4137e8260fe07c8"
},
{
"amount": "43338.199512",
"user": "0x29f1856E73262fc4372BBF442EbB550919459308",
"tx": "0x666f2848ebb8b2f7c6d7829fbab733bce6aeb750b6c70a51753ad86321f87247"
},
{
"amount": "43325.172344",
"user": "0x21ff84851BdF79de9AA357E47856d58b2d825392",
"tx": "0xa13fae0c67f07b9eeaa65833f61e559672ba72a8c5b788ca83de99d95d1b2543"
},
{
"amount": "43329.582318",
"user": "0x1b956E6c00E238194B331eddEFF72Cb5f28A8d01",
"tx": "0x5eb1aba5b222162fbdec7d3e70bada62541fdef3914d25ba81e4fcb04a9d776b"
},
{
"amount": "43329.683698",
"user": "0x74b521F96c641FD59631Dc6a24c558ed39D64352",
"tx": "0x9050c6348f5ef78b2a6d6b0947dcf004a8b608434319e9e30d8d6495fa19dc42"
},
{
"amount": "10681.27524151227792",
"user": "0x4d982Ab0823fD2f48e934a7be2bb0a5374a26148",
"tx": "0x1bb20a86b93d4f463dfab637d48333322efa4562109547456c547a1f7141e324"
},
{
"amount": "348.3916556793255",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0x9c58d68fb547fef5c25e80d0685a9036fbfa5d61b558c2807c98e599659460a6"
},
{
"amount": "535.4042378778335",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -41177,18 +41081,6 @@
"tranche_id": 2,
"tx": "0x16288057d0947efbbbc6ca61d6864ecfd4eb7949ddc1a934a05474ddbe453d4b"
},
{
"amount": "536.260884812357375",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 2,
"tx": "0x18cda39375506d544e7a7b9fa9137aa3887b2abac598b151502a2c4eb1835f37"
},
{
"amount": "348.3916556793255",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 2,
"tx": "0x9c58d68fb547fef5c25e80d0685a9036fbfa5d61b558c2807c98e599659460a6"
},
{
"amount": "535.4042378778335",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@@ -42403,8 +42295,8 @@
}
],
"total_tokens": "259998.8875",
"withdrawn_tokens": "131772.63119677124875",
"remaining_tokens": "128226.25630322875125"
"withdrawn_tokens": "130887.978656279565875",
"remaining_tokens": "129110.908843720434125"
},
{
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
@@ -42522,12 +42414,6 @@
}
],
"withdrawals": [
{
"amount": "43325.172344",
"user": "0x21ff84851BdF79de9AA357E47856d58b2d825392",
"tranche_id": 2,
"tx": "0xa13fae0c67f07b9eeaa65833f61e559672ba72a8c5b788ca83de99d95d1b2543"
},
{
"amount": "30379.050924",
"user": "0x21ff84851BdF79de9AA357E47856d58b2d825392",
@@ -42542,8 +42428,8 @@
}
],
"total_tokens": "200000",
"withdrawn_tokens": "101182.629594",
"remaining_tokens": "98817.370406"
"withdrawn_tokens": "57857.45725",
"remaining_tokens": "142142.54275"
},
{
"address": "0x8DA3586FF7526E122093EE6dD86DFBf067ad8704",
@@ -42905,12 +42791,6 @@
}
],
"withdrawals": [
{
"amount": "10681.27524151227792",
"user": "0x4d982Ab0823fD2f48e934a7be2bb0a5374a26148",
"tranche_id": 2,
"tx": "0x1bb20a86b93d4f463dfab637d48333322efa4562109547456c547a1f7141e324"
},
{
"amount": "10964.26423788708204",
"user": "0x4d982Ab0823fD2f48e934a7be2bb0a5374a26148",
@@ -42925,8 +42805,8 @@
}
],
"total_tokens": "49294.676",
"withdrawn_tokens": "24940.14903303097784",
"remaining_tokens": "24354.52696696902216"
"withdrawn_tokens": "14258.87379151869992",
"remaining_tokens": "35035.80220848130008"
},
{
"address": "0x4092E429B149b5495265b608FD6Fae69fa5bfBe6",
@@ -42954,12 +42834,6 @@
}
],
"withdrawals": [
{
"amount": "43329.683698",
"user": "0x74b521F96c641FD59631Dc6a24c558ed39D64352",
"tranche_id": 2,
"tx": "0x9050c6348f5ef78b2a6d6b0947dcf004a8b608434319e9e30d8d6495fa19dc42"
},
{
"amount": "30570.627196",
"user": "0x74b521F96c641FD59631Dc6a24c558ed39D64352",
@@ -42980,8 +42854,8 @@
}
],
"total_tokens": "200000",
"withdrawn_tokens": "101186.22854",
"remaining_tokens": "98813.77146"
"withdrawn_tokens": "57856.544842",
"remaining_tokens": "142143.455158"
},
{
"address": "0x834b777E3aB758C84FeBbfb9d6BB675bc4B16915",
@@ -43344,12 +43218,6 @@
}
],
"withdrawals": [
{
"amount": "43329.582318",
"user": "0x1b956E6c00E238194B331eddEFF72Cb5f28A8d01",
"tranche_id": 2,
"tx": "0x5eb1aba5b222162fbdec7d3e70bada62541fdef3914d25ba81e4fcb04a9d776b"
},
{
"amount": "30374.150954",
"user": "0x1b956E6c00E238194B331eddEFF72Cb5f28A8d01",
@@ -43370,8 +43238,8 @@
}
],
"total_tokens": "200000",
"withdrawn_tokens": "101184.251654",
"remaining_tokens": "98815.748346"
"withdrawn_tokens": "57854.669336",
"remaining_tokens": "142145.330664"
},
{
"address": "0xA5d8726fFaD226e65D136ef9C2185750863b4850",
@@ -43504,12 +43372,6 @@
}
],
"withdrawals": [
{
"amount": "19140.8654581272429",
"user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
"tranche_id": 2,
"tx": "0xcfc7eefc60479d3e8470ea1c5d673a12e2417c9b9b3ebf4bf4137e8260fe07c8"
},
{
"amount": "13246.0770207423553",
"user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
@@ -43530,8 +43392,8 @@
}
],
"total_tokens": "87676.33",
"withdrawn_tokens": "44350.3417083452635",
"remaining_tokens": "43325.9882916547365"
"withdrawn_tokens": "25209.4762502180206",
"remaining_tokens": "62466.8537497819794"
},
{
"address": "0x9cF9B305601154C85ff86014d10a8762C802db0B",
@@ -43739,12 +43601,6 @@
}
],
"withdrawals": [
{
"amount": "43338.199512",
"user": "0x29f1856E73262fc4372BBF442EbB550919459308",
"tranche_id": 2,
"tx": "0x666f2848ebb8b2f7c6d7829fbab733bce6aeb750b6c70a51753ad86321f87247"
},
{
"amount": "30360.0931",
"user": "0x29f1856E73262fc4372BBF442EbB550919459308",
@@ -43765,8 +43621,8 @@
}
],
"total_tokens": "200000",
"withdrawn_tokens": "101179.892368",
"remaining_tokens": "98820.107632"
"withdrawn_tokens": "57841.692856",
"remaining_tokens": "142158.307144"
},
{
"address": "0x87D71adAbC11c35aF566eD51421eDA0c82828a3A",
@@ -44713,8 +44569,8 @@
"tranche_start": "2021-11-05T00:00:00.000Z",
"tranche_end": "2023-05-05T00:00:00.000Z",
"total_added": "14597706.0446472999",
"total_removed": "5732771.846810855311841256",
"locked_amount": "1490328.857776421955841927241714667",
"total_removed": "5581993.656033465744205406",
"locked_amount": "1530469.269321785094773221183308807",
"deposits": [
{
"amount": "129284.449",
@@ -44993,56 +44849,6 @@
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0xb499e0514e04e8acb67e4e8cc68ceaf57a018bbf844b006f7e77d1a3373ddfec"
},
{
"amount": "743.788992596092989",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0xe6310e8b181b7de346b3dacbdda2dfb8191938c1326eb3ccab3c390a1da3fc5d"
},
{
"amount": "8987.626998403452",
"user": "0xCe068b733CDB8D1455E72Ede39705E209251269f",
"tx": "0xa9c90284c90345a2895e81e8ef23db30f051ec6c6ef5183ca255fcaf22de4327"
},
{
"amount": "6912.633608920802",
"user": "0x97E5985117F47c8d110Be1c422DdCB9bE9b46e62",
"tx": "0xc1f747d9dbff23e28d6de87a8dbec2c56d46197429056310ea86a58c6d496951"
},
{
"amount": "11752.132634029515",
"user": "0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42",
"tx": "0x00d7d3b263bb030d6185e25b7f193be30c5393215377a9254b326438d7646e75"
},
{
"amount": "14517.473476800768",
"user": "0xe2E6F37cb1f1980418012BF69f43910d6Bc73e73",
"tx": "0xd9b50ce86b31b3f056eb0d3468968af34bc2baa1cea80abd23bb52f4fee3bbba"
},
{
"amount": "9677.727038032512",
"user": "0xd4632B682228Db5f38E2283869AEe8c29ee6Eec8",
"tx": "0x90d931bf82513dea5199db4e453ff157388063079569c50910df85790b16bb3b"
},
{
"amount": "10369.208041666186",
"user": "0x83BB032E371D7f18195037d85b3A1d459322C20c",
"tx": "0xfe06b188901c295532cd3e8701fcccee385405585f295b1e8fbdef1644803bef"
},
{
"amount": "6913.0876496568166456",
"user": "0x17d93ca9263fCaEADf29088b3aCa8C290d5423FB",
"tx": "0x455a8038de44fe4c2308c74f9512ce861c1153da4fc3deb4626ff5820757e92b"
},
{
"amount": "80421.5336580481619385",
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
"tx": "0x69930da3ef2f654a71946c49cacdd77c151bdf8f8ee18812eede5e3da511a901"
},
{
"amount": "482.97867923526106275",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x7dca129b4e009127a517d3951d7ca38068ea2c375608b22e3c087aa2ceabc40e"
},
{
"amount": "800.792718381487871",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@@ -48082,18 +47888,6 @@
"tranche_id": 3,
"tx": "0xb499e0514e04e8acb67e4e8cc68ceaf57a018bbf844b006f7e77d1a3373ddfec"
},
{
"amount": "743.788992596092989",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0xe6310e8b181b7de346b3dacbdda2dfb8191938c1326eb3ccab3c390a1da3fc5d"
},
{
"amount": "482.97867923526106275",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0x7dca129b4e009127a517d3951d7ca38068ea2c375608b22e3c087aa2ceabc40e"
},
{
"amount": "800.792718381487871",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@@ -50610,8 +50404,8 @@
}
],
"total_tokens": "359123.469575",
"withdrawn_tokens": "322117.44737479022324375",
"remaining_tokens": "37006.02220020977675625"
"withdrawn_tokens": "320890.679702958869192",
"remaining_tokens": "38232.789872041130808"
},
{
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
@@ -50841,12 +50635,6 @@
}
],
"withdrawals": [
{
"amount": "80421.5336580481619385",
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
"tranche_id": 3,
"tx": "0x69930da3ef2f654a71946c49cacdd77c151bdf8f8ee18812eede5e3da511a901"
},
{
"amount": "21866.26138234560055572",
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
@@ -51173,8 +50961,8 @@
}
],
"total_tokens": "1266324.603486",
"withdrawn_tokens": "1135136.99412579103610352",
"remaining_tokens": "131187.60936020896389648"
"withdrawn_tokens": "1054715.46046774287416502",
"remaining_tokens": "211609.14301825712583498"
},
{
"address": "0xC5d9221EB9c28A69859264c0A2Fe0d3272228296",
@@ -51639,12 +51427,6 @@
}
],
"withdrawals": [
{
"amount": "6912.633608920802",
"user": "0x97E5985117F47c8d110Be1c422DdCB9bE9b46e62",
"tranche_id": 3,
"tx": "0xc1f747d9dbff23e28d6de87a8dbec2c56d46197429056310ea86a58c6d496951"
},
{
"amount": "7096.654181850842",
"user": "0x97E5985117F47c8d110Be1c422DdCB9bE9b46e62",
@@ -51671,8 +51453,8 @@
}
],
"total_tokens": "31784.9",
"withdrawn_tokens": "28482.987343369846",
"remaining_tokens": "3301.912656630154"
"withdrawn_tokens": "21570.353734449044",
"remaining_tokens": "10214.546265550956"
},
{
"address": "0x17d93ca9263fCaEADf29088b3aCa8C290d5423FB",
@@ -51685,12 +51467,6 @@
}
],
"withdrawals": [
{
"amount": "6913.0876496568166456",
"user": "0x17d93ca9263fCaEADf29088b3aCa8C290d5423FB",
"tranche_id": 3,
"tx": "0x455a8038de44fe4c2308c74f9512ce861c1153da4fc3deb4626ff5820757e92b"
},
{
"amount": "7096.9655595642880472",
"user": "0x17d93ca9263fCaEADf29088b3aCa8C290d5423FB",
@@ -51717,8 +51493,8 @@
}
],
"total_tokens": "31786.09544",
"withdrawn_tokens": "28485.1258959784646008",
"remaining_tokens": "3300.9695440215353992"
"withdrawn_tokens": "21572.0382463216479552",
"remaining_tokens": "10214.0571936783520448"
},
{
"address": "0xbEb7f1B85626Fd9BdA69765d7abb3832C542A62E",
@@ -51746,12 +51522,6 @@
}
],
"withdrawals": [
{
"amount": "9677.727038032512",
"user": "0xd4632B682228Db5f38E2283869AEe8c29ee6Eec8",
"tranche_id": 3,
"tx": "0x90d931bf82513dea5199db4e453ff157388063079569c50910df85790b16bb3b"
},
{
"amount": "9935.44459047968",
"user": "0xd4632B682228Db5f38E2283869AEe8c29ee6Eec8",
@@ -51790,8 +51560,8 @@
}
],
"total_tokens": "44499.2",
"withdrawn_tokens": "39877.369881119552",
"remaining_tokens": "4621.830118880448"
"withdrawn_tokens": "30199.64284308704",
"remaining_tokens": "14299.55715691296"
},
{
"address": "0xe2E6F37cb1f1980418012BF69f43910d6Bc73e73",
@@ -51804,12 +51574,6 @@
}
],
"withdrawals": [
{
"amount": "14517.473476800768",
"user": "0xe2E6F37cb1f1980418012BF69f43910d6Bc73e73",
"tranche_id": 3,
"tx": "0xd9b50ce86b31b3f056eb0d3468968af34bc2baa1cea80abd23bb52f4fee3bbba"
},
{
"amount": "14902.31933949408",
"user": "0xe2E6F37cb1f1980418012BF69f43910d6Bc73e73",
@@ -51842,8 +51606,8 @@
}
],
"total_tokens": "66748.8",
"withdrawn_tokens": "59815.78315339584",
"remaining_tokens": "6933.01684660416"
"withdrawn_tokens": "45298.309676595072",
"remaining_tokens": "21450.490323404928"
},
{
"address": "0x83BB032E371D7f18195037d85b3A1d459322C20c",
@@ -51856,12 +51620,6 @@
}
],
"withdrawals": [
{
"amount": "10369.208041666186",
"user": "0x83BB032E371D7f18195037d85b3A1d459322C20c",
"tranche_id": 3,
"tx": "0xfe06b188901c295532cd3e8701fcccee385405585f295b1e8fbdef1644803bef"
},
{
"amount": "10645.268077994374",
"user": "0x83BB032E371D7f18195037d85b3A1d459322C20c",
@@ -51894,8 +51652,8 @@
}
],
"total_tokens": "47678.2",
"withdrawn_tokens": "42726.479785904542",
"remaining_tokens": "4951.720214095458"
"withdrawn_tokens": "32357.271744238356",
"remaining_tokens": "15320.928255761644"
},
{
"address": "0xCe068b733CDB8D1455E72Ede39705E209251269f",
@@ -51908,12 +51666,6 @@
}
],
"withdrawals": [
{
"amount": "8987.626998403452",
"user": "0xCe068b733CDB8D1455E72Ede39705E209251269f",
"tranche_id": 3,
"tx": "0xa9c90284c90345a2895e81e8ef23db30f051ec6c6ef5183ca255fcaf22de4327"
},
{
"amount": "9224.162860659198",
"user": "0xCe068b733CDB8D1455E72Ede39705E209251269f",
@@ -51940,8 +51692,8 @@
}
],
"total_tokens": "41320.2",
"withdrawn_tokens": "37027.447413995682",
"remaining_tokens": "4292.752586004318"
"withdrawn_tokens": "28039.82041559223",
"remaining_tokens": "13280.37958440777"
},
{
"address": "0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42",
@@ -51954,12 +51706,6 @@
}
],
"withdrawals": [
{
"amount": "11752.132634029515",
"user": "0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42",
"tranche_id": 3,
"tx": "0x00d7d3b263bb030d6185e25b7f193be30c5393215377a9254b326438d7646e75"
},
{
"amount": "12063.855243783915",
"user": "0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42",
@@ -51992,8 +51738,8 @@
}
],
"total_tokens": "54034.5",
"withdrawn_tokens": "48421.615684875225",
"remaining_tokens": "5612.884315124775"
"withdrawn_tokens": "36669.48305084571",
"remaining_tokens": "17365.01694915429"
}
]
},
@@ -52003,7 +51749,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "5778205.3912159303",
"total_removed": "3353757.81738108986999524",
"locked_amount": "271934.541601173425293253528574424",
"locked_amount": "287794.260969934471042521754104188",
"deposits": [
{
"amount": "552496.6455",
@@ -54098,7 +53844,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "472355.6199999996",
"total_removed": "35983.6942986130685",
"locked_amount": "112256.250734483009981796586808748",
"locked_amount": "114199.22063145092350782298427196",
"deposits": [
{
"amount": "3000",
@@ -83256,7 +83002,7 @@
"tranche_start": "2021-12-05T00:00:00.000Z",
"tranche_end": "2022-06-05T00:00:00.000Z",
"total_added": "171288.42",
"total_removed": "66803.5995794947989",
"total_removed": "66601.1049690697989",
"locked_amount": "0",
"deposits": [
{
@@ -87481,11 +87227,6 @@
}
],
"withdrawals": [
{
"amount": "202.494610425",
"user": "0x76bC9a132e27E9007c2adBfc92E65Bf0C5082B51",
"tx": "0x8ca9ede6297f539eafe855fe5f55aef4cb8ca66630779c385285a56e995e9997"
},
{
"amount": "225",
"user": "0x18CB827d620aF4Eb847C32737d60e36489d7ECb2",
@@ -90823,12 +90564,6 @@
}
],
"withdrawals": [
{
"amount": "202.494610425",
"user": "0x76bC9a132e27E9007c2adBfc92E65Bf0C5082B51",
"tranche_id": 6,
"tx": "0x8ca9ede6297f539eafe855fe5f55aef4cb8ca66630779c385285a56e995e9997"
},
{
"amount": "47.505389575",
"user": "0x76bC9a132e27E9007c2adBfc92E65Bf0C5082B51",
@@ -90837,8 +90572,8 @@
}
],
"total_tokens": "250",
"withdrawn_tokens": "250",
"remaining_tokens": "0"
"withdrawn_tokens": "47.505389575",
"remaining_tokens": "202.494610425"
},
{
"address": "0xb147d8B6804970f6fCb9EAc7f7Ec5A0aFCcFe5c2",
@@ -26,20 +26,20 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
it('market price', () => {
cy.getByTestId(marketTitle).contains('Market price').click();
validateMarketDataRow(0, 'Mark Price', '46,126.90058');
validateMarketDataRow(1, 'Best Bid Price', '44,126.90058 ');
validateMarketDataRow(2, 'Best Offer Price', '48,126.90058 ');
validateMarketDataRow(0, 'Mark Price', '0.05749');
validateMarketDataRow(1, 'Best Bid Price', '6.81765 ');
validateMarketDataRow(2, 'Best Offer Price', '6.81769 ');
validateMarketDataRow(3, 'Quote Unit', 'BTC');
});
it('market volume displayed', () => {
cy.getByTestId(marketTitle).contains('Market volume').click();
validateMarketDataRow(0, '24 Hour Volume', '1');
validateMarketDataRow(0, '24 Hour Volume', '-');
validateMarketDataRow(1, 'Open Interest', '0');
validateMarketDataRow(2, 'Best Bid Volume', '1');
validateMarketDataRow(3, 'Best Offer Volume', '3');
validateMarketDataRow(4, 'Best Static Bid Volume', '2');
validateMarketDataRow(5, 'Best Static Offer Volume', '4');
validateMarketDataRow(2, 'Best Bid Volume', '5');
validateMarketDataRow(3, 'Best Offer Volume', '1');
validateMarketDataRow(4, 'Best Static Bid Volume', '5');
validateMarketDataRow(5, 'Best Static Offer Volume', '1');
});
it('insurance pool displayed', () => {
@@ -149,9 +149,9 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
.contains(/Liquidity(?! m)/)
.click();
validateMarketDataRow(0, 'Target Stake', '10.00 tBTC');
validateMarketDataRow(1, 'Supplied Stake', '0.01 tBTC');
validateMarketDataRow(2, 'Market Value Proxy', '20.00 tBTC');
validateMarketDataRow(0, 'Target Stake', '0.56789 tBTC');
validateMarketDataRow(1, 'Supplied Stake', '0.56767 tBTC');
validateMarketDataRow(2, 'Market Value Proxy', '6.77678 tBTC');
cy.getByTestId('view-liquidity-link').should(
'have.text',
@@ -163,8 +163,8 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
cy.getByTestId(marketTitle).contains('Liquidity price range').click();
validateMarketDataRow(0, 'Liquidity Price Range', '2.00% of mid price');
validateMarketDataRow(1, 'Lowest Price', '45,204.362 BTC');
validateMarketDataRow(2, 'Highest Price', '47,049.438 BTC');
validateMarketDataRow(1, 'Lowest Price', '0.05634 BTC');
validateMarketDataRow(2, 'Highest Price', '0.05864 BTC');
});
it('oracle displayed', () => {
@@ -38,7 +38,7 @@ describe('accounts', { tags: '@smoke' }, () => {
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="deposited"]')
.should('have.text', '100,001.01');
.should('have.text', '1,001.00');
});
describe('sorting by ag-grid columns should work well', () => {
it('sorting by asset', () => {
@@ -58,24 +58,24 @@ describe('accounts', { tags: '@smoke' }, () => {
cy.getByTestId('Collateral').click();
const marketsSortedDefault = [
'1,000.00002',
'100,001.01',
'1,001.00',
'1,000.01',
'1,000.01',
'1,000.00',
'1,000.00001',
];
const marketsSortedAsc = [
'1,000.00',
'1,000.00001',
'1,000.00002',
'1,000.01',
'100,001.01',
'1,000.01',
'1,001.00',
];
const marketsSortedDesc = [
'100,001.01',
'1,001.00',
'1,000.01',
'1,000.01',
'1,000.00002',
'1,000.00001',
'1,000.00',
];
checkSorting(
'deposited',
@@ -87,9 +87,9 @@ describe('accounts', { tags: '@smoke' }, () => {
it('sorting by used', () => {
cy.getByTestId('Collateral').click();
const marketsSortedDefault = ['0.00', '1.01', '0.01', '0.00', '0.00'];
const marketsSortedAsc = ['0.00', '0.00', '0.00', '0.01', '1.01'];
const marketsSortedDesc = ['1.01', '0.01', '0.00', '0.00', '0.00'];
const marketsSortedDefault = ['0.00', '1.00', '0.01', '0.01', '0.00'];
const marketsSortedAsc = ['0.00', '0.00', '0.01', '0.01', '1.00'];
const marketsSortedDesc = ['1.00', '0.01', '0.01', '0.00', '0.00'];
checkSorting(
'used',
marketsSortedDefault,
@@ -102,24 +102,24 @@ describe('accounts', { tags: '@smoke' }, () => {
cy.getByTestId('Collateral').click();
const marketsSortedDefault = [
'1,000.00002',
'100,000.00',
'1,000.00',
'1,000.00',
'1,000.00',
'1,000.00001',
];
const marketsSortedAsc = [
'1,000.00',
'1,000.00',
'1,000.00',
'1,000.00001',
'1,000.00002',
'100,000.00',
];
const marketsSortedDesc = [
'100,000.00',
'1,000.00002',
'1,000.00001',
'1,000.00',
'1,000.00',
'1,000.00',
];
checkSorting(
@@ -2,11 +2,7 @@ import * as Schema from '@vegaprotocol/types';
import { aliasGQLQuery, mockConnectWallet } from '@vegaprotocol/cypress';
import { testOrderSubmission } from '../support/order-validation';
import type { OrderSubmission } from '@vegaprotocol/wallet';
import {
accountsQuery,
estimateOrderQuery,
amendGeneralAccountBalance,
} from '@vegaprotocol/mock';
import { accountsQuery, estimateOrderQuery } from '@vegaprotocol/mock';
import { createOrder } from '../support/create-order';
const orderSizeField = 'order-size';
@@ -587,10 +583,6 @@ describe('suspended market validation', { tags: '@regression' }, () => {
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY
);
const accounts = accountsQuery();
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Accounts', accounts);
});
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
@@ -640,10 +632,30 @@ describe('account validation', { tags: '@regression' }, () => {
beforeEach(() => {
cy.setVegaWallet();
cy.mockTradingPage();
const accounts = accountsQuery();
amendGeneralAccountBalance(accounts, 'market-0', '0');
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Accounts', accounts);
aliasGQLQuery(
req,
'Accounts',
accountsQuery({
party: {
accountsConnection: {
edges: [
{
node: {
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '0',
market: null,
asset: {
__typename: 'Asset',
id: 'asset-0',
},
},
},
],
},
},
})
);
});
cy.mockSubscription();
cy.visit('/#/markets/market-0');
@@ -667,13 +679,19 @@ describe('account validation', { tags: '@regression' }, () => {
beforeEach(() => {
cy.setVegaWallet();
cy.mockTradingPage();
const accounts = accountsQuery();
amendGeneralAccountBalance(accounts, 'market-0', '100000000');
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Accounts', accounts);
});
cy.mockGQL((req) => {
aliasGQLQuery(req, 'EstimateOrder', estimateOrderQuery());
aliasGQLQuery(
req,
'EstimateOrder',
estimateOrderQuery({
estimateOrder: {
marginLevels: {
__typename: 'MarginLevels',
initialLevel: '1000000000',
},
},
})
);
});
cy.mockSubscription();
cy.visit('/#/markets/market-0');
@@ -689,7 +707,7 @@ describe('account validation', { tags: '@regression' }, () => {
);
cy.getByTestId('dealticket-warning-margin').should(
'contain.text',
'You may not have enough margin available to open this position. 2,354.72283 tDAI is currently required. You have only 1,000.01 tDAI available.'
'9,999.99 tDAI is currently required. You have only 1,000.00 tDAI available.Deposit tDAI'
);
cy.getByTestId('deal-ticket-deposit-dialog-button').click();
cy.getByTestId('dialog-content')
@@ -31,7 +31,7 @@ describe('orders list', { tags: '@smoke' }, () => {
cy.visit('/#/markets/market-0');
cy.getByTestId('Orders').click();
cy.wait('@Orders').then(() => {
expect(subscriptionMocks.OrdersUpdate).to.be.calledThrice;
expect(subscriptionMocks.OrdersUpdate).to.be.calledTwice;
});
cy.wait('@Markets');
});
@@ -136,7 +136,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
cy.visit('/#/markets/market-0');
cy.getByTestId('Orders').click();
cy.wait('@Orders').then(() => {
expect(subscriptionMocks.OrdersUpdate).to.be.calledThrice;
expect(subscriptionMocks.OrdersUpdate).to.be.calledTwice;
});
});
const orderId = '1234567890';
@@ -354,7 +354,7 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
cy.visit('/#/markets/market-0');
cy.getByTestId('Orders').click();
cy.wait('@Orders').then(() => {
expect(subscriptionMocks.OrdersUpdate).to.be.calledThrice;
expect(subscriptionMocks.OrdersUpdate).to.be.calledTwice;
});
cy.mockVegaWalletTransaction();
});
@@ -164,10 +164,10 @@ describe('positions', { tags: '@smoke' }, () => {
cy.get('[col-id="liquidationPrice"]').should('contain.text', '0'); // liquidation price
cy.get('[col-id="currentLeverage"]').should('contain.text', '2.846.1');
cy.get('[col-id="currentLeverage"]').should('contain.text', '138.446.1');
cy.get('[col-id="marginAccountBalance"]') // margin allocated
.should('contain.text', '0.01');
.should('contain.text', '1,000');
cy.get('[col-id="unrealisedPNL"]').each(($unrealisedPnl) => {
cy.wrap($unrealisedPnl).invoke('text').should('not.be.empty');
@@ -17,13 +17,6 @@ describe('connect hosted wallet', { tags: '@smoke' }, () => {
});
it('can connect', () => {
// 0002-WCON-002
// 0002-WCON-003
// 0002-WCON-039
// 0002-WCON-017
// 0002-WCON-018
// 0002-WCON-019
// Mock authentication
cy.intercept('POST', 'https://wallet.testnet.vega.xyz/api/v1/auth/token', {
body: {
@@ -48,9 +41,6 @@ describe('connect hosted wallet', { tags: '@smoke' }, () => {
},
});
cy.getByTestId(connectVegaBtn).click();
cy.contains(
'Choose wallet app to connect, or to change port or server URL enter a custom wallet location first'
);
cy.contains('Connect Vega wallet');
cy.contains('Hosted Fairground wallet');
@@ -61,13 +51,9 @@ describe('connect hosted wallet', { tags: '@smoke' }, () => {
cy.getByTestId(form).find('#passphrase').click().type('pass');
cy.getByTestId('rest-connector-form').find('button[type=submit]').click();
cy.getByTestId(manageVegaBtn).should('exist');
cy.getByTestId('manage-vega-wallet').click();
cy.getByTestId('keypair-list').should('exist');
});
it('doesnt connect with invalid credentials', () => {
// 0002-WCON-020
// Mock incorrect username/password
cy.intercept('POST', 'https://wallet.testnet.vega.xyz/api/v1/auth/token', {
body: {
@@ -113,10 +99,6 @@ describe('connect vega wallet', { tags: '@smoke' }, () => {
});
it('can connect', () => {
// 0002-WCON-002
// 0002-WCON-005
// 0002-WCON-007
mockConnectWallet();
cy.getByTestId(connectVegaBtn).click();
cy.getByTestId('connectors-list')
@@ -128,40 +110,16 @@ describe('connect vega wallet', { tags: '@smoke' }, () => {
});
it('can change selected public key and disconnect', () => {
// 0002-WCON-022
// 0002-WCON-023
// 0002-WCON-025
// 0002-WCON-026
// 0002-WCON-021
// 0002-WCON-027
// 0002-WCON-030
// 0002-WCON-029
// 0002-WCON-008
// 0002-WCON-035
// 0002-WCON-014
// 0002-WCON-010
mockConnectWallet();
const key2 = Cypress.env('VEGA_PUBLIC_KEY2');
const truncatedKey2 = Cypress.env('TRUNCATED_VEGA_PUBLIC_KEY2');
cy.connectVegaWallet();
cy.getByTestId('manage-vega-wallet').click();
cy.getByTestId('keypair-list').should('exist');
cy.getByTestId(`key-${key2}`).should('contain.text', truncatedKey2);
cy.getByTestId(`key-${key2}`)
.find('[data-testid="copy-vega-public-key"]')
.should('be.visible');
cy.get(`[data-testid="key-${key2}"] > .mr-2`).click();
cy.getByTestId('keypair-list')
.find('[data-state="checked"]')
.should('be.visible');
cy.getByTestId('disconnect').click();
cy.getByTestId('connect-vega-wallet').should('exist');
cy.getByTestId('manage-vega-wallet').should('not.exist');
cy.getByTestId('connect-vega-wallet').click();
cy.contains(
'Choose wallet app to connect, or to change port or server URL enter a custom wallet location first'
);
});
});
@@ -76,9 +76,6 @@ describe(
cy.getByTestId(closeDialog).click();
cy.getByTestId('Trading').first().click();
cy.getByTestId(collateralTab).click();
cy.getByTestId(openTransferDialog).should('not.exist');
cy.getByTestId('Portfolio').eq(0).click();
cy.getByTestId(collateralTab).click();
cy.getByTestId(openTransferDialog).click();
cy.getByTestId(dialogTransferText).should(
'contain.text',
@@ -7,13 +7,13 @@ import type { onMessage } from '@vegaprotocol/cypress';
import type { PartialDeep } from 'type-fest';
import { orderUpdateSubscription } from '@vegaprotocol/mock';
const sendOrderUpdate: ((data: OrdersUpdateSubscription) => void)[] = [];
let sendOrderUpdate: (data: OrdersUpdateSubscription) => void;
const getOnOrderUpdate = () => {
const onOrderUpdate: onMessage<
OrdersUpdateSubscription,
OrdersUpdateSubscriptionVariables
> = (send) => {
sendOrderUpdate.push(send);
sendOrderUpdate = send;
};
return onOrderUpdate;
};
@@ -31,5 +31,5 @@ export function updateOrder(
if (!sendOrderUpdate) {
throw new Error('OrderSub not called');
}
sendOrderUpdate.forEach((send) => send(update));
sendOrderUpdate(update);
}
+18 -1
View File
@@ -28,6 +28,7 @@ import {
} from '@vegaprotocol/mock';
import type { PartialDeep } from 'type-fest';
import type { MarketDataQuery, MarketsQuery } from '@vegaprotocol/market-list';
import type { MarketInfoQuery } from '@vegaprotocol/market-info';
type MarketPageMockData = {
state: Schema.MarketState;
@@ -68,6 +69,18 @@ const marketsDataOverride = (
},
});
const marketInfoOverride = (
data: MarketPageMockData
): PartialDeep<MarketInfoQuery> => ({
market: {
state: data.state,
tradingMode: data.tradingMode,
data: {
trigger: data.trigger,
},
},
});
const mockTradingPage = (
req: CyHttpMessages.IncomingHttpRequest,
state: Schema.MarketState = Schema.MarketState.STATE_ACTIVE,
@@ -96,7 +109,11 @@ const mockTradingPage = (
aliasGQLQuery(req, 'Margins', marginsQuery());
aliasGQLQuery(req, 'Assets', assetsQuery());
aliasGQLQuery(req, 'Asset', assetQuery());
aliasGQLQuery(req, 'MarketInfo', marketInfoQuery());
aliasGQLQuery(
req,
'MarketInfo',
marketInfoQuery(marketInfoOverride({ state, tradingMode, trigger }))
);
aliasGQLQuery(req, 'Trades', tradesQuery());
aliasGQLQuery(req, 'Chart', chartQuery());
aliasGQLQuery(req, 'Candles', candlesQuery());
-1
View File
@@ -12,7 +12,6 @@ export const Home = () => {
// should be the oldest market that is currently trading in us mode(i.e. not in auction).
const { data, error, loading } = useDataProvider({
dataProvider: marketsWithDataProvider,
variables: undefined,
});
const update = useGlobalStore((store) => store.update);
const marketId = useGlobalStore((store) => store.marketId);
@@ -47,8 +47,7 @@ export const Liquidity = () => {
const useReloadLiquidityData = (marketId: string | undefined) => {
const { reload } = useDataProvider({
dataProvider: liquidityProvisionsDataProvider,
variables: { marketId: marketId || '' },
skip: !marketId,
variables: useMemo(() => ({ marketId }), [marketId]),
});
useEffect(() => {
const interval = setInterval(reload, 10000);
@@ -78,8 +77,7 @@ export const LiquidityContainer = ({
const { data, loading, error } = useDataProvider({
dataProvider: lpAggregatedDataProvider,
update,
variables: { marketId: marketId || '' },
skip: !marketId,
variables: useMemo(() => ({ marketId }), [marketId]),
});
const assetDecimalPlaces =
@@ -163,8 +161,7 @@ export const LiquidityViewContainer = ({
} = useDataProvider({
dataProvider: lpAggregatedDataProvider,
update,
variables: { marketId: marketId || '' },
skip: !marketId,
variables: useMemo(() => ({ marketId }), [marketId]),
});
const targetStake = marketData?.targetStake;
+9 -2
View File
@@ -7,6 +7,10 @@ import {
useThrottledDataProvider,
} from '@vegaprotocol/react-helpers';
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
import type {
MarketData,
MarketDataUpdateFieldsFragment,
} from '@vegaprotocol/market-list';
import { marketProvider, marketDataProvider } from '@vegaprotocol/market-list';
import { useGlobalStore, usePageTitleStore } from '../../stores';
@@ -31,10 +35,13 @@ const TitleUpdater = ({
}) => {
const pageTitle = usePageTitleStore((store) => store.pageTitle);
const updateTitle = usePageTitleStore((store) => store.updateTitle);
const { data: marketData } = useThrottledDataProvider(
const { data: marketData } = useThrottledDataProvider<
MarketData,
MarketDataUpdateFieldsFragment
>(
{
dataProvider: marketDataProvider,
variables: { marketId: marketId || '' },
variables: useMemo(() => ({ marketId }), [marketId]),
skip: !marketId,
},
1000
@@ -179,10 +179,7 @@ const MainGrid = ({
</Tab>
<Tab id="accounts" name={t('Collateral')}>
<VegaWalletContainer>
<TradingViews.Collateral
pinnedAsset={pinnedAsset}
hideButtons
/>
<TradingViews.Collateral pinnedAsset={pinnedAsset} />
</VegaWalletContainer>
</Tab>
</Tabs>
@@ -301,7 +301,7 @@ export const AccountHistoryChart = ({
asset: AssetFieldsFragment;
}) => {
const { theme } = useThemeSwitcher();
const values: { cols: [string, string]; rows: [Date, number][] } | null =
const values: { cols: string[]; rows: [Date, ...number[]][] } | null =
useMemo(() => {
if (!data?.balanceChanges.edges.length) {
return null;
@@ -49,10 +49,7 @@ export const Portfolio = () => {
</Tab>
<Tab id="positions" name={t('Positions')}>
<VegaWalletContainer>
<PositionsContainer
onMarketClick={onMarketClick}
noBottomPlaceholder
/>
<PositionsContainer onMarketClick={onMarketClick} />
</VegaWalletContainer>
</Tab>
<Tab id="orders" name={t('Orders')}>
@@ -8,14 +8,15 @@ import { useVegaWallet } from '@vegaprotocol/wallet';
import type { PinnedAsset } from '@vegaprotocol/accounts';
import { AccountManager, useTransferDialog } from '@vegaprotocol/accounts';
import { useDepositDialog } from '@vegaprotocol/deposits';
import { useParams } from 'react-router-dom';
export const AccountsContainer = ({
pinnedAsset,
hideButtons,
}: {
pinnedAsset?: PinnedAsset;
hideButtons?: boolean;
}) => {
const params = useParams();
const hideButtons = 'marketId' in params;
const { pubKey, isReadOnly } = useVegaWallet();
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
const openWithdrawalDialog = useWithdrawalDialog((store) => store.open);
@@ -48,7 +49,7 @@ export const AccountsContainer = ({
pinnedAsset={pinnedAsset}
/>
{!isReadOnly && !hideButtons && (
<div className="flex gap-2 justify-end p-2 px-[11px] absolute lg:fixed bottom-0 right-3 dark:bg-black/75 bg-white/75 rounded">
<div className="flex gap-2 justify-end p-2 px-[11px] fixed bottom-0 right-2 dark:bg-black/75 bg-white/75 rounded">
<Button
variant="primary"
size="sm"
+1 -1
View File
@@ -14,7 +14,7 @@ export const Footer = () => {
const { blockDiff, datanodeBlockHeight } = useNodeHealth();
return (
<footer className="px-4 py-1 text-xs border-t border-default text-vega-light-300 dark:text-vega-dark-300 lg:fixed bottom-0 left-0 border-r bg-white dark:bg-black">
<footer className="px-4 py-1 text-xs border-t border-default text-vega-light-300 dark:text-vega-dark-300 fixed bottom-0 left-0 border-r bg-white dark:bg-black">
{/* Pull left to align with top nav, due to button padding */}
<div className="-ml-2">
{VEGA_URL && (
@@ -1,4 +1,5 @@
import type { RefObject } from 'react';
import { useMemo } from 'react';
import { useInView } from 'react-intersection-observer';
import { isNumeric } from '@vegaprotocol/utils';
import {
@@ -8,6 +9,7 @@ import {
import { PriceChangeCell } from '@vegaprotocol/datagrid';
import * as Schema from '@vegaprotocol/types';
import type { CandleClose } from '@vegaprotocol/types';
import type { Candle } from '@vegaprotocol/market-list';
import { marketCandlesProvider } from '@vegaprotocol/market-list';
import { THROTTLE_UPDATE_TIME } from '../constants';
@@ -28,14 +30,19 @@ export const Last24hPriceChange = ({
}: Props) => {
const [ref, inView] = useInView({ root: inViewRoot?.current });
const yesterday = useYesterday();
const { data, error } = useThrottledDataProvider(
const variables = useMemo(
() => ({
marketId: marketId,
interval: Schema.Interval.INTERVAL_I1H,
since: new Date(yesterday).toISOString(),
}),
[marketId, yesterday]
);
const { data, error } = useThrottledDataProvider<Candle[], Candle>(
{
dataProvider: marketCandlesProvider,
variables: {
marketId: marketId || '',
interval: Schema.Interval.INTERVAL_I1H,
since: new Date(yesterday).toISOString(),
},
variables,
skip: !marketId || !inView,
},
THROTTLE_UPDATE_TIME
@@ -10,6 +10,8 @@ import {
useYesterday,
} from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types';
import { useMemo } from 'react';
import type { Candle } from '@vegaprotocol/market-list';
import { THROTTLE_UPDATE_TIME } from '../constants';
interface Props {
@@ -30,14 +32,19 @@ export const Last24hVolume = ({
const yesterday = useYesterday();
const [ref, inView] = useInView({ root: inViewRoot?.current });
const { data } = useThrottledDataProvider(
const variables = useMemo(
() => ({
marketId: marketId,
interval: Schema.Interval.INTERVAL_I1H,
since: new Date(yesterday).toISOString(),
}),
[marketId, yesterday]
);
const { data } = useThrottledDataProvider<Candle[], Candle>(
{
dataProvider: marketCandlesProvider,
variables: {
marketId: marketId || '',
interval: Schema.Interval.INTERVAL_I1H,
since: new Date(yesterday).toISOString(),
},
variables,
skip: !(inView && marketId),
},
THROTTLE_UPDATE_TIME
@@ -4,7 +4,10 @@ import {
useDataProvider,
useNetworkParams,
} from '@vegaprotocol/react-helpers';
import type { MarketData } from '@vegaprotocol/market-list';
import type {
MarketData,
MarketDataUpdateFieldsFragment,
} from '@vegaprotocol/market-list';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import { HeaderStat } from '../header';
import {
@@ -67,7 +70,7 @@ export const MarketLiquiditySupplied = ({
[noUpdate]
);
useDataProvider({
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
dataProvider: marketDataProvider,
update,
variables,
@@ -1,8 +1,13 @@
import type { RefObject } from 'react';
import { useMemo } from 'react';
import { useInView } from 'react-intersection-observer';
import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils';
import { useThrottledDataProvider } from '@vegaprotocol/react-helpers';
import { PriceCell } from '@vegaprotocol/datagrid';
import type {
MarketData,
MarketDataUpdateFieldsFragment,
} from '@vegaprotocol/market-list';
import { marketDataProvider } from '@vegaprotocol/market-list';
import { THROTTLE_UPDATE_TIME } from '../constants';
@@ -22,10 +27,15 @@ export const MarketMarkPrice = ({
asPriceCell,
}: Props) => {
const [ref, inView] = useInView({ root: inViewRoot?.current });
const { data } = useThrottledDataProvider(
const variables = useMemo(() => ({ marketId }), [marketId]);
const { data } = useThrottledDataProvider<
MarketData,
MarketDataUpdateFieldsFragment
>(
{
dataProvider: marketDataProvider,
variables: { marketId: marketId || '' },
variables,
skip: !inView,
},
THROTTLE_UPDATE_TIME
@@ -1,11 +1,15 @@
import throttle from 'lodash/throttle';
import type { MarketData, Market } from '@vegaprotocol/market-list';
import type {
MarketData,
MarketDataUpdateFieldsFragment,
Market,
} from '@vegaprotocol/market-list';
import { marketDataProvider } from '@vegaprotocol/market-list';
import { t } from '@vegaprotocol/i18n';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types';
import { HeaderStat } from '../header';
import { useCallback, useRef, useState } from 'react';
import { useCallback, useMemo, useRef, useState } from 'react';
import * as constants from '../constants';
export const MarketState = ({ market }: { market: Market | null }) => {
@@ -29,10 +33,14 @@ export const MarketState = ({ market }: { market: Market | null }) => {
[throttledSetMarketState]
);
useDataProvider({
const variables = useMemo(
() => ({ marketId: market?.id || '' }),
[market?.id]
);
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
dataProvider: marketDataProvider,
update,
variables: { marketId: market?.id || '' },
variables,
skip: !market?.id,
});
@@ -1,16 +1,24 @@
import { useCallback, useRef, useState } from 'react';
import { useCallback, useMemo, useRef, useState } from 'react';
import throttle from 'lodash/throttle';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import type { MarketData } from '@vegaprotocol/market-list';
import type {
MarketData,
MarketDataUpdateFieldsFragment,
} from '@vegaprotocol/market-list';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import { HeaderStat } from '../header';
import * as constants from '../constants';
export const MarketVolume = ({ marketId }: { marketId: string }) => {
const [marketVolume, setMarketVolume] = useState<string>('-');
const variables = { marketId };
const variables = useMemo(
() => ({
marketId: marketId,
}),
[marketId]
);
const { data } = useDataProvider({
dataProvider: marketProvider,
variables,
@@ -38,7 +46,7 @@ export const MarketVolume = ({ marketId }: { marketId: string }) => {
[data?.positionDecimalPlaces, throttledSetMarketVolume]
);
useDataProvider({
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
dataProvider: marketDataProvider,
update,
variables,
@@ -106,13 +106,14 @@ export const SelectMarketPopover = ({
loading: marketsLoading,
reload: marketListReload,
} = useMarketList();
const variables = useMemo(() => ({ partyId: pubKey }), [pubKey]);
const {
data: positions,
loading: positionsLoading,
reload,
} = useDataProvider({
dataProvider: positionsDataProvider,
variables: { partyId: pubKey || '' },
variables,
skip: !pubKey,
});
const onSelectMarket = useCallback(
@@ -20,7 +20,6 @@ export const WelcomeDialog = () => {
const [riskAccepted] = useLocalStorage(constants.RISK_ACCEPTED_KEY);
const { data } = useDataProvider({
dataProvider: activeMarketsProvider,
variables: undefined,
});
const { update, shouldDisplayWelcomeDialog } = useGlobalStore((store) => ({
-15
View File
@@ -34,18 +34,6 @@ html [data-theme='dark'] {
/* sell candles only use stroke as the candle is solid (without border) */
--pennant-color-sell-stroke: theme('colors.vega.pink.500');
/* studies */
--pennant-color-eldar-ray-bear-power: theme('colors.vega.pink.500');
--pennant-color-eldar-ray-bull-power: theme('colors.vega.green.650');
--pennant-color-macd-divergence-buy: theme('colors.vega.green.650');
--pennant-color-macd-divergence-sell: theme('colors.vega.pink.500');
--pennant-color-macd-signal: theme('colors.vega.blue.500');
--pennant-color-macd-macd: theme('colors.vega.yellow.500');
--pennant-color-volume-buy: theme('colors.vega.green.650');
--pennant-color-volume-sell: theme('colors.vega.pink.500');
/* depth chart */
--pennant-color-depth-buy-fill: theme('colors.vega.green.650');
--pennant-color-depth-buy-stroke: theme('colors.vega.green.500');
@@ -62,9 +50,6 @@ html [data-theme='light'] {
/* sell candles only use stroke as the candle is solid (without border) */
--pennant-color-sell-stroke: theme('colors.vega.pink.400');
--pennant-color-volume-buy: theme('colors.vega.green.400');
--pennant-color-volume-sell: theme('colors.vega.pink.500');
/* depth chart */
--pennant-color-depth-buy-fill: theme('colors.vega.green.400');
--pennant-color-depth-buy-stroke: theme('colors.vega.green.550');
+1 -1
View File
@@ -15,7 +15,7 @@ interface PageTitleStore {
updateTitle: (title: string) => void;
}
export const useGlobalStore = create<GlobalStore>((set) => ({
export const useGlobalStore = create<GlobalStore>()((set) => ({
nodeSwitcherDialog: false,
marketId: LocalStorage.getItem('marketId') || null,
shouldDisplayWelcomeDialog: false,
@@ -18,7 +18,6 @@ import type {
AccountFieldsFragment,
AccountsQuery,
AccountEventsSubscription,
AccountsQueryVariables,
} from './__generated__/Accounts';
import type { Market } from '@vegaprotocol/market-list';
import type { Asset } from '@vegaprotocol/assets';
@@ -86,8 +85,7 @@ export const accountsOnlyDataProvider = makeDataProvider<
AccountsQuery,
AccountFieldsFragment[],
AccountEventsSubscription,
AccountEventsSubscription['accounts'],
AccountsQueryVariables
AccountEventsSubscription['accounts']
>({
query: AccountsDocument,
subscriptionQuery: AccountEventsDocument,
@@ -161,16 +159,8 @@ const getAssetAccountAggregation = (
return { ...balanceAccount, breakdown };
};
export const accountsDataProvider = makeDerivedDataProvider<
Account[],
never,
AccountsQueryVariables
>(
[
accountsOnlyDataProvider,
(callback, client) => marketsProvider(callback, client, undefined),
(callback, client) => assetsProvider(callback, client, undefined),
],
export const accountsDataProvider = makeDerivedDataProvider<Account[], never>(
[accountsOnlyDataProvider, marketsProvider, assetsProvider],
([accounts, markets, assets]): Account[] | null => {
return accounts
? accounts
@@ -204,8 +194,7 @@ export const accountsDataProvider = makeDerivedDataProvider<
export const aggregatedAccountsDataProvider = makeDerivedDataProvider<
AccountFields[],
never,
AccountsQueryVariables
never
>(
[accountsDataProvider],
(parts) => parts[0] && getAccountData(parts[0] as Account[])
+4 -1
View File
@@ -31,7 +31,10 @@ export const AccountManager = ({
}: AccountManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null);
const variables = useMemo(() => ({ partyId }), [partyId]);
const { data, loading, error, reload } = useDataProvider({
const { data, loading, error, reload } = useDataProvider<
AccountFields[],
never
>({
dataProvider: aggregatedAccountsDataProvider,
variables,
});
+13 -35
View File
@@ -1,14 +1,9 @@
import { forwardRef, useMemo, useState } from 'react';
import {
addDecimalsFormatNumber,
isNumeric,
toBigNum,
} from '@vegaprotocol/utils';
import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import type {
VegaICellRendererParams,
VegaValueFormatterParams,
VegaValueGetterParams,
} from '@vegaprotocol/datagrid';
import { Button, ButtonLink, Dialog } from '@vegaprotocol/ui-toolkit';
import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
@@ -122,23 +117,17 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
headerTooltip={t(
'This is the total amount of collateral used plus the amount available in your general account.'
)}
valueGetter={({
data,
}: VegaValueGetterParams<AccountFields, 'deposited'>) => {
return !data?.deposited
? undefined
: toBigNum(data.deposited, data.asset.decimals).toNumber();
}}
maxWidth={300}
cellRenderer={({
data,
value,
node,
}: VegaICellRendererParams<AccountFields, 'deposited'>) => {
const valueFormatted =
data &&
data.asset &&
isNumeric(data.deposited) &&
addDecimalsFormatNumber(data.deposited, data.asset.decimals);
isNumeric(value) &&
addDecimalsFormatNumber(value, data.asset.decimals);
return node.rowPinned ? (
<CenteredGridCellWrapper className="h-[30px] justify-end">
{valueFormatted}
@@ -155,23 +144,17 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
headerTooltip={t(
'This is the amount of collateral used from your general account.'
)}
valueGetter={({
data,
}: VegaValueGetterParams<AccountFields, 'used'>) => {
return !data?.used
? undefined
: toBigNum(data.used, data.asset.decimals).toNumber();
}}
maxWidth={300}
cellRenderer={({
data,
value,
node,
}: VegaICellRendererParams<AccountFields, 'used'>) => {
const valueFormatted =
data &&
data.asset &&
isNumeric(data.used) &&
addDecimalsFormatNumber(data.used, data.asset.decimals);
isNumeric(value) &&
addDecimalsFormatNumber(value, data.asset.decimals);
return node.rowPinned ? (
<CenteredGridCellWrapper className="h-[30px] justify-end">
{valueFormatted}
@@ -188,31 +171,26 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
headerTooltip={t(
'This is the amount of collateral available in your general account.'
)}
valueGetter={({
data,
}: VegaValueGetterParams<AccountFields, 'available'>) => {
return !data?.available
? undefined
: toBigNum(data.available, data.asset.decimals).toNumber();
}}
valueFormatter={({
value,
data,
}: VegaValueFormatterParams<AccountFields, 'available'>) =>
data &&
data.asset &&
isNumeric(data.available) &&
addDecimalsFormatNumber(data.available, data.asset.decimals)
isNumeric(value) &&
addDecimalsFormatNumber(value, data.asset.decimals)
}
maxWidth={300}
cellRenderer={({
data,
value,
node,
}: VegaICellRendererParams<AccountFields, 'available'>) => {
const valueFormatted =
data &&
data.asset &&
isNumeric(data.available) &&
addDecimalsFormatNumber(data.available, data.asset.decimals);
isNumeric(value) &&
addDecimalsFormatNumber(value, data.asset.decimals);
return node.rowPinned ? (
<CenteredGridCellWrapper className="h-[30px] justify-end">
{valueFormatted}
+6 -24
View File
@@ -43,6 +43,10 @@ export const accountFields: AccountFieldsFragment[] = [
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '100000000',
market: {
id: 'market-0',
__typename: 'Market',
},
asset: {
__typename: 'Asset',
id: 'asset-id-2',
@@ -71,7 +75,7 @@ export const accountFields: AccountFieldsFragment[] = [
},
asset: {
__typename: 'Asset',
id: 'asset-0',
id: 'asset-id-2',
},
},
{
@@ -90,7 +94,7 @@ export const accountFields: AccountFieldsFragment[] = [
{
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '10000000000',
balance: '100000000',
market: null,
asset: {
__typename: 'Asset',
@@ -137,25 +141,3 @@ export const accountEventsSubscription = (
};
return merge(defaultResult, override);
};
export const amendGeneralAccountBalance = (
accounts: AccountsQuery,
marketId: string,
balance: string
) => {
if (accounts.party?.accountsConnection?.edges) {
const marginAccount = accounts.party.accountsConnection.edges.find(
(edge) => edge?.node.market?.id === marketId
);
if (marginAccount) {
const generalAccount = accounts.party.accountsConnection.edges.find(
(edge) =>
edge?.node.asset.id === marginAccount.node.asset.id &&
!edge?.node.market
);
if (generalAccount) {
generalAccount.node.balance = balance;
}
}
}
};
+1 -1
View File
@@ -20,7 +20,7 @@ export const TransferContainer = () => {
const { param } = useNetworkParam(NetworkParams.transfer_fee_factor);
const { data } = useDataProvider({
dataProvider: accountsDataProvider,
variables: { partyId: pubKey || '' },
variables: { partyId: pubKey },
skip: !pubKey,
});
const create = useVegaTransactionStore((store) => store.create);
+1 -1
View File
@@ -11,7 +11,7 @@ interface Actions {
open: (open?: boolean) => void;
}
export const useTransferDialog = create<State & Actions>((set) => ({
export const useTransferDialog = create<State & Actions>()((set) => ({
isOpen: false,
open: (open = true) => {
set(() => ({ isOpen: open }));
+1 -1
View File
@@ -9,4 +9,4 @@ type HeaderStore = {
[url: string]: HeaderEntry | undefined;
};
export const useHeaderStore = create<HeaderStore>(() => ({}));
export const useHeaderStore = create<HeaderStore>()(() => ({}));
+10 -13
View File
@@ -1,11 +1,8 @@
import { makeDataProvider } from '@vegaprotocol/utils';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { useMemo } from 'react';
import type {
AssetQuery,
AssetFieldsFragment,
AssetQueryVariables,
} from './__generated__/Asset';
import type { AssetQuery, AssetFieldsFragment } from './__generated__/Asset';
import { AssetDocument } from './__generated__/Asset';
export type Asset = AssetFieldsFragment;
@@ -18,21 +15,21 @@ export const getData = (responseData: AssetQuery | null | undefined) => {
return null;
};
export const assetProvider = makeDataProvider<
AssetQuery,
Asset,
never,
never,
AssetQueryVariables
>({
export const assetProvider = makeDataProvider<AssetQuery, Asset, never, never>({
query: AssetDocument,
getData,
});
export const useAssetDataProvider = (assetId: string) => {
const variables = useMemo(
() => ({
assetId,
}),
[assetId]
);
return useDataProvider({
dataProvider: assetProvider,
variables: { assetId: assetId || '' },
variables,
skip: !assetId,
});
};
+1 -1
View File
@@ -20,7 +20,7 @@ export type AssetDetailsDialogStore = {
open: (id: string, trigger?: HTMLElement | null, asJson?: boolean) => void;
};
export const useAssetDetailsDialogStore = create<AssetDetailsDialogStore>(
export const useAssetDetailsDialogStore = create<AssetDetailsDialogStore>()(
(set) => ({
isOpen: false,
id: '',
@@ -40,5 +40,4 @@ export const enabledAssetsProvider = makeDerivedDataProvider<
export const useAssetsDataProvider = () =>
useDataProvider({
dataProvider: assetsProvider,
variables: undefined,
});
+2 -2
View File
@@ -1,6 +1,6 @@
import 'pennant/dist/style.css';
import {
CandlestickChart,
Chart,
ChartType,
Interval,
Overlay,
@@ -161,7 +161,7 @@ export const CandlesChartContainer = ({
</DropdownMenu>
</div>
<div className="flex-1">
<CandlestickChart
<Chart
dataSource={dataSource}
options={{
chartType: chartType,
@@ -1,4 +1,4 @@
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { formatNumber } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { Notification, Intent } from '@vegaprotocol/ui-toolkit';
import { useDepositDialog } from '@vegaprotocol/deposits';
@@ -19,14 +19,14 @@ export const MarginWarning = ({ margin, balance, asset }: Props) => {
<Notification
intent={Intent.Warning}
testId="dealticket-warning-margin"
message={`You may not have enough margin available to open this position. ${addDecimalsFormatNumber(
message={`You may not have enough margin available to open this position. ${formatNumber(
margin,
asset.decimals
)} ${asset.symbol} ${t(
'is currently required. You have only'
)} ${addDecimalsFormatNumber(balance, asset.decimals)} ${
asset.symbol
} ${t('available.')}`}
)} ${formatNumber(balance, asset.decimals)} ${asset.symbol} ${t(
'available.'
)}`}
buttonProps={{
text: t(`Deposit ${asset.symbol}`),
action: () => openDepositDialog(asset.id),
@@ -1,3 +1,4 @@
import { useMemo } from 'react';
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { useThrottledDataProvider } from '@vegaprotocol/react-helpers';
@@ -28,7 +29,7 @@ export const DealTicketContainer = ({
} = useThrottledDataProvider(
{
dataProvider: marketDataProvider,
variables: { marketId },
variables: useMemo(() => ({ marketId }), [marketId]),
},
1000
);
@@ -1,5 +1,6 @@
import { Tooltip } from '@vegaprotocol/ui-toolkit';
import type { ReactNode } from 'react';
import { useMemo } from 'react';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import type { Market, MarketData } from '@vegaprotocol/market-list';
import {
@@ -11,51 +12,22 @@ interface DealTicketFeeDetailsProps {
order: OrderSubmissionBody['orderSubmission'];
market: Market;
marketData: MarketData;
margin: string;
totalMargin: string;
balance: string;
}
export interface DealTicketFeeDetailProps {
export interface DealTicketFeeDetails {
label: string;
value?: string | number | null;
labelDescription?: string | ReactNode;
symbol?: string;
}
export const DealTicketFeeDetail = ({
label,
value,
labelDescription,
symbol,
}: DealTicketFeeDetailProps) => (
<div className="text-xs mt-2 flex justify-between items-center gap-4 flex-wrap">
<div>
<Tooltip description={labelDescription}>
<div>{label}</div>
</Tooltip>
</div>
<div className="text-neutral-500 dark:text-neutral-300">{`${value ?? '-'} ${
symbol || ''
}`}</div>
</div>
);
export const DealTicketFeeDetails = ({
order,
market,
marketData,
margin,
totalMargin,
balance,
}: DealTicketFeeDetailsProps) => {
const feeDetails = useFeeDealTicketDetails(order, market, marketData);
const details = getFeeDetailsValues({
...feeDetails,
margin,
totalMargin,
balance,
});
const details = useMemo(() => getFeeDetailsValues(feeDetails), [feeDetails]);
return (
<div>
{details.map(({ label, value, labelDescription, symbol }) => (
@@ -21,7 +21,8 @@ import {
Intent,
Notification,
} from '@vegaprotocol/ui-toolkit';
import { useOrderMarginValidation } from '../../hooks/use-order-margin-validation';
import { MarginWarning } from '../deal-ticket-validation/margin-warning';
import {
validateExpiration,
validateMarketState,
@@ -31,16 +32,11 @@ import {
} from '../../utils';
import { ZeroBalanceError } from '../deal-ticket-validation/zero-balance-error';
import { SummaryValidationType } from '../../constants';
import { useInitialMargin } from '../../hooks/use-initial-margin';
import { useHasNoBalance } from '../../hooks/use-has-no-balance';
import type { Market, MarketData } from '@vegaprotocol/market-list';
import { MarginWarning } from '../deal-ticket-validation/margin-warning';
import {
useMarketAccountBalance,
useAccountBalance,
} from '@vegaprotocol/accounts';
import { OrderTimeInForce, OrderType } from '@vegaprotocol/types';
import { useOrderForm } from '../../hooks/use-order-form';
import type { OrderObj } from '@vegaprotocol/orders';
export interface DealTicketProps {
market: Market;
@@ -58,12 +54,10 @@ export const DealTicket = ({
const { pubKey, isReadOnly } = useVegaWallet();
// store last used tif for market so that when changing OrderType the previous TIF
// selection for that type is used when switching back
const [lastTIF, setLastTIF] = useState({
[OrderType.TYPE_MARKET]: OrderTimeInForce.TIME_IN_FORCE_IOC,
[OrderType.TYPE_LIMIT]: OrderTimeInForce.TIME_IN_FORCE_GTC,
});
const {
control,
errors,
@@ -73,41 +67,20 @@ export const DealTicket = ({
update,
handleSubmit,
} = useOrderForm(market.id);
const asset = market.tradableInstrument.instrument.product.settlementAsset;
const { accountBalance: marginAccountBalance } = useMarketAccountBalance(
market.id
const marketStateError = validateMarketState(marketData.marketState);
const hasNoBalance = useHasNoBalance(
market.tradableInstrument.instrument.product.settlementAsset.id
);
const marketTradingModeError = validateMarketTradingMode(
marketData.marketTradingMode
);
const { accountBalance: generalAccountBalance } = useAccountBalance(asset.id);
const balance = (
BigInt(marginAccountBalance) + BigInt(generalAccountBalance)
).toString();
const { marketState, marketTradingMode } = marketData;
const normalizedOrder =
order &&
normalizeOrderSubmission(
order,
market.decimalPlaces,
market.positionDecimalPlaces
);
const { margin, totalMargin } = useInitialMargin(market.id, normalizedOrder);
useEffect(() => {
const checkForErrors = useCallback(() => {
if (!pubKey) {
setError('summary', {
message: t('No public key selected'),
type: SummaryValidationType.NoPubKey,
});
setError('summary', { message: t('No public key selected') });
return;
}
const marketStateError = validateMarketState(marketState);
if (marketStateError !== true) {
setError('summary', {
message: marketStateError,
@@ -116,7 +89,6 @@ export const DealTicket = ({
return;
}
const hasNoBalance = generalAccountBalance === '0';
if (hasNoBalance) {
setError('summary', {
message: SummaryValidationType.NoCollateral,
@@ -125,7 +97,6 @@ export const DealTicket = ({
return;
}
const marketTradingModeError = validateMarketTradingMode(marketTradingMode);
if (marketTradingModeError !== true) {
setError('summary', {
message: marketTradingModeError,
@@ -133,19 +104,39 @@ export const DealTicket = ({
});
return;
}
clearErrors('summary');
}, [
marketState,
marketTradingMode,
generalAccountBalance,
hasNoBalance,
marketStateError,
marketTradingModeError,
pubKey,
setError,
]);
useEffect(() => {
if (
(!hasNoBalance &&
errors.summary?.type === SummaryValidationType.NoCollateral) ||
(marketStateError === true &&
errors.summary?.type === SummaryValidationType.MarketState) ||
(marketTradingModeError === true &&
errors.summary?.type === SummaryValidationType.TradingMode)
) {
clearErrors('summary');
}
checkForErrors();
}, [
hasNoBalance,
marketStateError,
marketTradingModeError,
clearErrors,
errors.summary,
errors.summary?.message,
errors.summary?.type,
checkForErrors,
]);
const onSubmit = useCallback(
(order: OrderSubmission) => {
checkForErrors();
submit(
normalizeOrderSubmission(
order,
@@ -154,11 +145,11 @@ export const DealTicket = ({
)
);
},
[submit, market.decimalPlaces, market.positionDecimalPlaces]
[checkForErrors, submit, market.decimalPlaces, market.positionDecimalPlaces]
);
// if an order doesn't exist one will be created by the store immediately
if (!order || !normalizedOrder) return null;
if (!order) return null;
return (
<form
@@ -263,10 +254,9 @@ export const DealTicket = ({
)}
<SummaryMessage
errorMessage={errors.summary?.message}
asset={asset}
marketTradingMode={marketData.marketTradingMode}
balance={balance}
margin={totalMargin}
market={market}
marketData={marketData}
order={order}
isReadOnly={isReadOnly}
pubKey={pubKey}
onClickCollateral={onClickCollateral}
@@ -276,12 +266,9 @@ export const DealTicket = ({
variant={order.side === Schema.Side.SIDE_BUY ? 'ternary' : 'secondary'}
/>
<DealTicketFeeDetails
order={normalizedOrder}
order={order}
market={market}
marketData={marketData}
margin={margin}
totalMargin={totalMargin}
balance={marginAccountBalance}
/>
</form>
);
@@ -293,10 +280,9 @@ export const DealTicket = ({
*/
interface SummaryMessageProps {
errorMessage?: string;
asset: { id: string; symbol: string; name: string; decimals: number };
marketTradingMode: MarketData['marketTradingMode'];
balance: string;
margin: string;
market: Market;
marketData: MarketData;
order: OrderObj;
isReadOnly: boolean;
pubKey: string | null;
onClickCollateral?: () => void;
@@ -304,17 +290,22 @@ interface SummaryMessageProps {
const SummaryMessage = memo(
({
errorMessage,
asset,
marketTradingMode,
balance,
margin,
market,
marketData,
order,
isReadOnly,
pubKey,
onClickCollateral,
}: SummaryMessageProps) => {
// Specific error UI for if balance is so we can
// render a deposit dialog
const asset = market.tradableInstrument.instrument.product.settlementAsset;
const assetSymbol = asset.symbol;
const { balanceError, balance, margin } = useOrderMarginValidation({
market,
marketData,
order,
});
const openVegaWalletDialog = useVegaWalletDialogStore(
(store) => store.openVegaWalletDialog
);
@@ -358,7 +349,7 @@ const SummaryMessage = memo(
return (
<div className="mb-2">
<ZeroBalanceError
asset={asset}
asset={market.tradableInstrument.instrument.product.settlementAsset}
onClickCollateral={onClickCollateral}
/>
</div>
@@ -379,16 +370,21 @@ const SummaryMessage = memo(
// If there is no blocking error but user doesn't have enough
// balance render the margin warning, but still allow submission
if (BigInt(balance) < BigInt(margin)) {
return <MarginWarning balance={balance} margin={margin} asset={asset} />;
if (balanceError) {
return (
<div className="mb-2">
<MarginWarning balance={balance} margin={margin} asset={asset} />
</div>
);
}
// Show auction mode warning
if (
[
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
].includes(marketTradingMode)
].includes(marketData.marketTradingMode)
) {
return (
<div className="mb-2">
@@ -55,7 +55,6 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
const { data, loading, error } = useDataProvider({
dataProvider: marketsProvider,
variables: undefined,
skipUpdates: true,
});
-10
View File
@@ -7,15 +7,6 @@ export const EST_MARGIN_TOOLTIP_TEXT = (settlementAsset: string) =>
For example, for a notional size of $500, if the margin requirement is 10%, then the estimated margin would be approximately $50.`,
[settlementAsset]
);
export const EST_TOTAL_MARGIN_TOOLTIP_TEXT = t(
'Estimated total margin that will cover open position, active orders and this order.'
);
export const MARGIN_ACCOUNT_TOOLTIP_TEXT = t('Margin account balance');
export const MARGIN_DIFF_TOOLTIP_TEXT = (settlementAsset: string) =>
t(
"The additional margin required for your new position (taking into account volume and open orders), compared to your current margin. Measured in the market's settlement asset ($s).",
[settlementAsset]
);
export const CONTRACTS_MARGIN_TOOLTIP_TEXT = t(
'The number of contracts determines how many units of the futures contract to buy or sell. For example, this is similar to buying one share of a listed company. The value of 1 contract is equivalent to the price of the contract. For example, if the current price is $50, then one contract is worth $50.'
);
@@ -50,7 +41,6 @@ export enum MarketModeValidationType {
}
export enum SummaryValidationType {
NoPubKey = 'NoPubKey',
NoCollateral = 'NoCollateral',
TradingMode = 'MarketTradingMode',
MarketState = 'MarketState',
+2
View File
@@ -4,3 +4,5 @@ export * from './use-fee-deal-ticket-details';
export * from './use-market-positions';
export * from './use-maximum-position-size';
export * from './use-order-closeout';
export * from './use-order-margin';
export * from './use-order-margin-validation';
@@ -1,3 +1,4 @@
import { useMemo } from 'react';
import { marketDepthProvider } from '@vegaprotocol/market-depth';
import * as Schema from '@vegaprotocol/types';
import type { Market } from '@vegaprotocol/market-list';
@@ -12,10 +13,11 @@ interface Props {
}
export const useCalculateSlippage = ({ market, order }: Props) => {
const variables = useMemo(() => ({ marketId: market.id }), [market.id]);
const { data } = useThrottledDataProvider(
{
dataProvider: marketDepthProvider,
variables: { marketId: market.id },
variables,
},
1000
);
@@ -3,26 +3,24 @@ import {
addDecimal,
addDecimalsFormatNumber,
formatNumber,
toBigNum,
} from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import * as Schema from '@vegaprotocol/types';
import { useVegaWallet } from '@vegaprotocol/wallet';
import BigNumber from 'bignumber.js';
import { useMemo } from 'react';
import type { Market, MarketData } from '@vegaprotocol/market-list';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import {
EST_CLOSEOUT_TOOLTIP_TEXT,
// EST_MARGIN_TOOLTIP_TEXT,
EST_TOTAL_MARGIN_TOOLTIP_TEXT,
EST_MARGIN_TOOLTIP_TEXT,
NOTIONAL_SIZE_TOOLTIP_TEXT,
MARGIN_ACCOUNT_TOOLTIP_TEXT,
MARGIN_DIFF_TOOLTIP_TEXT,
} from '../constants';
import { useCalculateSlippage } from './use-calculate-slippage';
import { useOrderCloseOut } from './use-order-closeout';
import { useMarketAccountBalance } from '@vegaprotocol/accounts';
import { useOrderMargin } from './use-order-margin';
import type { OrderMargin } from './use-order-margin';
import { getDerivedPrice } from '../utils/get-price';
import { useEstimateOrderQuery } from './__generated__/EstimateOrder';
import type { EstimateOrderQuery } from './__generated__/EstimateOrder';
export const useFeeDealTicketDetails = (
order: OrderSubmissionBody['orderSubmission'],
@@ -30,23 +28,33 @@ export const useFeeDealTicketDetails = (
marketData: MarketData
) => {
const { pubKey } = useVegaWallet();
const { accountBalance } = useMarketAccountBalance(market.id);
const slippage = useCalculateSlippage({ market, order });
const price = useMemo(() => {
return getDerivedPrice(order, marketData);
}, [order, marketData]);
const derivedPrice = useMemo(() => {
return getDerivedPrice(order, market, marketData);
}, [order, market, marketData]);
const { data: estMargin } = useEstimateOrderQuery({
variables: {
marketId: market.id,
partyId: pubKey || '',
price,
size: order.size,
side: order.side,
timeInForce: order.timeInForce,
type: order.type,
},
skip: !pubKey || !market || !order.size || !price,
// Note this isn't currently used anywhere
const slippageAdjustedPrice = useMemo(() => {
if (derivedPrice) {
if (slippage && parseFloat(slippage) !== 0) {
const isLong = order.side === Schema.Side.SIDE_BUY;
const multiplier = new BigNumber(1)[isLong ? 'plus' : 'minus'](
parseFloat(slippage) / 100
);
return new BigNumber(derivedPrice).multipliedBy(multiplier).toNumber();
}
return derivedPrice;
}
return null;
}, [derivedPrice, order.side, slippage]);
const estMargin = useOrderMargin({
order,
market,
marketData,
partyId: pubKey || '',
derivedPrice,
});
const estCloseOut = useOrderCloseOut({
@@ -56,13 +64,13 @@ export const useFeeDealTicketDetails = (
});
const notionalSize = useMemo(() => {
if (price && order.size) {
return toBigNum(order.size, market.positionDecimalPlaces)
.multipliedBy(addDecimal(price, market.decimalPlaces))
if (derivedPrice && order.size) {
return new BigNumber(order.size)
.multipliedBy(addDecimal(derivedPrice, market.decimalPlaces))
.toString();
}
return null;
}, [price, order.size, market.decimalPlaces, market.positionDecimalPlaces]);
}, [derivedPrice, order.size, market.decimalPlaces]);
const assetSymbol =
market.tradableInstrument.instrument.product.settlementAsset.symbol;
@@ -72,40 +80,37 @@ export const useFeeDealTicketDetails = (
market,
assetSymbol,
notionalSize,
accountBalance,
estimateOrder: estMargin?.estimateOrder,
estMargin,
estCloseOut,
slippage,
slippageAdjustedPrice,
};
}, [
market,
assetSymbol,
notionalSize,
accountBalance,
estMargin,
estCloseOut,
slippage,
slippageAdjustedPrice,
]);
};
export interface FeeDetails {
balance: string;
market: Market;
assetSymbol: string;
notionalSize: string | null;
estMargin: OrderMargin | null;
estCloseOut: string | null;
estimateOrder: EstimateOrderQuery['estimateOrder'] | undefined;
margin: string;
totalMargin: string;
slippage: string | null;
}
export const getFeeDetailsValues = ({
balance,
assetSymbol,
estCloseOut,
estimateOrder,
margin,
market,
notionalSize,
totalMargin,
estMargin,
estCloseOut,
market,
}: FeeDetails) => {
const assetDecimals =
market.tradableInstrument.instrument.product.settlementAsset.decimals;
@@ -124,12 +129,7 @@ export const getFeeDetailsValues = ({
? addDecimalsFormatNumber(value, assetDecimals)
: '-';
};
const details: {
label: string;
value?: string | null;
symbol: string;
labelDescription: React.ReactNode;
}[] = [
return [
{
label: t('Notional'),
value: formatValueWithMarketDp(notionalSize),
@@ -139,8 +139,8 @@ export const getFeeDetailsValues = ({
{
label: t('Fees'),
value:
estimateOrder?.totalFeeAmount &&
`~${formatValueWithAssetDp(estimateOrder?.totalFeeAmount)}`,
estMargin?.totalFees &&
`~${formatValueWithAssetDp(estMargin?.totalFees)}`,
labelDescription: (
<>
<span>
@@ -149,7 +149,7 @@ export const getFeeDetailsValues = ({
)}
</span>
<FeesBreakdown
fees={estimateOrder?.fee}
fees={estMargin?.fees}
feeFactors={market.fees.factors}
symbol={assetSymbol}
decimals={assetDecimals}
@@ -158,46 +158,18 @@ export const getFeeDetailsValues = ({
),
symbol: assetSymbol,
},
/*
{
label: t('Initial margin'),
value: margin && `~${formatValueWithAssetDp(margin)}`,
label: t('Margin'),
value:
estMargin?.margin && `~${formatValueWithAssetDp(estMargin?.margin)}`,
symbol: assetSymbol,
labelDescription: EST_MARGIN_TOOLTIP_TEXT(assetSymbol),
},
*/
{
label: t('Margin required'),
value: `~${formatValueWithAssetDp(
balance
? (BigInt(totalMargin) - BigInt(balance)).toString()
: totalMargin
)}`,
symbol: assetSymbol,
labelDescription: MARGIN_DIFF_TOOLTIP_TEXT(assetSymbol),
label: t('Liquidation'),
value: estCloseOut && `~${formatValueWithMarketDp(estCloseOut)}`,
symbol: market.tradableInstrument.instrument.product.quoteName,
labelDescription: EST_CLOSEOUT_TOOLTIP_TEXT(quoteName),
},
];
if (balance) {
details.push({
label: t('Projected margin'),
value: `~${formatValueWithAssetDp(totalMargin)}`,
symbol: assetSymbol,
labelDescription: EST_TOTAL_MARGIN_TOOLTIP_TEXT,
});
}
details.push({
label: t('Current margin allocation'),
value: balance
? `~${formatValueWithAssetDp(balance)}`
: `${formatValueWithAssetDp(balance)}`,
symbol: assetSymbol,
labelDescription: MARGIN_ACCOUNT_TOOLTIP_TEXT,
});
details.push({
label: t('Liquidation'),
value: estCloseOut && `~${formatValueWithMarketDp(estCloseOut)}`,
symbol: market.tradableInstrument.instrument.product.quoteName,
labelDescription: EST_CLOSEOUT_TOOLTIP_TEXT(quoteName),
});
return details;
};
@@ -0,0 +1,11 @@
import { useAccountBalance } from '@vegaprotocol/accounts';
import { toBigNum } from '@vegaprotocol/utils';
export const useHasNoBalance = (assetId: string) => {
const { accountBalance, accountDecimals } = useAccountBalance(assetId);
const balance =
accountBalance && accountDecimals !== null
? toBigNum(accountBalance, accountDecimals)
: toBigNum('0', 0);
return balance.isZero();
};
@@ -1,69 +0,0 @@
import { useMemo } from 'react';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { marketDataProvider } from '@vegaprotocol/market-list';
import {
calculateMargins,
// getDerivedPrice,
volumeAndMarginProvider,
} from '@vegaprotocol/positions';
import { Side } from '@vegaprotocol/types';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { marketInfoProvider } from '@vegaprotocol/market-info';
export const useInitialMargin = (
marketId: OrderSubmissionBody['orderSubmission']['marketId'],
order?: OrderSubmissionBody['orderSubmission']
) => {
const { pubKey: partyId } = useVegaWallet();
const commonVariables = { marketId, partyId: partyId || '' };
const { data: marketData } = useDataProvider({
dataProvider: marketDataProvider,
variables: { marketId },
});
const { data: activeVolumeAndMargin } = useDataProvider({
dataProvider: volumeAndMarginProvider,
variables: commonVariables,
skip: !partyId,
});
const { data: marketInfo } = useDataProvider({
dataProvider: marketInfoProvider,
variables: commonVariables,
});
let totalMargin = '0';
let margin = '0';
if (marketInfo?.riskFactors && marketData && order) {
const {
positionDecimalPlaces,
decimalPlaces,
tradableInstrument,
riskFactors,
} = marketInfo;
const { marginCalculator, instrument } = tradableInstrument;
const { decimals } = instrument.product.settlementAsset;
margin = totalMargin = calculateMargins({
side: order.side,
size: order.size,
price: marketData.markPrice, // getDerivedPrice(order, marketData), same in positions-data-providers
positionDecimalPlaces,
decimalPlaces,
decimals,
scalingFactors: marginCalculator?.scalingFactors,
riskFactors,
}).initialMargin;
}
if (activeVolumeAndMargin) {
let sellMargin = BigInt(activeVolumeAndMargin.sellInitialMargin);
let buyMargin = BigInt(activeVolumeAndMargin.buyInitialMargin);
if (order?.side === Side.SIDE_SELL) {
sellMargin += BigInt(totalMargin);
} else {
buyMargin += BigInt(totalMargin);
}
totalMargin =
sellMargin > buyMargin ? sellMargin.toString() : buyMargin.toString();
}
return useMemo(() => ({ totalMargin, margin }), [totalMargin, margin]);
};
@@ -0,0 +1,48 @@
import { useMemo } from 'react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { toBigNum } from '@vegaprotocol/utils';
import { useAccountBalance } from '@vegaprotocol/accounts';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useOrderMargin } from './use-order-margin';
import type { Market, MarketData } from '@vegaprotocol/market-list';
interface Props {
market: Market;
marketData: MarketData;
order: OrderSubmissionBody['orderSubmission'];
}
export const useOrderMarginValidation = ({
market,
marketData,
order,
}: Props) => {
const { pubKey } = useVegaWallet();
const estMargin = useOrderMargin({
order,
market,
marketData,
partyId: pubKey || '',
});
const { id: assetId, decimals: assetDecimals } =
market.tradableInstrument.instrument.product.settlementAsset;
const { accountBalance, accountDecimals } = useAccountBalance(assetId);
const balance =
accountBalance && accountDecimals !== null
? toBigNum(accountBalance, accountDecimals)
: toBigNum('0', assetDecimals);
const margin = toBigNum(estMargin?.margin || 0, assetDecimals);
// return only simple types (bool, string) for make memo sensible
const balanceError = balance.isGreaterThan(0) && balance.isLessThan(margin);
const balanceAsString = balance.toString();
const marginAsString = margin.toString();
return useMemo(() => {
return {
balance: balanceAsString,
margin: marginAsString,
balanceError,
};
}, [balanceAsString, marginAsString, balanceError]);
};
@@ -0,0 +1,116 @@
import { renderHook } from '@testing-library/react';
import { useQuery } from '@apollo/client';
import { BigNumber } from 'bignumber.js';
import type { PositionMargin } from './use-market-positions';
import type { Props } from './use-order-margin';
import { useOrderMargin } from './use-order-margin';
import * as Schema from '@vegaprotocol/types';
import type { Market, MarketData } from '@vegaprotocol/market-list';
let mockEstimateData = {
estimateOrder: {
fee: {
makerFee: '100000.000',
infrastructureFee: '100000.000',
liquidityFee: '100000.000',
},
marginLevels: {
initialLevel: '200000',
},
},
};
jest.mock('@apollo/client', () => ({
...jest.requireActual('@apollo/client'),
useQuery: jest.fn(() => ({ data: mockEstimateData })),
}));
let mockMarketPositions: PositionMargin = {
openVolume: '1',
balance: '100000',
};
jest.mock('./use-market-positions', () => ({
useMarketPositions: ({
marketId,
partyId,
}: {
marketId: string;
partyId: string;
}) => mockMarketPositions,
}));
describe('useOrderMargin', () => {
const marketId = 'marketId';
const args: Props = {
order: {
marketId,
size: '2',
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_IOC,
type: Schema.OrderType.TYPE_MARKET,
},
market: {
id: marketId,
decimalPlaces: 2,
positionDecimalPlaces: 0,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
} as unknown as Market,
marketData: {
indicativePrice: '100',
markPrice: '200',
} as unknown as MarketData,
partyId: 'partyId',
};
afterEach(() => {
jest.clearAllMocks();
});
it('should calculate margin correctly', () => {
const { result } = renderHook(() => useOrderMargin(args));
expect(result.current?.margin).toEqual('100000');
expect((useQuery as jest.Mock).mock.calls[0][1].variables.size).toEqual(
args.order.size
);
});
it('should calculate fees correctly', () => {
const { result } = renderHook(() => useOrderMargin(args));
expect(result.current?.totalFees).toEqual('300000');
});
it('should not subtract initialMargin if there is no position', () => {
mockMarketPositions = null;
const { result } = renderHook(() => useOrderMargin(args));
expect(result.current?.margin).toEqual('200000');
expect((useQuery as jest.Mock).mock.calls[0][1].variables.size).toEqual(
args.order.size
);
});
it('should return empty value if API fails', () => {
mockEstimateData = {
estimateOrder: {
fee: {
makerFee: '100000.000',
infrastructureFee: '100000.000',
liquidityFee: '100000.000',
},
marginLevels: {
initialLevel: '',
},
},
};
const { result } = renderHook(() => useOrderMargin(args));
expect(result.current).toEqual(null);
const calledSize = new BigNumber(mockMarketPositions?.openVolume || 0)
.plus(args.order.size)
.toString();
expect((useQuery as jest.Mock).mock.calls[0][1].variables.size).toEqual(
calledSize
);
});
});
@@ -0,0 +1,76 @@
import { useMemo } from 'react';
import { BigNumber } from 'bignumber.js';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { removeDecimal } from '@vegaprotocol/utils';
import { useMarketPositions } from './use-market-positions';
import { useEstimateOrderQuery } from './__generated__/EstimateOrder';
import type { Market, MarketData } from '@vegaprotocol/market-list';
import { getDerivedPrice } from '../utils/get-price';
export interface Props {
order: OrderSubmissionBody['orderSubmission'];
market: Market;
marketData: MarketData;
partyId: string;
derivedPrice?: string;
}
export interface OrderMargin {
margin: string;
totalFees: string | null;
fees: {
makerFee: string;
liquidityFee: string;
infrastructureFee: string;
};
}
export const useOrderMargin = ({
order,
market,
marketData,
partyId,
derivedPrice,
}: Props): OrderMargin | null => {
const { balance } = useMarketPositions({ marketId: market.id }) || {};
const priceForEstimate =
derivedPrice || getDerivedPrice(order, market, marketData);
const { data } = useEstimateOrderQuery({
variables: {
marketId: market.id,
partyId,
price: priceForEstimate,
size: removeDecimal(order.size, market.positionDecimalPlaces),
side: order.side,
timeInForce: order.timeInForce,
type: order.type,
},
skip: !partyId || !market.id || !order.size || !priceForEstimate,
});
const { makerFee, liquidityFee, infrastructureFee } = data?.estimateOrder
.fee || { makerFee: '', liquidityFee: '', infrastructureFee: '' };
const { initialLevel } = data?.estimateOrder.marginLevels ?? {};
return useMemo(() => {
if (initialLevel) {
const margin = BigNumber.maximum(
0,
new BigNumber(initialLevel).minus(balance || 0)
).toString();
const fees = new BigNumber(makerFee)
.plus(liquidityFee)
.plus(infrastructureFee)
.toString();
return {
margin,
totalFees: fees,
fees: {
makerFee,
liquidityFee,
infrastructureFee,
},
};
}
return null;
}, [initialLevel, makerFee, liquidityFee, infrastructureFee, balance]);
};
+12 -19
View File
@@ -64,27 +64,20 @@ export function generateMarketData(
id: 'market-id',
__typename: 'Market',
},
auctionEnd: '2022-06-21T17:18:43.484055236Z',
auctionStart: '2022-06-21T17:18:43.484055236Z',
bestBidPrice: '0',
bestBidVolume: '0',
bestOfferPrice: '0',
bestOfferVolume: '0',
bestStaticBidPrice: '0',
bestStaticBidVolume: '0',
bestStaticOfferPrice: '0',
bestStaticOfferVolume: '0',
indicativePrice: '100',
indicativeVolume: '10',
marketState: Schema.MarketState.STATE_ACTIVE,
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
marketValueProxy: '',
markPrice: '200',
midPrice: '0',
openInterest: '',
staticMidPrice: '0',
suppliedStake: '1000',
auctionEnd: '2022-06-21T17:18:43.484055236Z',
targetStake: '1000000',
suppliedStake: '1000',
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
marketState: Schema.MarketState.STATE_ACTIVE,
staticMidPrice: '0',
indicativePrice: '100',
bestStaticBidPrice: '0',
bestStaticOfferPrice: '0',
indicativeVolume: '10',
bestBidPrice: '0',
bestOfferPrice: '0',
markPrice: '200',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_BATCH,
};
return merge(defaultMarketData, override);
+4 -2
View File
@@ -1,6 +1,7 @@
import { removeDecimal } from '@vegaprotocol/utils';
import * as Schema from '@vegaprotocol/types';
import { isMarketInAuction } from './is-market-in-auction';
import type { MarketData } from '@vegaprotocol/market-list';
import type { MarketData, Market } from '@vegaprotocol/market-list';
/**
* Get the market price based on market mode (auction or not auction)
@@ -33,6 +34,7 @@ export const getDerivedPrice = (
type: Schema.OrderType;
price?: string | undefined;
},
market: Market,
marketData: MarketData
) => {
// If order type is market we should use either the mark price
@@ -42,7 +44,7 @@ export const getDerivedPrice = (
// Use the market price if order is a market order
let price;
if (order.type === Schema.OrderType.TYPE_LIMIT && order.price) {
price = order.price;
price = removeDecimal(order.price, market.decimalPlaces);
} else {
price = getMarketPrice(marketData);
}
@@ -12,7 +12,6 @@ export const DepositContainer = ({ assetId }: { assetId?: string }) => {
const { VEGA_ENV } = useEnvironment();
const { data, loading, error } = useDataProvider({
dataProvider: enabledAssetsProvider,
variables: undefined,
});
return (
+1 -1
View File
@@ -15,7 +15,7 @@ interface Actions {
close: () => void;
}
export const useDepositDialog = create<State & Actions>((set) => ({
export const useDepositDialog = create<State & Actions>()((set) => ({
isOpen: false,
assetId: undefined,
open: (assetId) => set(() => ({ assetId, isOpen: true })),
-18
View File
@@ -1,18 +0,0 @@
import { act } from 'react-dom/test-utils';
const zu = jest.requireActual('zustand'); // if using jest
// a variable to hold reset functions for all stores declared in the app
const storeResetFns = new Set();
// when creating a store, we get its initial state, create a reset function and add it in the set
export const create = (createState) => {
const store = zu.create(createState);
const initialState = store.getState();
storeResetFns.add(() => store.setState(initialState, true));
return store;
};
// Reset all stores after each test run
beforeEach(() => {
act(() => storeResetFns.forEach((resetFn) => resetFn()));
});
+21
View File
@@ -0,0 +1,21 @@
import type { StateCreator } from 'zustand';
import { act } from 'react-dom/test-utils';
const { create: actualCreate } = jest.requireActual('zustand'); // if using jest
// a variable to hold reset functions for all stores declared in the app
const storeResetFns = new Set<() => void>();
// when creating a store, we get its initial state, create a reset function and add it in the set
export const create =
() =>
<S>(createState: StateCreator<S>) => {
const store = actualCreate(createState);
const initialState = store.getState();
storeResetFns.add(() => store.setState(initialState, true));
return store;
};
// Reset all stores after each test run
beforeEach(() => {
act(() => storeResetFns.forEach((resetFn) => resetFn()));
});
@@ -34,7 +34,7 @@ export type EnvStore = Env & Actions;
export const STORAGE_KEY = 'vega_url';
const SUBSCRIPTION_TIMEOUT = 3000;
export const useEnvironment = create<EnvStore>((set, get) => ({
export const useEnvironment = create<EnvStore>()((set, get) => ({
...compileEnvVars(),
nodes: [],
status: 'default',
+2 -1
View File
@@ -17,7 +17,8 @@
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"jest.config.ts"
"jest.config.ts",
"__mocks__"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}
+6 -20
View File
@@ -13,7 +13,6 @@ import type { PageInfo, Edge } from '@vegaprotocol/utils';
import { FillsDocument, FillsEventDocument } from './__generated__/Fills';
import type {
FillsQuery,
FillsQueryVariables,
FillFieldsFragment,
FillEdgeFragment,
FillsEventSubscription,
@@ -57,28 +56,19 @@ const update = (
});
};
export type Trade = Omit<FillFieldsFragment, 'market'> & {
market?: Market;
isLastPlaceholder?: boolean;
};
export type Trade = Omit<FillFieldsFragment, 'market'> & { market?: Market };
export type TradeEdge = Edge<Trade>;
const getData = (responseData: FillsQuery | null): FillEdgeFragment[] =>
responseData?.party?.tradesConnection?.edges || [];
const getPageInfo = (responseData: FillsQuery | null): PageInfo | null =>
responseData?.party?.tradesConnection?.pageInfo || null;
const getPageInfo = (responseData: FillsQuery): PageInfo | null =>
responseData.party?.tradesConnection?.pageInfo || null;
const getDelta = (subscriptionData: FillsEventSubscription) =>
subscriptionData.trades || [];
export const fillsProvider = makeDataProvider<
Parameters<typeof getData>['0'],
ReturnType<typeof getData>,
Parameters<typeof getDelta>['0'],
ReturnType<typeof getDelta>,
FillsQueryVariables
>({
export const fillsProvider = makeDataProvider({
query: FillsDocument,
subscriptionQuery: FillsEventDocument,
update,
@@ -93,13 +83,9 @@ export const fillsProvider = makeDataProvider<
export const fillsWithMarketProvider = makeDerivedDataProvider<
(TradeEdge | null)[],
Trade[],
FillsQueryVariables
Trade[]
>(
[
fillsProvider,
(callback, client) => marketsProvider(callback, client, undefined),
],
[fillsProvider, marketsProvider],
(partsData): (TradeEdge | null)[] =>
(partsData[0] as ReturnType<typeof getData>)?.map(
(edge) =>
+8 -42
View File
@@ -1,12 +1,10 @@
import type { AgGridReact } from 'ag-grid-react';
import { useCallback, useRef } from 'react';
import { useRef } from 'react';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { FillsTable } from './fills-table';
import type { BodyScrollEvent, BodyScrollEndEvent } from 'ag-grid-community';
import { useFillsList } from './use-fills-list';
import type { Trade } from './fills-data-provider';
import { useBottomPlaceholder } from '@vegaprotocol/react-helpers';
interface FillsManagerProps {
partyId: string;
@@ -21,51 +19,22 @@ export const FillsManager = ({
}: FillsManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null);
const scrolledToTop = useRef(true);
const {
data,
error,
loading,
addNewRows,
getRows,
reload,
makeBottomPlaceholders,
} = useFillsList({
const { data, error, loading, addNewRows, getRows, reload } = useFillsList({
partyId,
marketId,
gridRef,
scrolledToTop,
});
const checkBottomPlaceholder = useCallback(() => {
const rowCont = gridRef.current?.api?.getModel().getRowCount() ?? 0;
const lastRowIndex = gridRef.current?.api?.getLastDisplayedRow();
if (lastRowIndex && rowCont - 1 === lastRowIndex) {
const lastrow = gridRef.current?.api.getDisplayedRowAtIndex(lastRowIndex);
lastrow?.setRowHeight(50);
makeBottomPlaceholders(lastrow?.data);
gridRef.current?.api.onRowHeightChanged();
gridRef.current?.api.refreshInfiniteCache();
const onBodyScrollEnd = (event: BodyScrollEndEvent) => {
if (event.top === 0) {
addNewRows();
}
}, [makeBottomPlaceholders]);
};
const onBodyScrollEnd = useCallback(
(event: BodyScrollEndEvent) => {
if (event.top === 0) {
addNewRows();
}
checkBottomPlaceholder();
},
[addNewRows, checkBottomPlaceholder]
);
const onBodyScroll = useCallback((event: BodyScrollEvent) => {
const onBodyScroll = (event: BodyScrollEvent) => {
scrolledToTop.current = event.top <= 0;
}, []);
const { isFullWidthRow, fullWidthCellRenderer, rowClassRules } =
useBottomPlaceholder<Trade>({
gridRef,
});
};
return (
<div className="h-full relative">
@@ -79,9 +48,6 @@ export const FillsManager = ({
onMarketClick={onMarketClick}
suppressLoadingOverlay
suppressNoRowsOverlay
isFullWidthRow={isFullWidthRow}
fullWidthCellRenderer={fullWidthCellRenderer}
rowClassRules={rowClassRules}
/>
<div className="pointer-events-none absolute inset-0">
<AsyncRenderer
+9 -27
View File
@@ -1,6 +1,6 @@
import type { RefObject } from 'react';
import type { AgGridReact } from 'ag-grid-react';
import { useCallback, useRef } from 'react';
import { useCallback, useMemo, useRef } from 'react';
import { makeInfiniteScrollGetRows } from '@vegaprotocol/utils';
import { useDataProvider, updateGridData } from '@vegaprotocol/react-helpers';
import type { Trade, TradeEdge } from './fills-data-provider';
@@ -22,21 +22,6 @@ export const useFillsList = ({
const dataRef = useRef<(TradeEdge | null)[] | null>(null);
const totalCountRef = useRef<number | undefined>(undefined);
const newRows = useRef(0);
const placeholderAdded = useRef(-1);
const makeBottomPlaceholders = useCallback((trade?: Trade) => {
if (!trade) {
if (placeholderAdded.current >= 0) {
dataRef.current?.splice(placeholderAdded.current, 1);
}
placeholderAdded.current = -1;
} else if (placeholderAdded.current === -1) {
dataRef.current?.push({
node: { ...trade, id: `${trade?.id}-1`, isLastPlaceholder: true },
});
placeholderAdded.current = (dataRef.current?.length || 0) - 1;
}
}, []);
const addNewRows = useCallback(() => {
if (newRows.current === 0) {
@@ -88,11 +73,16 @@ export const useFillsList = ({
[gridRef]
);
const { data, error, loading, load, totalCount, reload } = useDataProvider({
const variables = useMemo(() => ({ partyId, marketId }), [partyId, marketId]);
const { data, error, loading, load, totalCount, reload } = useDataProvider<
(TradeEdge | null)[],
Trade[]
>({
dataProvider: fillsWithMarketProvider,
update,
insert,
variables: { partyId, marketId: marketId || '' },
variables,
});
totalCountRef.current = totalCount;
@@ -102,13 +92,5 @@ export const useFillsList = ({
load,
newRows
);
return {
data,
error,
loading,
addNewRows,
getRows,
reload,
makeBottomPlaceholders,
};
return { data, error, loading, addNewRows, getRows, reload };
};
@@ -42,7 +42,7 @@ export const update = (
data: ReturnType<typeof getData> | null,
delta: ReturnType<typeof getData>,
reload: () => void,
variables: LedgerEntriesQueryVariables
variables?: LedgerEntriesQueryVariables
) => {
if (!data) {
return data;
@@ -110,8 +110,8 @@ export const ledgerEntriesProvider = makeDerivedDataProvider<
>(
[
ledgerEntriesOnlyProvider,
(callback, client) => assetsProvider(callback, client, undefined),
(callback, client) => marketsProvider(callback, client, undefined),
(callback, client) => assetsProvider(callback, client),
marketsProvider,
],
([entries, assets, markets]) => {
return entries.map((edge: AggregatedLedgerEntriesEdge) => {
@@ -14,14 +14,11 @@ import {
import type {
MarketLpQuery,
MarketLpQueryVariables,
LiquidityProviderFeeShareFieldsFragment,
LiquidityProviderFeeShareQuery,
LiquidityProviderFeeShareQueryVariables,
LiquidityProviderFeeShareUpdateSubscription,
LiquidityProvisionFieldsFragment,
LiquidityProvisionsQuery,
LiquidityProvisionsQueryVariables,
LiquidityProvisionsUpdateSubscription,
} from './__generated__/MarketLiquidity';
import type { IterableElement } from 'type-fest';
@@ -30,8 +27,7 @@ export const liquidityProvisionsDataProvider = makeDataProvider<
LiquidityProvisionsQuery,
LiquidityProvisionFieldsFragment[],
LiquidityProvisionsUpdateSubscription,
LiquidityProvisionsUpdateSubscription['liquidityProvisions'],
LiquidityProvisionsQueryVariables
LiquidityProvisionsUpdateSubscription['liquidityProvisions']
>({
query: LiquidityProvisionsDocument,
subscriptionQuery: LiquidityProvisionsUpdateDocument,
@@ -103,8 +99,7 @@ export const marketLiquidityDataProvider = makeDataProvider<
MarketLpQuery,
MarketLpQuery,
never,
never,
MarketLpQueryVariables
never
>({
query: MarketLpDocument,
getData: (responseData: MarketLpQuery | null) => {
@@ -116,8 +111,7 @@ export const liquidityFeeShareDataProvider = makeDataProvider<
LiquidityProviderFeeShareQuery,
LiquidityProviderFeeShareFieldsFragment[],
LiquidityProviderFeeShareUpdateSubscription,
LiquidityProviderFeeShareUpdateSubscription['marketsData'][0]['liquidityProviderFeeShare'],
LiquidityProviderFeeShareQueryVariables
LiquidityProviderFeeShareUpdateSubscription['marketsData'][0]['liquidityProviderFeeShare']
>({
query: LiquidityProviderFeeShareDocument,
subscriptionQuery: LiquidityProviderFeeShareUpdateDocument,
@@ -153,11 +147,7 @@ export const liquidityFeeShareDataProvider = makeDataProvider<
},
});
export const lpAggregatedDataProvider = makeDerivedDataProvider<
ReturnType<typeof getLiquidityProvision>,
never,
MarketLpQueryVariables
>(
export const lpAggregatedDataProvider = makeDerivedDataProvider(
[
liquidityProvisionsDataProvider,
marketLiquidityDataProvider,
@@ -5,10 +5,12 @@ import { useDataProvider, useYesterday } from '@vegaprotocol/react-helpers';
import type {
MarketCandles,
MarketMaybeWithDataAndCandles,
MarketsCandlesQueryVariables,
} from '@vegaprotocol/market-list';
import { marketListProvider } from '@vegaprotocol/market-list';
import {
marketsCandlesProvider,
marketListProvider,
} from '@vegaprotocol/market-list';
import type { LiquidityProvisionMarketsQuery } from './__generated__/MarketsLiquidity';
import { LiquidityProvisionMarketsDocument } from './__generated__/MarketsLiquidity';
@@ -95,18 +97,15 @@ export const liquidityMarketsProvider = makeDataProvider<
getData,
});
const liquidityProvisionProvider = makeDerivedDataProvider<
Market[],
never,
Exclude<MarketsCandlesQueryVariables, 'interval'>
>(
const liquidityProvisionProvider = makeDerivedDataProvider<Market[], never>(
[
marketListProvider,
(callback, client, variables) =>
marketListProvider(callback, client, {
since: variables.since,
marketsCandlesProvider(callback, client, {
...variables,
interval: Schema.Interval.INTERVAL_I1D,
}),
(callback, client) => liquidityMarketsProvider(callback, client, undefined),
liquidityMarketsProvider,
],
(parts) => {
return addData(
@@ -31,7 +31,7 @@ describe('market depth provider update', () => {
sequenceNumber: '',
previousSequenceNumber: '',
};
const updatedData = update(data, [delta], reload, { marketId: '1' });
const updatedData = update(data, [delta], reload);
expect(updatedData).toBe(data);
});
@@ -54,12 +54,8 @@ describe('market depth provider update', () => {
previousSequenceNumber: '',
},
];
expect(update(data, delta.slice(0, 1), reload, { marketId: '1' })).toBe(
data
);
expect(update(data, delta.slice(1, 2), reload, { marketId: '1' })).toBe(
data
);
expect(update(data, delta.slice(0, 1), reload)).toBe(data);
expect(update(data, delta.slice(1, 2), reload)).toBe(data);
});
it('restarts and captureException when there is gap in updates', () => {
@@ -76,7 +72,7 @@ describe('market depth provider update', () => {
previousSequenceNumber: '12',
},
];
const updatedData = update(data, delta, reload, { marketId: '1' });
const updatedData = update(data, delta, reload);
expect(updatedData).toBe(data);
expect(reload).toBeCalled();
expect(mockCaptureException).toBeCalled();
@@ -9,14 +9,12 @@ import {
} from './__generated__/MarketDepth';
import type {
MarketDepthQuery,
MarketDepthQueryVariables,
MarketDepthUpdateSubscription,
} from './__generated__/MarketDepth';
export const update: Update<
ReturnType<typeof getData>,
ReturnType<typeof getDelta>,
MarketDepthQueryVariables
ReturnType<typeof getDelta>
> = (data, deltas, reload) => {
if (!data) {
return data;
@@ -63,19 +61,12 @@ export const update: Update<
return data;
};
const getData = (responseData: MarketDepthQuery | null) =>
responseData?.market || null;
const getData = (responseData: MarketDepthQuery | null) => responseData?.market;
const getDelta = (subscriptionData: MarketDepthUpdateSubscription) =>
subscriptionData.marketsDepthUpdate;
export const marketDepthProvider = makeDataProvider<
MarketDepthQuery,
ReturnType<typeof getData>,
MarketDepthUpdateSubscription,
ReturnType<typeof getDelta>,
MarketDepthQueryVariables
>({
export const marketDepthProvider = makeDataProvider({
query: MarketDepthDocument,
subscriptionQuery: MarketDepthUpdateDocument,
update,
@@ -7,13 +7,12 @@ import { useDataProvider } from '@vegaprotocol/react-helpers';
import { marketDepthProvider } from './market-depth-provider';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import type { MarketData } from '@vegaprotocol/market-list';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type {
MarketDepthUpdateSubscription,
MarketDepthQuery,
MarketDepthQueryVariables,
PriceLevelFieldsFragment,
} from './__generated__/MarketDepth';
import type { PriceLevelFieldsFragment } from './__generated__/MarketDepth';
import {
compactRows,
updateCompactedRows,
@@ -29,7 +28,7 @@ interface OrderbookManagerProps {
export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
const [resolution, setResolution] = useState(1);
const variables = { marketId };
const variables = useMemo(() => ({ marketId }), [marketId]);
const resolutionRef = useRef(resolution);
const [orderbookData, setOrderbookData] = useState<OrderbookData>({
rows: null,
@@ -80,8 +79,8 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
delta: deltas,
data: rawData,
}: {
delta?: MarketDepthUpdateSubscription['marketsDepthUpdate'] | null;
data: NonNullable<MarketDepthQuery['market']> | null | undefined;
delta?: MarketDepthUpdateSubscription['marketsDepthUpdate'];
data?: MarketDepthQuery['market'];
}) => {
if (!dataRef.current.rows) {
return false;
@@ -104,11 +103,7 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
[marketId, updateOrderbookData]
);
const { data, error, loading, flush, reload } = useDataProvider<
MarketDepthQuery['market'] | undefined,
MarketDepthUpdateSubscription['marketsDepthUpdate'] | null,
MarketDepthQueryVariables
>({
const { data, error, loading, flush, reload } = useDataProvider({
dataProvider: marketDepthProvider,
update,
variables,
@@ -1,5 +1,4 @@
import { totalFeesPercentage } from '@vegaprotocol/market-list';
import type { TradeFee, FeeFactors } from '@vegaprotocol/types';
import {
addDecimalsFormatNumber,
formatNumberPercentage,
@@ -8,7 +7,12 @@ import { t } from '@vegaprotocol/i18n';
import { Tooltip } from '@vegaprotocol/ui-toolkit';
import BigNumber from 'bignumber.js';
export const FeesCell = ({ feeFactors }: { feeFactors: FeeFactors }) => (
import type { Market } from '@vegaprotocol/market-list';
export const FeesCell = ({
feeFactors,
}: {
feeFactors: Market['fees']['factors'];
}) => (
<Tooltip description={<FeesBreakdownPercentage feeFactors={feeFactors} />}>
<span>{totalFeesPercentage(feeFactors) ?? '-'}</span>
</Tooltip>
@@ -17,7 +21,7 @@ export const FeesCell = ({ feeFactors }: { feeFactors: FeeFactors }) => (
export const FeesBreakdownPercentage = ({
feeFactors,
}: {
feeFactors?: FeeFactors;
feeFactors?: Market['fees']['factors'];
}) => {
if (!feeFactors) return null;
return (
@@ -50,8 +54,12 @@ export const FeesBreakdown = ({
symbol,
decimals,
}: {
fees?: TradeFee;
feeFactors?: FeeFactors;
fees?: {
infrastructureFee: string;
liquidityFee: string;
makerFee: string;
};
feeFactors?: Market['fees']['factors'];
symbol?: string;
decimals: number;
}) => {
@@ -1,4 +1,4 @@
query MarketInfo($marketId: ID!) {
query MarketInfo($marketId: ID!, $interval: Interval!, $since: String!) {
market(id: $marketId) {
id
decimalPlaces
@@ -32,6 +32,7 @@ query MarketInfo($marketId: ID!) {
}
}
}
tradingMode
fees {
factors {
makerFee
@@ -53,6 +54,35 @@ query MarketInfo($marketId: ID!) {
short
long
}
data {
market {
id
}
markPrice
midPrice
bestBidVolume
bestOfferVolume
bestStaticBidVolume
bestStaticOfferVolume
bestBidPrice
bestOfferPrice
trigger
openInterest
suppliedStake
openInterest
targetStake
marketValueProxy
priceMonitoringBounds {
minValidPrice
maxValidPrice
trigger {
horizonSecs
probability
auctionExtensionSecs
}
referencePrice
}
}
liquidityMonitoringParameters {
triggeringRatio
targetStakeParameters {
@@ -60,6 +90,13 @@ query MarketInfo($marketId: ID!) {
scalingFactor
}
}
candlesConnection(interval: $interval, since: $since) {
edges {
node {
volume
}
}
}
tradableInstrument {
instrument {
id
@@ -107,12 +144,10 @@ query MarketInfo($marketId: ID!) {
}
}
}
marginCalculator {
scalingFactors {
searchLevel
initialMargin
collateralRelease
}
}
depth {
lastTrade {
price
}
}
}
@@ -0,0 +1,147 @@
query MarketInfoNoCandles($marketId: ID!) {
market(id: $marketId) {
id
decimalPlaces
positionDecimalPlaces
state
tradingMode
lpPriceRange
proposal {
id
rationale {
title
description
}
}
marketTimestamps {
open
close
}
openingAuction {
durationSecs
volume
}
accountsConnection {
edges {
node {
type
asset {
id
}
balance
}
}
}
tradingMode
fees {
factors {
makerFee
infrastructureFee
liquidityFee
}
}
priceMonitoringSettings {
parameters {
triggers {
horizonSecs
probability
auctionExtensionSecs
}
}
}
riskFactors {
market
short
long
}
data {
market {
id
}
markPrice
midPrice
bestBidVolume
bestOfferVolume
bestStaticBidVolume
bestStaticOfferVolume
bestBidPrice
bestOfferPrice
trigger
openInterest
suppliedStake
openInterest
targetStake
marketValueProxy
priceMonitoringBounds {
minValidPrice
maxValidPrice
trigger {
horizonSecs
probability
auctionExtensionSecs
}
referencePrice
}
}
liquidityMonitoringParameters {
triggeringRatio
targetStakeParameters {
timeWindow
scalingFactor
}
}
tradableInstrument {
instrument {
id
name
code
metadata {
tags
}
product {
... on Future {
quoteName
settlementAsset {
id
symbol
name
decimals
}
dataSourceSpecForSettlementData {
id
}
dataSourceSpecForTradingTermination {
id
}
dataSourceSpecBinding {
settlementDataProperty
tradingTerminationProperty
}
}
}
}
riskModel {
... on LogNormalRiskModel {
tau
riskAversionParameter
params {
r
sigma
mu
}
}
... on SimpleRiskModel {
params {
factorLong
factorShort
}
}
}
}
depth {
lastTrade {
price
}
}
}
}
@@ -5,14 +5,16 @@ import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type MarketInfoQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
interval: Types.Interval;
since: Types.Scalars['String'];
}>;
export type MarketInfoQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } }, marginCalculator?: { __typename?: 'MarginCalculator', scalingFactors: { __typename?: 'ScalingFactors', searchLevel: number, initialMargin: number, collateralRelease: number } } | null } } | null };
export type MarketInfoQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, data?: { __typename?: 'MarketData', markPrice: string, midPrice: string, bestBidVolume: string, bestOfferVolume: string, bestStaticBidVolume: string, bestStaticOfferVolume: string, bestBidPrice: string, bestOfferPrice: string, trigger: Types.AuctionTrigger, openInterest: string, suppliedStake?: string | null, targetStake?: string | null, marketValueProxy: string, market: { __typename?: 'Market', id: string }, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, candlesConnection?: { __typename?: 'CandleDataConnection', edges?: Array<{ __typename?: 'CandleEdge', node: { __typename?: 'Candle', volume: string } } | null> | null } | null, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } } }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
export const MarketInfoDocument = gql`
query MarketInfo($marketId: ID!) {
query MarketInfo($marketId: ID!, $interval: Interval!, $since: String!) {
market(id: $marketId) {
id
decimalPlaces
@@ -46,6 +48,7 @@ export const MarketInfoDocument = gql`
}
}
}
tradingMode
fees {
factors {
makerFee
@@ -67,6 +70,35 @@ export const MarketInfoDocument = gql`
short
long
}
data {
market {
id
}
markPrice
midPrice
bestBidVolume
bestOfferVolume
bestStaticBidVolume
bestStaticOfferVolume
bestBidPrice
bestOfferPrice
trigger
openInterest
suppliedStake
openInterest
targetStake
marketValueProxy
priceMonitoringBounds {
minValidPrice
maxValidPrice
trigger {
horizonSecs
probability
auctionExtensionSecs
}
referencePrice
}
}
liquidityMonitoringParameters {
triggeringRatio
targetStakeParameters {
@@ -74,6 +106,13 @@ export const MarketInfoDocument = gql`
scalingFactor
}
}
candlesConnection(interval: $interval, since: $since) {
edges {
node {
volume
}
}
}
tradableInstrument {
instrument {
id
@@ -121,12 +160,10 @@ export const MarketInfoDocument = gql`
}
}
}
marginCalculator {
scalingFactors {
searchLevel
initialMargin
collateralRelease
}
}
depth {
lastTrade {
price
}
}
}
@@ -146,6 +183,8 @@ export const MarketInfoDocument = gql`
* const { data, loading, error } = useMarketInfoQuery({
* variables: {
* marketId: // value for 'marketId'
* interval: // value for 'interval'
* since: // value for 'since'
* },
* });
*/
@@ -0,0 +1,190 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type MarketInfoNoCandlesQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
}>;
export type MarketInfoNoCandlesQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, data?: { __typename?: 'MarketData', markPrice: string, midPrice: string, bestBidVolume: string, bestOfferVolume: string, bestStaticBidVolume: string, bestStaticOfferVolume: string, bestBidPrice: string, bestOfferPrice: string, trigger: Types.AuctionTrigger, openInterest: string, suppliedStake?: string | null, targetStake?: string | null, marketValueProxy: string, market: { __typename?: 'Market', id: string }, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } } }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
export const MarketInfoNoCandlesDocument = gql`
query MarketInfoNoCandles($marketId: ID!) {
market(id: $marketId) {
id
decimalPlaces
positionDecimalPlaces
state
tradingMode
lpPriceRange
proposal {
id
rationale {
title
description
}
}
marketTimestamps {
open
close
}
openingAuction {
durationSecs
volume
}
accountsConnection {
edges {
node {
type
asset {
id
}
balance
}
}
}
tradingMode
fees {
factors {
makerFee
infrastructureFee
liquidityFee
}
}
priceMonitoringSettings {
parameters {
triggers {
horizonSecs
probability
auctionExtensionSecs
}
}
}
riskFactors {
market
short
long
}
data {
market {
id
}
markPrice
midPrice
bestBidVolume
bestOfferVolume
bestStaticBidVolume
bestStaticOfferVolume
bestBidPrice
bestOfferPrice
trigger
openInterest
suppliedStake
openInterest
targetStake
marketValueProxy
priceMonitoringBounds {
minValidPrice
maxValidPrice
trigger {
horizonSecs
probability
auctionExtensionSecs
}
referencePrice
}
}
liquidityMonitoringParameters {
triggeringRatio
targetStakeParameters {
timeWindow
scalingFactor
}
}
tradableInstrument {
instrument {
id
name
code
metadata {
tags
}
product {
... on Future {
quoteName
settlementAsset {
id
symbol
name
decimals
}
dataSourceSpecForSettlementData {
id
}
dataSourceSpecForTradingTermination {
id
}
dataSourceSpecBinding {
settlementDataProperty
tradingTerminationProperty
}
}
}
}
riskModel {
... on LogNormalRiskModel {
tau
riskAversionParameter
params {
r
sigma
mu
}
}
... on SimpleRiskModel {
params {
factorLong
factorShort
}
}
}
}
depth {
lastTrade {
price
}
}
}
}
`;
/**
* __useMarketInfoNoCandlesQuery__
*
* To run a query within a React component, call `useMarketInfoNoCandlesQuery` and pass it any options that fit your needs.
* When your component renders, `useMarketInfoNoCandlesQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useMarketInfoNoCandlesQuery({
* variables: {
* marketId: // value for 'marketId'
* },
* });
*/
export function useMarketInfoNoCandlesQuery(baseOptions: Apollo.QueryHookOptions<MarketInfoNoCandlesQuery, MarketInfoNoCandlesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<MarketInfoNoCandlesQuery, MarketInfoNoCandlesQueryVariables>(MarketInfoNoCandlesDocument, options);
}
export function useMarketInfoNoCandlesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<MarketInfoNoCandlesQuery, MarketInfoNoCandlesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<MarketInfoNoCandlesQuery, MarketInfoNoCandlesQueryVariables>(MarketInfoNoCandlesDocument, options);
}
export type MarketInfoNoCandlesQueryHookResult = ReturnType<typeof useMarketInfoNoCandlesQuery>;
export type MarketInfoNoCandlesLazyQueryHookResult = ReturnType<typeof useMarketInfoNoCandlesLazyQuery>;
export type MarketInfoNoCandlesQueryResult = Apollo.QueryResult<MarketInfoNoCandlesQuery, MarketInfoNoCandlesQueryVariables>;
@@ -2,4 +2,5 @@ export * from './info-key-value-table';
export * from './info-market';
export * from './tooltip-mapping';
export * from './__generated__/MarketInfo';
export * from './__generated__/MarketInfoNoCandles';
export * from './market-info-data-provider';
@@ -1,9 +1,6 @@
import { AssetDetailsTable, useAssetDataProvider } from '@vegaprotocol/assets';
import { useEnvironment } from '@vegaprotocol/environment';
import {
totalFeesPercentage,
calcCandleVolume,
} from '@vegaprotocol/market-list';
import { totalFeesPercentage } from '@vegaprotocol/market-list';
import {
addDecimalsFormatNumber,
formatNumber,
@@ -23,20 +20,31 @@ import {
Splash,
} from '@vegaprotocol/ui-toolkit';
import BigNumber from 'bignumber.js';
import pick from 'lodash/pick';
import { useMemo } from 'react';
import { generatePath, Link } from 'react-router-dom';
import { MarketInfoTable } from './info-key-value-table';
import { marketInfoWithDataAndCandlesProvider } from './market-info-data-provider';
import { marketInfoDataProvider } from './market-info-data-provider';
import type { MarketInfoWithDataAndCandles } from './market-info-data-provider';
import type { MarketInfoQuery } from './__generated__/MarketInfo';
import { MarketProposalNotification } from '@vegaprotocol/proposals';
export interface InfoProps {
market: MarketInfoWithDataAndCandles;
market: MarketInfoQuery['market'];
onSelect: (id: string) => void;
}
export const calcCandleVolume = (
m: MarketInfoQuery['market']
): string | undefined => {
return m?.candlesConnection?.edges
?.reduce((acc: BigNumber, c) => {
return acc.plus(new BigNumber(c?.node?.volume ?? 0));
}, new BigNumber(m?.candlesConnection?.edges[0]?.node.volume ?? 0))
?.toString();
};
export interface MarketInfoContainerProps {
marketId: string;
onSelect?: (id: string) => void;
@@ -59,15 +67,15 @@ export const MarketInfoContainer = ({
);
const { data, loading, error, reload } = useDataProvider({
dataProvider: marketInfoWithDataAndCandlesProvider,
dataProvider: marketInfoDataProvider,
skipUpdates: true,
variables,
});
return (
<AsyncRenderer data={data} loading={loading} error={error} reload={reload}>
{data ? (
<Info market={data} onSelect={(id) => onSelect?.(id)} />
{data && data.market ? (
<Info market={data.market} onSelect={(id) => onSelect?.(id)} />
) : (
<Splash>
<p>{t('Could not load market')}</p>
@@ -80,6 +88,7 @@ export const MarketInfoContainer = ({
export const Info = ({ market, onSelect }: InfoProps) => {
const { VEGA_TOKEN_URL, VEGA_EXPLORER_URL } = useEnvironment();
const headerClassName = 'uppercase text-lg';
const dayVolume = calcCandleVolume(market);
const assetSymbol =
market?.tradableInstrument.instrument.product?.settlementAsset.symbol || '';
const quoteUnit =
@@ -96,8 +105,6 @@ export const Info = ({ market, onSelect }: InfoProps) => {
market.accountsConnection?.edges
);
const last24hourVolume = market.candles && calcCandleVolume(market.candles);
const marketDataPanels = [
{
title: t('Current fees'),
@@ -124,9 +131,13 @@ export const Info = ({ market, onSelect }: InfoProps) => {
<>
<MarketInfoTable
data={{
markPrice: market.data?.markPrice,
bestBidPrice: market.data?.bestBidPrice,
bestOfferPrice: market.data?.bestOfferPrice,
...pick(
market.data,
'name',
'markPrice',
'bestBidPrice',
'bestOfferPrice'
),
quoteUnit: market.tradableInstrument.instrument.product.quoteName,
}}
decimalPlaces={market.decimalPlaces}
@@ -146,17 +157,16 @@ export const Info = ({ market, onSelect }: InfoProps) => {
<MarketInfoTable
data={{
'24hourVolume':
last24hourVolume && last24hourVolume !== '0'
? addDecimalsFormatNumber(
last24hourVolume,
market.positionDecimalPlaces
)
: '-',
openInterest: market.data?.openInterest,
bestBidVolume: market.data?.bestBidVolume,
bestOfferVolume: market.data?.bestOfferVolume,
bestStaticBidVolume: market.data?.bestStaticBidVolume,
bestStaticOfferVolume: market.data?.bestStaticOfferVolume,
dayVolume && dayVolume !== '0' ? formatNumber(dayVolume) : '-',
...pick(
market.data,
'openInterest',
'name',
'bestBidVolume',
'bestOfferVolume',
'bestStaticBidVolume',
'bestStaticOfferVolume'
),
}}
decimalPlaces={market.positionDecimalPlaces}
/>
@@ -182,9 +192,7 @@ export const Info = ({ market, onSelect }: InfoProps) => {
];
const keyDetails = {
decimalPlaces: market.decimalPlaces,
positionDecimalPlaces: market.positionDecimalPlaces,
tradingMode: market.tradingMode,
...pick(market, 'decimalPlaces', 'positionDecimalPlaces', 'tradingMode'),
state: Schema.MarketStateMapping[market.state],
};
@@ -1,68 +1,25 @@
import { makeDataProvider, makeDerivedDataProvider } from '@vegaprotocol/utils';
import type {
MarketInfoQuery,
MarketInfoQueryVariables,
} from './__generated__/MarketInfo';
import {
marketDataProvider,
marketCandlesProvider,
} from '@vegaprotocol/market-list';
import type {
MarketData,
Candle,
MarketCandlesQueryVariables,
} from '@vegaprotocol/market-list';
import { makeDataProvider } from '@vegaprotocol/utils';
import type { MarketInfoQuery } from './__generated__/MarketInfo';
import { MarketInfoDocument } from './__generated__/MarketInfo';
import type { MarketInfoNoCandlesQuery } from './__generated__/MarketInfoNoCandles';
import { MarketInfoNoCandlesDocument } from './__generated__/MarketInfoNoCandles';
export type MarketInfo = NonNullable<MarketInfoQuery['market']>;
export type MarketInfoWithData = MarketInfo & { data?: MarketData };
export type MarketInfoWithDataAndCandles = MarketInfoWithData & {
candles?: Candle[];
};
const getData = (responseData: MarketInfoQuery | null) =>
responseData?.market || null;
export const marketInfoProvider = makeDataProvider<
export const marketInfoDataProvider = makeDataProvider<
MarketInfoQuery,
MarketInfoQuery,
MarketInfoQuery['market'],
never,
never,
MarketInfoQueryVariables
never
>({
query: MarketInfoDocument,
getData,
getData: (responseData: MarketInfoQuery | null) => responseData,
});
export const marketInfoWithDataProvider = makeDerivedDataProvider<
MarketInfoWithData,
export const marketInfoNoCandlesDataProvider = makeDataProvider<
MarketInfoNoCandlesQuery,
MarketInfoNoCandlesQuery,
never,
MarketInfoQueryVariables
>([marketInfoProvider, marketDataProvider], (parts) => {
const market: MarketInfo | null = parts[0];
const marketData: MarketData | null = parts[1];
return (
market && {
...market,
data: marketData || undefined,
}
);
});
export const marketInfoWithDataAndCandlesProvider = makeDerivedDataProvider<
MarketInfoWithDataAndCandles,
never,
MarketCandlesQueryVariables
>([marketInfoProvider, marketDataProvider, marketCandlesProvider], (parts) => {
const market: MarketInfo | null = parts[0];
const marketData: MarketData | null = parts[1];
const candles: Candle[] | null = parts[2];
return (
market && {
...market,
data: marketData || undefined,
candles: candles || undefined,
}
);
never
>({
query: MarketInfoNoCandlesDocument,
getData: (responseData: MarketInfoNoCandlesQuery | null) => responseData,
});
@@ -93,6 +93,40 @@ export const marketInfoQuery = (
long: '0.008508132993273576',
},
lpPriceRange: '0.02',
data: {
__typename: 'MarketData',
market: {
__typename: 'Market',
id: '54b78c1b877e106842ae156332ccec740ad98d6bad43143ac6a029501dd7c6e0',
},
midPrice: '5749',
markPrice: '5749',
suppliedStake: '56767',
marketValueProxy: '677678',
targetStake: '56789',
bestBidVolume: '5',
bestOfferVolume: '1',
bestStaticBidVolume: '5',
bestStaticOfferVolume: '1',
openInterest: '0',
bestBidPrice: '681765',
bestOfferPrice: '681769',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
priceMonitoringBounds: [
{
minValidPrice: '654701',
maxValidPrice: '797323',
trigger: {
horizonSecs: 43200,
probability: 0.9999999,
auctionExtensionSecs: 600,
__typename: 'PriceMonitoringTrigger',
},
referencePrice: '722625',
__typename: 'PriceMonitoringBounds',
},
],
},
liquidityMonitoringParameters: {
triggeringRatio: '0',
targetStakeParameters: {
@@ -102,6 +136,7 @@ export const marketInfoQuery = (
},
__typename: 'LiquidityMonitoringParameters',
},
candlesConnection: null,
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
@@ -157,6 +192,13 @@ export const marketInfoQuery = (
},
},
},
depth: {
__typename: 'MarketDepth',
lastTrade: {
__typename: 'Trade',
price: '100',
},
},
},
};
+24 -60
View File
@@ -3,59 +3,40 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type MarketDataUpdateFieldsFragment = { __typename?: 'ObservableMarketData', marketId: string, auctionEnd?: string | null, auctionStart?: string | null, bestBidPrice: string, bestBidVolume: string, bestOfferPrice: string, bestOfferVolume: string, bestStaticBidPrice: string, bestStaticBidVolume: string, bestStaticOfferPrice: string, bestStaticOfferVolume: string, indicativePrice: string, indicativeVolume: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, marketValueProxy: string, markPrice: string, midPrice: string, openInterest: string, staticMidPrice: string, suppliedStake?: string | null, targetStake?: string | null, trigger: Types.AuctionTrigger, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null };
export type MarketDataUpdateFieldsFragment = { __typename?: 'ObservableMarketData', marketId: string, bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null };
export type MarketDataUpdateSubscriptionVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
}>;
export type MarketDataUpdateSubscription = { __typename?: 'Subscription', marketsData: Array<{ __typename?: 'ObservableMarketData', marketId: string, auctionEnd?: string | null, auctionStart?: string | null, bestBidPrice: string, bestBidVolume: string, bestOfferPrice: string, bestOfferVolume: string, bestStaticBidPrice: string, bestStaticBidVolume: string, bestStaticOfferPrice: string, bestStaticOfferVolume: string, indicativePrice: string, indicativeVolume: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, marketValueProxy: string, markPrice: string, midPrice: string, openInterest: string, staticMidPrice: string, suppliedStake?: string | null, targetStake?: string | null, trigger: Types.AuctionTrigger, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null }> };
export type MarketDataUpdateSubscription = { __typename?: 'Subscription', marketsData: Array<{ __typename?: 'ObservableMarketData', marketId: string, bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null }> };
export type MarketDataFieldsFragment = { __typename?: 'MarketData', auctionEnd?: string | null, auctionStart?: string | null, bestBidPrice: string, bestBidVolume: string, bestOfferPrice: string, bestOfferVolume: string, bestStaticBidPrice: string, bestStaticBidVolume: string, bestStaticOfferPrice: string, bestStaticOfferVolume: string, indicativePrice: string, indicativeVolume: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, marketValueProxy: string, markPrice: string, midPrice: string, openInterest: string, staticMidPrice: string, suppliedStake?: string | null, targetStake?: string | null, trigger: Types.AuctionTrigger, market: { __typename?: 'Market', id: string }, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null };
export type MarketDataFieldsFragment = { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, market: { __typename?: 'Market', id: string } };
export type MarketDataQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
}>;
export type MarketDataQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', data?: { __typename?: 'MarketData', auctionEnd?: string | null, auctionStart?: string | null, bestBidPrice: string, bestBidVolume: string, bestOfferPrice: string, bestOfferVolume: string, bestStaticBidPrice: string, bestStaticBidVolume: string, bestStaticOfferPrice: string, bestStaticOfferVolume: string, indicativePrice: string, indicativeVolume: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, marketValueProxy: string, markPrice: string, midPrice: string, openInterest: string, staticMidPrice: string, suppliedStake?: string | null, targetStake?: string | null, trigger: Types.AuctionTrigger, market: { __typename?: 'Market', id: string }, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null } | null } }> } | null };
export type MarketDataQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', data?: { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, market: { __typename?: 'Market', id: string } } | null } }> } | null };
export const MarketDataUpdateFieldsFragmentDoc = gql`
fragment MarketDataUpdateFields on ObservableMarketData {
marketId
auctionEnd
auctionStart
bestBidPrice
bestBidVolume
bestOfferPrice
bestOfferVolume
bestStaticBidPrice
bestStaticBidVolume
bestStaticOfferPrice
bestStaticOfferVolume
indicativePrice
indicativeVolume
marketState
marketTradingMode
marketValueProxy
markPrice
midPrice
openInterest
priceMonitoringBounds {
minValidPrice
maxValidPrice
trigger {
horizonSecs
probability
auctionExtensionSecs
}
referencePrice
}
staticMidPrice
suppliedStake
targetStake
trigger
staticMidPrice
marketTradingMode
marketState
indicativeVolume
indicativePrice
bestStaticBidPrice
bestStaticOfferPrice
targetStake
suppliedStake
}
`;
export const MarketDataFieldsFragmentDoc = gql`
@@ -63,38 +44,21 @@ export const MarketDataFieldsFragmentDoc = gql`
market {
id
}
auctionEnd
auctionStart
bestBidPrice
bestBidVolume
bestOfferPrice
bestOfferVolume
bestStaticBidPrice
bestStaticBidVolume
bestStaticOfferPrice
bestStaticOfferVolume
indicativePrice
indicativeVolume
marketState
marketTradingMode
marketValueProxy
markPrice
midPrice
openInterest
priceMonitoringBounds {
minValidPrice
maxValidPrice
trigger {
horizonSecs
probability
auctionExtensionSecs
}
referencePrice
}
staticMidPrice
suppliedStake
targetStake
trigger
staticMidPrice
marketTradingMode
marketState
indicativeVolume
indicativePrice
bestStaticBidPrice
bestStaticOfferPrice
targetStake
suppliedStake
auctionStart
auctionEnd
}
`;
export const MarketDataUpdateDocument = gql`
@@ -13,14 +13,13 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
const { data, error, loading, reload } = useDataProvider({
dataProvider,
skipUpdates: true,
variables: undefined,
});
return (
<div className="h-full relative">
<MarketListTable
rowData={error ? [] : data}
suppressLoadingOverlay
suppressNoRowsOverlay
noRowsOverlayComponent={() => null}
onRowClicked={(rowEvent: RowClickedEvent) => {
const { data, event } = rowEvent;
// filters out clicks on the symbol column because it should display asset details
@@ -1,7 +1,6 @@
import { makeDataProvider } from '@vegaprotocol/utils';
import type {
MarketCandlesQuery,
MarketCandlesQueryVariables,
MarketCandlesUpdateSubscription,
MarketCandlesFieldsFragment,
} from './__generated__/market-candles';
@@ -37,8 +36,7 @@ export const marketCandlesProvider = makeDataProvider<
MarketCandlesQuery,
Candle[],
MarketCandlesUpdateSubscription,
Candle,
MarketCandlesQueryVariables
Candle
>({
query: MarketCandlesDocument,
subscriptionQuery: MarketCandlesUpdateDocument,
@@ -1,4 +1,5 @@
import produce from 'immer';
import { useMemo } from 'react';
import { makeDataProvider, makeDerivedDataProvider } from '@vegaprotocol/utils';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import {
@@ -10,7 +11,6 @@ import type {
MarketDataFieldsFragment,
MarketDataUpdateSubscription,
MarketDataUpdateFieldsFragment,
MarketDataQueryVariables,
} from './__generated__/market-data';
export type MarketData = MarketDataFieldsFragment;
@@ -29,7 +29,7 @@ const update = (
};
const getData = (responseData: MarketDataQuery | null): MarketData | null =>
responseData?.marketsConnection?.edges[0]?.node?.data || null;
responseData?.marketsConnection?.edges[0].node.data || null;
const getDelta = (
subscriptionData: MarketDataUpdateSubscription
@@ -39,8 +39,7 @@ export const marketDataProvider = makeDataProvider<
MarketDataQuery,
MarketData,
MarketDataUpdateSubscription,
MarketDataUpdateFieldsFragment,
MarketDataQueryVariables
MarketDataUpdateFieldsFragment
>({
query: MarketDataDocument,
subscriptionQuery: MarketDataUpdateDocument,
@@ -49,12 +48,6 @@ export const marketDataProvider = makeDataProvider<
getDelta,
});
export const markPriceProvider = makeDerivedDataProvider<
string,
never,
MarketDataQueryVariables
>([marketDataProvider], ([marketData]) => (marketData as MarketData).markPrice);
export type StaticMarketData = Pick<
MarketData,
| 'marketTradingMode'
@@ -70,8 +63,7 @@ export type StaticMarketData = Pick<
export const staticMarketDataProvider = makeDerivedDataProvider<
StaticMarketData,
never,
MarketDataQueryVariables
never
>([marketDataProvider], (parts, variables, prevData) => {
const marketData = parts[0] as ReturnType<typeof getData>;
if (!marketData) {
@@ -97,9 +89,10 @@ export const staticMarketDataProvider = makeDerivedDataProvider<
});
export const useStaticMarketData = (marketId?: string, skip?: boolean) => {
const variables = useMemo(() => ({ marketId }), [marketId]);
return useDataProvider({
dataProvider: staticMarketDataProvider,
variables: { marketId: marketId || '' },
variables,
skip: skip || !marketId,
});
};
+20 -56
View File
@@ -1,37 +1,18 @@
fragment MarketDataUpdateFields on ObservableMarketData {
marketId
auctionEnd
auctionStart
bestBidPrice
bestBidVolume
bestOfferPrice
bestOfferVolume
bestStaticBidPrice
bestStaticBidVolume
bestStaticOfferPrice
bestStaticOfferVolume
indicativePrice
indicativeVolume
marketState
marketTradingMode
marketValueProxy
markPrice
midPrice
openInterest
priceMonitoringBounds {
minValidPrice
maxValidPrice
trigger {
horizonSecs
probability
auctionExtensionSecs
}
referencePrice
}
staticMidPrice
suppliedStake
targetStake
trigger
staticMidPrice
marketTradingMode
marketState
indicativeVolume
indicativePrice
bestStaticBidPrice
bestStaticOfferPrice
targetStake
suppliedStake
}
subscription MarketDataUpdate($marketId: ID!) {
@@ -44,38 +25,21 @@ fragment MarketDataFields on MarketData {
market {
id
}
auctionEnd
auctionStart
bestBidPrice
bestBidVolume
bestOfferPrice
bestOfferVolume
bestStaticBidPrice
bestStaticBidVolume
bestStaticOfferPrice
bestStaticOfferVolume
indicativePrice
indicativeVolume
marketState
marketTradingMode
marketValueProxy
markPrice
midPrice
openInterest
priceMonitoringBounds {
minValidPrice
maxValidPrice
trigger {
horizonSecs
probability
auctionExtensionSecs
}
referencePrice
}
staticMidPrice
suppliedStake
targetStake
trigger
staticMidPrice
marketTradingMode
marketState
indicativeVolume
indicativePrice
bestStaticBidPrice
bestStaticOfferPrice
targetStake
suppliedStake
auctionStart
auctionEnd
}
query MarketData($marketId: ID!) {
+20 -48
View File
@@ -44,62 +44,34 @@ const marketDataFields: MarketDataFieldsFragment = {
id: 'market-0',
__typename: 'Market',
},
auctionEnd: '2022-06-21T17:18:43.484055236Z',
auctionStart: '2022-06-21T17:18:43.484055236Z',
bestBidPrice: '4412690058',
bestBidVolume: '1',
bestOfferPrice: '4812690058',
bestOfferVolume: '3',
bestStaticBidPrice: '4512690058',
bestStaticBidVolume: '2',
bestStaticOfferPrice: '4712690058',
bestStaticOfferVolume: '4',
indicativePrice: '0',
indicativeVolume: '0',
marketState: Schema.MarketState.STATE_ACTIVE,
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
marketValueProxy: '2000000',
markPrice: '4612690058',
midPrice: '4612690000',
openInterest: '0',
priceMonitoringBounds: [
{
minValidPrice: '654701',
maxValidPrice: '797323',
trigger: {
horizonSecs: 43200,
probability: 0.9999999,
auctionExtensionSecs: 600,
__typename: 'PriceMonitoringTrigger',
},
referencePrice: '722625',
__typename: 'PriceMonitoringBounds',
},
],
staticMidPrice: '4612690001',
suppliedStake: '1000',
auctionEnd: '2022-06-21T17:18:43.484055236Z',
targetStake: '1000000',
suppliedStake: '1000',
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
marketState: Schema.MarketState.STATE_ACTIVE,
staticMidPrice: '0',
indicativePrice: '0',
bestStaticBidPrice: '0',
bestStaticOfferPrice: '0',
indicativeVolume: '0',
bestBidPrice: '0',
bestOfferPrice: '0',
markPrice: '4612690058',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
};
const marketDataUpdateFields: MarketDataUpdateFieldsFragment = {
bestBidPrice: '0',
bestBidVolume: '0',
bestOfferPrice: '0',
bestOfferVolume: '0',
bestStaticBidPrice: '0',
bestStaticBidVolume: '0',
bestStaticOfferPrice: '0',
bestStaticOfferVolume: '0',
indicativePrice: '0',
indicativeVolume: '0',
marketId: 'market-0',
marketState: Schema.MarketState.STATE_ACTIVE,
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
marketValueProxy: '',
markPrice: '4612690058',
midPrice: '0',
openInterest: '0',
marketState: Schema.MarketState.STATE_ACTIVE,
staticMidPrice: '0',
indicativePrice: '0',
bestStaticBidPrice: '0',
bestStaticOfferPrice: '0',
indicativeVolume: '0',
bestBidPrice: '0',
bestOfferPrice: '0',
markPrice: '4612690058',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
};
@@ -1,9 +1,6 @@
import { makeDataProvider } from '@vegaprotocol/utils';
import { MarketsCandlesDocument } from './__generated__/markets-candles';
import type {
MarketsCandlesQuery,
MarketsCandlesQueryVariables,
} from './__generated__/markets-candles';
import type { MarketsCandlesQuery } from './__generated__/markets-candles';
import type { Candle } from './market-candles-provider';
export interface MarketCandles {
@@ -25,8 +22,7 @@ export const marketsCandlesProvider = makeDataProvider<
MarketsCandlesQuery,
MarketCandles[],
never,
never,
MarketsCandlesQueryVariables
never
>({
query: MarketsCandlesDocument,
getData,
+5 -9
View File
@@ -4,8 +4,6 @@ import type {
MarketsQuery,
MarketFieldsFragment,
} from './__generated__/markets';
import type { MarketsCandlesQueryVariables } from './__generated__/markets-candles';
import { marketsDataProvider } from './markets-data-provider';
import { marketDataProvider } from './market-data-provider';
import { marketsCandlesProvider } from './markets-candles-provider';
@@ -39,7 +37,7 @@ export const marketProvider = makeDerivedDataProvider<
never,
{ marketId: string }
>(
[(callback, client) => marketsProvider(callback, client, undefined)],
[marketsProvider],
([markets], variables) =>
((markets as ReturnType<typeof getData>) || []).find(
(market) => market.id === variables?.marketId
@@ -86,11 +84,10 @@ const addCandles = <T extends Market>(
export const marketsWithCandlesProvider = makeDerivedDataProvider<
MarketMaybeWithCandles[],
never,
MarketsCandlesQueryVariables
never
>(
[
(callback, client) => activeMarketsProvider(callback, client, undefined),
(callback, client) => activeMarketsProvider(callback, client),
marketsCandlesProvider,
],
(parts) => addCandles(parts[0] as Market[], parts[1] as MarketCandles[])
@@ -116,11 +113,10 @@ export type MarketMaybeWithDataAndCandles = MarketMaybeWithData &
export const marketListProvider = makeDerivedDataProvider<
MarketMaybeWithDataAndCandles[],
never,
MarketsCandlesQueryVariables
never
>(
[
(callback, client) => marketsWithDataProvider(callback, client, undefined),
(callback, client) => marketsWithDataProvider(callback, client),
marketsCandlesProvider,
],
(parts) =>
@@ -76,9 +76,7 @@ const orderMatchFilters = (
return true;
};
const getData = (
responseData: OrdersQuery | null
): Edge<OrderFieldsFragment>[] =>
const getData = (responseData: OrdersQuery | null) =>
responseData?.party?.ordersConnection?.edges || [];
const getDelta = (subscriptionData: OrdersUpdateSubscription) =>
@@ -144,19 +142,14 @@ export const update = (
__typename: 'Order',
},
cursor: '',
__typename: 'OrderEdge',
});
}
});
});
};
export const ordersProvider = makeDataProvider<
OrdersQuery,
ReturnType<typeof getData>,
OrdersUpdateSubscription,
ReturnType<typeof getDelta>,
OrdersQueryVariables
>({
export const ordersProvider = makeDataProvider({
query: OrdersDocument,
subscriptionQuery: OrdersUpdateDocument,
update,
@@ -175,10 +168,7 @@ export const ordersWithMarketProvider = makeDerivedDataProvider<
Order[],
OrdersQueryVariables
>(
[
ordersProvider,
(callback, client) => marketsProvider(callback, client, undefined),
],
[ordersProvider, marketsProvider],
(partsData): OrderEdge[] =>
((partsData[0] as ReturnType<typeof getData>) || []).map((edge) => ({
cursor: edge.cursor,
@@ -193,13 +183,7 @@ export const ordersWithMarketProvider = makeDerivedDataProvider<
combineInsertionData<Order>
);
const hasActiveOrderProviderInternal = makeDataProvider<
OrdersQuery,
boolean,
OrdersUpdateSubscription,
ReturnType<typeof getDelta>,
OrdersQueryVariables
>({
const hasActiveOrderProviderInternal = makeDataProvider({
query: OrdersDocument,
subscriptionQuery: OrdersUpdateDocument,
update: (
@@ -9,8 +9,6 @@ import type {
} from 'ag-grid-community';
import { Button } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import type { GridReadyEvent } from 'ag-grid-community';
import { OrderListTable } from '../order-list/order-list';
import { useOrderListData } from './use-order-list-data';
import { useHasActiveOrder } from '../../order-hooks/use-has-active-order';
@@ -158,16 +156,6 @@ export const OrderListManager = ({
},
[create]
);
const onGridReady = useCallback(
(event: GridReadyEvent) => {
event.api.setDatasource({
getRows,
});
},
[getRows]
);
const cancelAll = useCallback(
(marketId?: string) => {
create({
@@ -189,7 +177,7 @@ export const OrderListManager = ({
<OrderListTable
ref={gridRef}
rowModelType="infinite"
onGridReady={onGridReady}
datasource={{ getRows }}
onBodyScrollEnd={onBodyScrollEnd}
onBodyScroll={onBodyScroll}
onFilterChanged={onFilterChanged}

Some files were not shown because too many files have changed in this diff Show More