feat: liquidity provisions view (#1133)
* feat(#473): add positions metrics data provider * feat(#473) add positions stats * feat(#473) add positions stats * feat(#473): add positions stats * feat(#473): add positions stats * feat(#473): position metrics, test and refactoring * feat(#473): add unit tests to positions table * feat(#473): fix spelling, order positions by updated at desc * feat(#473): protect from division by 0 * feat(#473): fix trading positions e2e tests * feat(#473): fix e2e data mocks * feat(#473): post code review clean up * feat(#993): dependencies handling in data provider * feat(#993): fix e2e tests data mocks * feat(#993): remove position metrics mocks, add market data market id * feat: #994 add price monitoring bounds and candles update interface * fix: move best bid price to diff section * feat(#993): add missing mocks, fix combine function * fix: add insurance pool and calc volume 24h * feat: display some oracle min info, asset id, insurance pool, move open interest and 24hVol * fix: add market-info.cy.ts case * fix: remove # from numbered price monitoring settings * fix: add insurance pool test * fix: format 24hvol * feat(#993): set loading initially to true, add unit tests * feat(#993): cleanup, add comments * feat(#993): remove undefined from client type * fix: remove indicativeVolume and oracleSpecBinding from market info * feat(#993): cosmetic changes * fix: add oracleSpecBinding back * Update libs/deal-ticket/src/components/info-market.tsx Co-authored-by: botond <105208209+notbot00@users.noreply.github.com> * feat: add initial queries * fix: memo yesterday's timestamp * fix: add back info * fix: update query * fix: add view full oracle details link and update mappings * fix: regen code, make link reactnode, fix index.ts * feat: add liquidity lib, refactor info market * fix: remove liquidity query from deal-ticket * feat:(#993): pass informaton about update callback cause * fix: small ui tweaks * fix: display in grid * feat: navigate to oracle by termination id * feat: #491 add use liquidity provision merging * fix: remove logs, add extra check on my liquidity provision * fix: type number trivially inferred from a number literal, remove type annotation * fix: cypress tests and formatting for market info * Update libs/deal-ticket/src/components/market-info/info-market.tsx * fix: use position decimal places for stake and market value proxy * fix: #491 use size/position decimal places for obligation, supplied and commitment amount * fix: add size component and use decimal places * fix: update readme liquidity * fix: #491 add correct asset decimal formatters * Update libs/deal-ticket/src/components/market-info/tooltip-mapping.tsx Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com> * fix: make link instead of button to open liquidity * fix: #491 add liquidity page, link to trading mode tooltip, tabs hidden or choose active * fix: remove LP dialog, use only link to page * fix: add market id in LP view * fix: follow trade grid design * fix: add one line tabs , remove link styling, remove any, add value formatters * fix: remove falsy check LP undefined * fix: keep date formatter in LP table * fix: add generic type market info, hooks in body function * fix: revert number formatters * fix: use one param only in network params query * fix: use network param in web3 lib * fix: move lp container to trading app * fix: remove resizable panel * feat: add header component, remove isEstimate * chore: remove unnecessary type cast * fix: fix build with children map clone element * chore: lint * fix: move use network params to react helpers * fix: add const for LP tabs * fix: fix formatting on LP page * fix: only show tilde for liquidity monitoring auction end date * fix: market id being rendered twice in market info * chore: fix lint * fix: types for generate withdraw form query * chore: fix intermittent failing withdrawal test * Update libs/deal-ticket/src/components/market-info/info-market.tsx * chore: add another wait for market Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com> Co-authored-by: botond <105208209+notbot00@users.noreply.github.com> Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com> Co-authored-by: Matthew Russell <mattrussell36@gmail.com> Co-authored-by: Joe <joe@vega.xyz>
This commit is contained in:
parent
fa6ddcfdf1
commit
cae6162a7f
@ -1,27 +0,0 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
|
||||||
import { gql } from '@apollo/client';
|
|
||||||
|
|
||||||
import type { NetworkParams } from './__generated__/NetworkParams';
|
|
||||||
|
|
||||||
export const NETWORK_PARAMS_QUERY = gql`
|
|
||||||
query NetworkParams {
|
|
||||||
networkParameters {
|
|
||||||
key
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export function useNetworkParam(params: string[]) {
|
|
||||||
const { data, loading, error } = useQuery<NetworkParams, never>(
|
|
||||||
NETWORK_PARAMS_QUERY
|
|
||||||
);
|
|
||||||
const foundParams = data?.networkParameters
|
|
||||||
?.filter((p) => params.includes(p.key))
|
|
||||||
.sort((a, b) => params.indexOf(a.key) - params.indexOf(b.key));
|
|
||||||
return {
|
|
||||||
data: foundParams ? foundParams.map((f) => f.value) : null,
|
|
||||||
loading,
|
|
||||||
error,
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,8 +1,8 @@
|
|||||||
|
import { useNetworkParams } from '@vegaprotocol/react-helpers';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { NetworkParams } from '../../../config';
|
import { NetworkParams } from '../../../config';
|
||||||
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
||||||
import { useNetworkParam } from '../../../hooks/use-network-param';
|
|
||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { addDecimal } from '../../../lib/decimals';
|
import { addDecimal } from '../../../lib/decimals';
|
||||||
import type {
|
import type {
|
||||||
@ -16,7 +16,7 @@ const useProposalNetworkParams = ({
|
|||||||
}: {
|
}: {
|
||||||
proposal: Proposals_proposals;
|
proposal: Proposals_proposals;
|
||||||
}) => {
|
}) => {
|
||||||
const { data, loading } = useNetworkParam([
|
const { data, loading } = useNetworkParams([
|
||||||
NetworkParams.GOV_UPDATE_MARKET_REQUIRED_MAJORITY,
|
NetworkParams.GOV_UPDATE_MARKET_REQUIRED_MAJORITY,
|
||||||
NetworkParams.GOV_UPDATE_MARKET_REQUIRED_PARTICIPATION,
|
NetworkParams.GOV_UPDATE_MARKET_REQUIRED_PARTICIPATION,
|
||||||
NetworkParams.GOV_NEW_MARKET_REQUIRED_MAJORITY,
|
NetworkParams.GOV_NEW_MARKET_REQUIRED_MAJORITY,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { Button, Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
import { Button, Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { formatDistance } from 'date-fns';
|
import { formatDistance } from 'date-fns';
|
||||||
// @ts-ignore No types availabel for duration-js
|
// @ts-ignore No types available for duration-js
|
||||||
import Duration from 'duration-js';
|
import Duration from 'duration-js';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -15,10 +15,10 @@ import {
|
|||||||
AppStateActionType,
|
AppStateActionType,
|
||||||
useAppState,
|
useAppState,
|
||||||
} from '../../../contexts/app-state/app-state-context';
|
} from '../../../contexts/app-state/app-state-context';
|
||||||
import { useNetworkParam } from '../../../hooks/use-network-param';
|
|
||||||
import type { Rewards } from './__generated__/Rewards';
|
import type { Rewards } from './__generated__/Rewards';
|
||||||
import { RewardInfo } from './reward-info';
|
import { RewardInfo } from './reward-info';
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
|
import { useNetworkParams } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
export const REWARDS_QUERY = gql`
|
export const REWARDS_QUERY = gql`
|
||||||
query Rewards($partyId: ID!) {
|
query Rewards($partyId: ID!) {
|
||||||
@ -77,7 +77,7 @@ export const RewardsIndex = () => {
|
|||||||
data: rewardAssetData,
|
data: rewardAssetData,
|
||||||
loading: rewardAssetLoading,
|
loading: rewardAssetLoading,
|
||||||
error: rewardAssetError,
|
error: rewardAssetError,
|
||||||
} = useNetworkParam([
|
} = useNetworkParams([
|
||||||
NetworkParams.REWARD_ASSET,
|
NetworkParams.REWARD_ASSET,
|
||||||
NetworkParams.REWARD_PAYOUT_DURATION,
|
NetworkParams.REWARD_PAYOUT_DURATION,
|
||||||
]);
|
]);
|
||||||
|
@ -7,7 +7,6 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
import { TokenInput } from '../../components/token-input';
|
import { TokenInput } from '../../components/token-input';
|
||||||
import { NetworkParams } from '../../config';
|
import { NetworkParams } from '../../config';
|
||||||
import { useAppState } from '../../contexts/app-state/app-state-context';
|
import { useAppState } from '../../contexts/app-state/app-state-context';
|
||||||
import { useNetworkParam } from '../../hooks/use-network-param';
|
|
||||||
import { useSearchParams } from '../../hooks/use-search-params';
|
import { useSearchParams } from '../../hooks/use-search-params';
|
||||||
import { BigNumber } from '../../lib/bignumber';
|
import { BigNumber } from '../../lib/bignumber';
|
||||||
import { addDecimal, removeDecimal } from '../../lib/decimals';
|
import { addDecimal, removeDecimal } from '../../lib/decimals';
|
||||||
@ -31,6 +30,7 @@ import type {
|
|||||||
UndelegateSubmissionBody,
|
UndelegateSubmissionBody,
|
||||||
} from '@vegaprotocol/wallet';
|
} from '@vegaprotocol/wallet';
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
|
import { useNetworkParam } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
export const PARTY_DELEGATIONS_QUERY = gql`
|
export const PARTY_DELEGATIONS_QUERY = gql`
|
||||||
query PartyDelegations($partyId: ID!) {
|
query PartyDelegations($partyId: ID!) {
|
||||||
@ -103,9 +103,9 @@ export const StakingForm = ({
|
|||||||
setAmount('');
|
setAmount('');
|
||||||
}, [action, setAmount]);
|
}, [action, setAmount]);
|
||||||
|
|
||||||
const { data } = useNetworkParam([
|
const { data } = useNetworkParam(
|
||||||
NetworkParams.VALIDATOR_DELEGATION_MIN_AMOUNT,
|
NetworkParams.VALIDATOR_DELEGATION_MIN_AMOUNT
|
||||||
]);
|
);
|
||||||
|
|
||||||
const minTokensWithDecimals = React.useMemo(() => {
|
const minTokensWithDecimals = React.useMemo(() => {
|
||||||
const minTokens = new BigNumber(data && data.length === 1 ? data[0] : '');
|
const minTokens = new BigNumber(data && data.length === 1 ? data[0] : '');
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import { MarketState } from '@vegaprotocol/types';
|
import {
|
||||||
|
MarketState,
|
||||||
|
MarketStateMapping,
|
||||||
|
MarketTradingModeMapping,
|
||||||
|
} from '@vegaprotocol/types';
|
||||||
import { mockTradingPage } from '../support/trading';
|
import { mockTradingPage } from '../support/trading';
|
||||||
|
|
||||||
const marketInfoBtn = 'Info';
|
const marketInfoBtn = 'Info';
|
||||||
@ -51,8 +55,12 @@ describe('market info is displayed', () => {
|
|||||||
validateMarketDataRow(0, 'Name', 'ETHBTC Quarterly (30 Jun 2022)');
|
validateMarketDataRow(0, 'Name', 'ETHBTC Quarterly (30 Jun 2022)');
|
||||||
validateMarketDataRow(1, 'Decimal Places', '2');
|
validateMarketDataRow(1, 'Decimal Places', '2');
|
||||||
validateMarketDataRow(2, 'Position Decimal Places', '0');
|
validateMarketDataRow(2, 'Position Decimal Places', '0');
|
||||||
validateMarketDataRow(3, 'Trading Mode', 'Trading mode continuous');
|
validateMarketDataRow(
|
||||||
validateMarketDataRow(4, 'State', 'STATE_ACTIVE');
|
3,
|
||||||
|
'Trading Mode',
|
||||||
|
MarketTradingModeMapping.TRADING_MODE_CONTINUOUS
|
||||||
|
);
|
||||||
|
validateMarketDataRow(4, 'State', MarketStateMapping.STATE_ACTIVE);
|
||||||
validateMarketDataRow(5, 'Market ID', 'market-0');
|
validateMarketDataRow(5, 'Market ID', 'market-0');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ describe('markets table', () => {
|
|||||||
|
|
||||||
it('renders markets correctly', () => {
|
it('renders markets correctly', () => {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
|
cy.wait('@Market');
|
||||||
cy.wait('@MarketList');
|
cy.wait('@MarketList');
|
||||||
cy.get('[data-testid^="market-link-"]')
|
cy.get('[data-testid^="market-link-"]')
|
||||||
.should('not.be.empty')
|
.should('not.be.empty')
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||||
import { connectEthereumWallet } from '../support/ethereum-wallet';
|
import { connectEthereumWallet } from '../support/ethereum-wallet';
|
||||||
|
import { generateAccounts } from '../support/mocks/generate-accounts';
|
||||||
import { generateNetworkParameters } from '../support/mocks/generate-network-parameters';
|
import { generateNetworkParameters } from '../support/mocks/generate-network-parameters';
|
||||||
import { generateWithdrawFormQuery } from '../support/mocks/generate-withdraw-page-query';
|
import { generateWithdrawFormQuery } from '../support/mocks/generate-withdraw-page-query';
|
||||||
import { generateWithdrawals } from '../support/mocks/generate-withdrawals';
|
import { generateWithdrawals } from '../support/mocks/generate-withdrawals';
|
||||||
@ -20,6 +21,7 @@ describe('withdraw', () => {
|
|||||||
aliasQuery(req, 'Withdrawals', generateWithdrawals());
|
aliasQuery(req, 'Withdrawals', generateWithdrawals());
|
||||||
aliasQuery(req, 'NetworkParamsQuery', generateNetworkParameters());
|
aliasQuery(req, 'NetworkParamsQuery', generateNetworkParameters());
|
||||||
aliasQuery(req, 'WithdrawFormQuery', generateWithdrawFormQuery());
|
aliasQuery(req, 'WithdrawFormQuery', generateWithdrawFormQuery());
|
||||||
|
aliasQuery(req, 'Accounts', generateAccounts());
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.visit('/portfolio');
|
cy.visit('/portfolio');
|
||||||
|
@ -71,6 +71,18 @@ export const generateAccounts = (
|
|||||||
decimals: 5,
|
decimals: 5,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
__typename: 'Account',
|
||||||
|
type: AccountType.ACCOUNT_TYPE_GENERAL,
|
||||||
|
balance: '100000000',
|
||||||
|
market: null,
|
||||||
|
asset: {
|
||||||
|
__typename: 'Asset',
|
||||||
|
id: 'asset-0',
|
||||||
|
symbol: 'AST0',
|
||||||
|
decimals: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -86,7 +86,9 @@ export const generateMarketInfoQuery = (
|
|||||||
id: '54b78c1b877e106842ae156332ccec740ad98d6bad43143ac6a029501dd7c6e0',
|
id: '54b78c1b877e106842ae156332ccec740ad98d6bad43143ac6a029501dd7c6e0',
|
||||||
},
|
},
|
||||||
markPrice: '5749',
|
markPrice: '5749',
|
||||||
indicativeVolume: '0',
|
suppliedStake: '56767',
|
||||||
|
marketValueProxy: '677678',
|
||||||
|
targetStake: '56789',
|
||||||
bestBidVolume: '5',
|
bestBidVolume: '5',
|
||||||
bestOfferVolume: '1',
|
bestOfferVolume: '1',
|
||||||
bestStaticBidVolume: '5',
|
bestStaticBidVolume: '5',
|
||||||
@ -146,6 +148,7 @@ export const generateMarketInfoQuery = (
|
|||||||
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||||
symbol: 'tBTC',
|
symbol: 'tBTC',
|
||||||
name: 'tBTC TEST',
|
name: 'tBTC TEST',
|
||||||
|
decimals: 1,
|
||||||
},
|
},
|
||||||
oracleSpecForSettlementPrice: {
|
oracleSpecForSettlementPrice: {
|
||||||
__typename: 'OracleSpec',
|
__typename: 'OracleSpec',
|
||||||
|
@ -1,66 +1,69 @@
|
|||||||
import { AccountType } from '@vegaprotocol/types';
|
import { AccountType } from '@vegaprotocol/types';
|
||||||
|
import type {
|
||||||
|
WithdrawFormQuery,
|
||||||
|
WithdrawFormQuery_assetsConnection_edges,
|
||||||
|
WithdrawFormQuery_party_accounts,
|
||||||
|
WithdrawFormQuery_party_withdrawals,
|
||||||
|
} from '@vegaprotocol/withdraws';
|
||||||
import merge from 'lodash/merge';
|
import merge from 'lodash/merge';
|
||||||
import type { PartialDeep } from 'type-fest';
|
import type { PartialDeep } from 'type-fest';
|
||||||
|
|
||||||
export const generateWithdrawFormQuery = (
|
export const generateWithdrawFormQuery = (
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
override?: PartialDeep<WithdrawFormQuery>
|
||||||
override?: PartialDeep<any>
|
): WithdrawFormQuery => {
|
||||||
) => {
|
const withdrawal: WithdrawFormQuery_party_withdrawals = {
|
||||||
|
id: 'withdrawal-0',
|
||||||
|
txHash: null,
|
||||||
|
__typename: 'Withdrawal',
|
||||||
|
};
|
||||||
|
const account: WithdrawFormQuery_party_accounts = {
|
||||||
|
type: AccountType.ACCOUNT_TYPE_GENERAL,
|
||||||
|
balance: '100000000',
|
||||||
|
asset: {
|
||||||
|
__typename: 'Asset',
|
||||||
|
id: 'asset-0',
|
||||||
|
symbol: 'AST0',
|
||||||
|
},
|
||||||
|
__typename: 'Account',
|
||||||
|
};
|
||||||
|
const assetEdge1: WithdrawFormQuery_assetsConnection_edges = {
|
||||||
|
node: {
|
||||||
|
id: 'asset-0',
|
||||||
|
symbol: 'AST0',
|
||||||
|
name: 'Asset 0',
|
||||||
|
decimals: 5,
|
||||||
|
source: {
|
||||||
|
__typename: 'ERC20',
|
||||||
|
contractAddress: '0x5E4b9aDA947130Fc320a144cd22bC1641e5c9d81',
|
||||||
|
},
|
||||||
|
__typename: 'Asset',
|
||||||
|
},
|
||||||
|
__typename: 'AssetEdge',
|
||||||
|
};
|
||||||
|
const assetEdge2: WithdrawFormQuery_assetsConnection_edges = {
|
||||||
|
node: {
|
||||||
|
id: 'asset-1',
|
||||||
|
symbol: 'AST1',
|
||||||
|
name: 'Asset 1',
|
||||||
|
decimals: 5,
|
||||||
|
source: {
|
||||||
|
__typename: 'ERC20',
|
||||||
|
contractAddress: '0x444b9aDA947130Fc320a144cd22bC1641e5c9d81',
|
||||||
|
},
|
||||||
|
__typename: 'Asset',
|
||||||
|
},
|
||||||
|
__typename: 'AssetEdge',
|
||||||
|
};
|
||||||
const defaultResult = {
|
const defaultResult = {
|
||||||
party: {
|
party: {
|
||||||
id: 'party-0',
|
id: 'party-0',
|
||||||
withdrawals: [
|
withdrawals: [withdrawal],
|
||||||
{
|
accounts: [account],
|
||||||
id: 'withdrawal-0',
|
|
||||||
txHash: null,
|
|
||||||
__typename: 'Withdrawal',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
accounts: [
|
|
||||||
{
|
|
||||||
type: AccountType.ACCOUNT_TYPE_GENERAL,
|
|
||||||
balance: '100000000',
|
|
||||||
asset: {
|
|
||||||
__typename: 'Asset',
|
|
||||||
id: 'asset-0',
|
|
||||||
symbol: 'AST0',
|
|
||||||
},
|
|
||||||
__typename: 'Account',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
__typename: 'Party',
|
__typename: 'Party',
|
||||||
},
|
},
|
||||||
assetsConnection: {
|
assetsConnection: {
|
||||||
edges: [
|
__typename: 'AssetsConnection',
|
||||||
{
|
edges: [assetEdge1, assetEdge2],
|
||||||
node: {
|
|
||||||
id: 'asset-0',
|
|
||||||
symbol: 'AST0',
|
|
||||||
name: 'Asset 0',
|
|
||||||
decimals: 5,
|
|
||||||
source: {
|
|
||||||
__typename: 'ERC20',
|
|
||||||
contractAddress: '0x5E4b9aDA947130Fc320a144cd22bC1641e5c9d81',
|
|
||||||
},
|
|
||||||
__typename: 'Asset',
|
|
||||||
},
|
|
||||||
__typename: 'AssetEdge',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
id: 'asset-1',
|
|
||||||
symbol: 'AST1',
|
|
||||||
name: 'Asset 1',
|
|
||||||
decimals: 5,
|
|
||||||
source: {
|
|
||||||
__typename: 'ERC20',
|
|
||||||
contractAddress: '0x444b9aDA947130Fc320a144cd22bC1641e5c9d81',
|
|
||||||
},
|
|
||||||
__typename: 'Asset',
|
|
||||||
},
|
|
||||||
__typename: 'AssetEdge',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
53
apps/trading/components/header/header.tsx
Normal file
53
apps/trading/components/header/header.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import type { ReactElement, ReactNode } from 'react';
|
||||||
|
import { Children } from 'react';
|
||||||
|
import { cloneElement } from 'react';
|
||||||
|
|
||||||
|
interface TradeMarketHeaderProps {
|
||||||
|
title: ReactNode;
|
||||||
|
children: ReactElement[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Header = ({ title, children }: TradeMarketHeaderProps) => {
|
||||||
|
return (
|
||||||
|
<header className="w-screen xl:px-4 pt-4 border-b border-neutral-300 dark:border-neutral-700">
|
||||||
|
<div className="xl:flex xl:gap-4 items-start">
|
||||||
|
<div className="px-4 mb-2 xl:mb-0 sm:text-lg md:text-xl lg:text-2xl">
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="market-summary"
|
||||||
|
className="flex flex-nowrap items-start xl:flex-1 w-full overflow-x-auto text-xs "
|
||||||
|
>
|
||||||
|
{Children.map(children, (child, index) => {
|
||||||
|
return cloneElement(child, {
|
||||||
|
id: `header-stat-${index}`,
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HeaderStat = ({
|
||||||
|
children,
|
||||||
|
heading,
|
||||||
|
id,
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
heading: string;
|
||||||
|
id?: string;
|
||||||
|
}) => {
|
||||||
|
const itemClass =
|
||||||
|
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-neutral-300 dark:border-neutral-700';
|
||||||
|
const itemHeading = 'text-neutral-400';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={itemClass}>
|
||||||
|
<div id={id} className={itemHeading}>
|
||||||
|
{heading}
|
||||||
|
</div>
|
||||||
|
<div aria-labelledby={id}>{children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
1
apps/trading/components/header/index.ts
Normal file
1
apps/trading/components/header/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './header';
|
@ -10,9 +10,8 @@ import type { Market_market } from '../../pages/markets/__generated__/Market';
|
|||||||
|
|
||||||
type MarketDataGridProps = {
|
type MarketDataGridProps = {
|
||||||
grid: {
|
grid: {
|
||||||
label: string;
|
label: string | ReactNode;
|
||||||
value?: ReactNode;
|
value?: ReactNode;
|
||||||
isEstimate?: boolean;
|
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -20,12 +19,11 @@ const MarketDataGrid = ({ grid }: MarketDataGridProps) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{grid.map(
|
{grid.map(
|
||||||
({ label, value, isEstimate }, index) =>
|
({ label, value }, index) =>
|
||||||
value && (
|
value && (
|
||||||
<div key={index} className="grid grid-cols-2">
|
<div key={index} className="grid grid-cols-2">
|
||||||
<span data-testid="tooltip-label">{label}</span>
|
<span data-testid="tooltip-label">{label}</span>
|
||||||
<span data-testid="tooltip-value">
|
<span data-testid="tooltip-value" className="text-right">
|
||||||
{isEstimate && <span className="ml-[-0.625em]">{'~'}</span>}
|
|
||||||
{value}
|
{value}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -61,12 +59,14 @@ const compileGridData = (market: Market_market) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (market.data?.auctionEnd) {
|
if (market.data?.auctionEnd) {
|
||||||
|
const endDate = getDateTimeFormat().format(
|
||||||
|
new Date(market.data.auctionEnd)
|
||||||
|
);
|
||||||
grid.push({
|
grid.push({
|
||||||
label: isLiquidityMonitoringAuction
|
label: isLiquidityMonitoringAuction
|
||||||
? t('Est auction end')
|
? t('Est auction end')
|
||||||
: t('Auction end'),
|
: t('Auction end'),
|
||||||
value: getDateTimeFormat().format(new Date(market.data.auctionEnd)),
|
value: isLiquidityMonitoringAuction ? `~${endDate}` : endDate,
|
||||||
isEstimate: isLiquidityMonitoringAuction ? true : false,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +79,11 @@ const compileGridData = (market: Market_market) => {
|
|||||||
|
|
||||||
if (isLiquidityMonitoringAuction && market.data?.suppliedStake) {
|
if (isLiquidityMonitoringAuction && market.data?.suppliedStake) {
|
||||||
grid.push({
|
grid.push({
|
||||||
label: t('Current liquidity'),
|
label: (
|
||||||
// @TODO: link this to liquidity view when https://github.com/vegaprotocol/frontend-monorepo/issues/491 is done
|
<Link href={`/liquidity/${market.id}`} target="_blank">
|
||||||
|
{t('Current liquidity')}
|
||||||
|
</Link>
|
||||||
|
),
|
||||||
value: formatStake(market.data.suppliedStake, market),
|
value: formatStake(market.data.suppliedStake, market),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -88,22 +91,24 @@ const compileGridData = (market: Market_market) => {
|
|||||||
if (market.data?.indicativePrice) {
|
if (market.data?.indicativePrice) {
|
||||||
grid.push({
|
grid.push({
|
||||||
label: t('Est uncrossing price'),
|
label: t('Est uncrossing price'),
|
||||||
value: addDecimalsFormatNumber(
|
value:
|
||||||
market.data.indicativePrice,
|
'~' +
|
||||||
market.positionDecimalPlaces
|
addDecimalsFormatNumber(
|
||||||
),
|
market.data.indicativePrice,
|
||||||
isEstimate: true,
|
market.positionDecimalPlaces
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (market.data?.indicativeVolume) {
|
if (market.data?.indicativeVolume) {
|
||||||
grid.push({
|
grid.push({
|
||||||
label: t('Est uncrossing vol'),
|
label: t('Est uncrossing vol'),
|
||||||
value: addDecimalsFormatNumber(
|
value:
|
||||||
market.data.indicativeVolume,
|
'~' +
|
||||||
market.positionDecimalPlaces
|
addDecimalsFormatNumber(
|
||||||
),
|
market.data.indicativeVolume,
|
||||||
isEstimate: true,
|
market.positionDecimalPlaces
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +133,7 @@ export const TradingModeTooltip = ({ market }: TradingModeTooltipProps) => {
|
|||||||
case MarketTradingMode.TRADING_MODE_OPENING_AUCTION: {
|
case MarketTradingMode.TRADING_MODE_OPENING_AUCTION: {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p className="mb-16">
|
<p className="mb-4">
|
||||||
<span>
|
<span>
|
||||||
{t(
|
{t(
|
||||||
'This new market is in an opening auction to determine a fair mid-price before starting continuous trading.'
|
'This new market is in an opening auction to determine a fair mid-price before starting continuous trading.'
|
||||||
@ -150,7 +155,7 @@ export const TradingModeTooltip = ({ market }: TradingModeTooltipProps) => {
|
|||||||
case AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY: {
|
case AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY: {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p data-testid="tooltip-market-info" className="mb-16">
|
<p data-testid="tooltip-market-info" className="mb-4">
|
||||||
<span>
|
<span>
|
||||||
{t(
|
{t(
|
||||||
'This market is in auction until it reaches sufficient liquidity.'
|
'This market is in auction until it reaches sufficient liquidity.'
|
||||||
@ -170,7 +175,7 @@ export const TradingModeTooltip = ({ market }: TradingModeTooltipProps) => {
|
|||||||
case AuctionTrigger.AUCTION_TRIGGER_PRICE: {
|
case AuctionTrigger.AUCTION_TRIGGER_PRICE: {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p className="mb-16">
|
<p className="mb-4">
|
||||||
<span>
|
<span>
|
||||||
{t('This market is in auction due to high price volatility.')}
|
{t('This market is in auction due to high price volatility.')}
|
||||||
</span>{' '}
|
</span>{' '}
|
||||||
|
103
apps/trading/pages/liquidity/[marketId].page.tsx
Normal file
103
apps/trading/pages/liquidity/[marketId].page.tsx
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import { LiquidityTable, useLiquidityProvision } from '@vegaprotocol/liquidity';
|
||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import { LiquidityProvisionStatus } from '@vegaprotocol/types';
|
||||||
|
import { AsyncRenderer, Tab, Tabs } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
|
import { Header, HeaderStat } from '../../components/header';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { useRef, useMemo } from 'react';
|
||||||
|
|
||||||
|
const LiquidityPage = ({ id }: { id?: string }) => {
|
||||||
|
const { query } = useRouter();
|
||||||
|
const { keypair } = useVegaWallet();
|
||||||
|
const gridRef = useRef<AgGridReact | null>(null);
|
||||||
|
|
||||||
|
const partyId = keypair?.pub;
|
||||||
|
// Default to first marketId query item if found
|
||||||
|
const marketId =
|
||||||
|
id || (Array.isArray(query.marketId) ? query.marketId[0] : query.marketId);
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { liquidityProviders, suppliedStake, targetStake, code, symbol },
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
} = useLiquidityProvision({ marketId });
|
||||||
|
|
||||||
|
const myLpEdges = useMemo(
|
||||||
|
() => liquidityProviders.filter((e) => e.party === partyId),
|
||||||
|
[liquidityProviders, partyId]
|
||||||
|
);
|
||||||
|
const activeEdges = useMemo(
|
||||||
|
() =>
|
||||||
|
liquidityProviders.filter(
|
||||||
|
(e) => e.status === LiquidityProvisionStatus.STATUS_ACTIVE
|
||||||
|
),
|
||||||
|
[liquidityProviders]
|
||||||
|
);
|
||||||
|
const inactiveEdges = useMemo(
|
||||||
|
() =>
|
||||||
|
liquidityProviders.filter(
|
||||||
|
(e) => e.status !== LiquidityProvisionStatus.STATUS_ACTIVE
|
||||||
|
),
|
||||||
|
[liquidityProviders]
|
||||||
|
);
|
||||||
|
|
||||||
|
const enum LiquidityTabs {
|
||||||
|
Active = 'active',
|
||||||
|
Inactive = 'inactive',
|
||||||
|
MyLiquidityProvision = 'myLP',
|
||||||
|
}
|
||||||
|
|
||||||
|
const getActiveDefaultId = () => {
|
||||||
|
if (myLpEdges?.length > 0) return LiquidityTabs.MyLiquidityProvision;
|
||||||
|
if (activeEdges?.length) return LiquidityTabs.Active;
|
||||||
|
else if (inactiveEdges?.length > 0) return LiquidityTabs.Inactive;
|
||||||
|
return LiquidityTabs.Active;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AsyncRenderer loading={loading} error={error} data={liquidityProviders}>
|
||||||
|
<div className="h-full grid grid-rows-[min-content_1fr]">
|
||||||
|
<Header
|
||||||
|
title={
|
||||||
|
<Link href={`/markets/${marketId}`}>
|
||||||
|
{`${code} ${t('liquidity provision')}`}
|
||||||
|
</Link>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<HeaderStat heading={t('Target stake')}>
|
||||||
|
<div>{`${targetStake} ${symbol}`}</div>
|
||||||
|
</HeaderStat>
|
||||||
|
<HeaderStat heading={t('Supplied stake')}>
|
||||||
|
<div>{`${suppliedStake} ${symbol}`}</div>
|
||||||
|
</HeaderStat>
|
||||||
|
<HeaderStat heading={t('Market ID')}>
|
||||||
|
<div className="break-word">{marketId}</div>
|
||||||
|
</HeaderStat>
|
||||||
|
</Header>
|
||||||
|
<Tabs active={getActiveDefaultId()}>
|
||||||
|
<Tab
|
||||||
|
id={LiquidityTabs.MyLiquidityProvision}
|
||||||
|
name={t('My liquidity provision')}
|
||||||
|
hidden={!partyId}
|
||||||
|
>
|
||||||
|
<LiquidityTable ref={gridRef} data={myLpEdges} />
|
||||||
|
</Tab>
|
||||||
|
<Tab id={LiquidityTabs.Active} name={t('Active')}>
|
||||||
|
<LiquidityTable ref={gridRef} data={activeEdges} />
|
||||||
|
</Tab>
|
||||||
|
<Tab id={LiquidityTabs.Inactive} name={t('Inactive')}>
|
||||||
|
<LiquidityTable ref={gridRef} data={inactiveEdges} />
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
</AsyncRenderer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
LiquidityPage.getInitialProps = () => ({
|
||||||
|
page: 'liquidity',
|
||||||
|
});
|
||||||
|
|
||||||
|
export default LiquidityPage;
|
1
apps/trading/pages/liquidity/index.ts
Normal file
1
apps/trading/pages/liquidity/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './[marketId].page';
|
@ -5,7 +5,7 @@ import { Interval } from '@vegaprotocol/types';
|
|||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { PageQueryContainer } from '../../components/page-query-container';
|
import { PageQueryContainer } from '../../components/page-query-container';
|
||||||
import { useGlobalStore } from '../../stores';
|
import { useGlobalStore } from '../../stores';
|
||||||
import { TradeGrid, TradePanels } from './trade-grid';
|
import { TradeGrid, TradePanels } from './trade-grid';
|
||||||
@ -91,10 +91,19 @@ const MarketPage = ({ id }: { id?: string }) => {
|
|||||||
|
|
||||||
// Cache timestamp for yesterday to prevent full unmount of market page when
|
// Cache timestamp for yesterday to prevent full unmount of market page when
|
||||||
// a rerender occurs
|
// a rerender occurs
|
||||||
const [yTimestamp] = useState(() => {
|
const yTimestamp = useMemo(() => {
|
||||||
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
||||||
return new Date(yesterday * 1000).toISOString();
|
return new Date(yesterday * 1000).toISOString();
|
||||||
});
|
}, []);
|
||||||
|
|
||||||
|
const variables = useMemo(
|
||||||
|
() => ({
|
||||||
|
marketId: marketId || '',
|
||||||
|
interval: Interval.INTERVAL_I1H,
|
||||||
|
since: yTimestamp,
|
||||||
|
}),
|
||||||
|
[marketId, yTimestamp]
|
||||||
|
);
|
||||||
|
|
||||||
if (!marketId) {
|
if (!marketId) {
|
||||||
return (
|
return (
|
||||||
@ -109,11 +118,7 @@ const MarketPage = ({ id }: { id?: string }) => {
|
|||||||
query={MARKET_QUERY}
|
query={MARKET_QUERY}
|
||||||
data-testid="market"
|
data-testid="market"
|
||||||
options={{
|
options={{
|
||||||
variables: {
|
variables,
|
||||||
marketId,
|
|
||||||
interval: Interval.INTERVAL_I1H,
|
|
||||||
since: yTimestamp,
|
|
||||||
},
|
|
||||||
fetchPolicy: 'network-only',
|
fetchPolicy: 'network-only',
|
||||||
}}
|
}}
|
||||||
render={({ market }) => {
|
render={({ market }) => {
|
||||||
|
@ -1,48 +1,47 @@
|
|||||||
import 'allotment/dist/style.css';
|
|
||||||
import {
|
import {
|
||||||
DealTicketContainer,
|
DealTicketContainer,
|
||||||
MarketInfoContainer,
|
MarketInfoContainer,
|
||||||
} from '@vegaprotocol/deal-ticket';
|
} from '@vegaprotocol/deal-ticket';
|
||||||
import { OrderbookContainer } from '@vegaprotocol/market-depth';
|
import { OrderbookContainer } from '@vegaprotocol/market-depth';
|
||||||
import { SelectMarketPopover } from '@vegaprotocol/market-list';
|
|
||||||
import { OrderListContainer } from '@vegaprotocol/orders';
|
import { OrderListContainer } from '@vegaprotocol/orders';
|
||||||
import { FillsContainer } from '@vegaprotocol/fills';
|
import { FillsContainer } from '@vegaprotocol/fills';
|
||||||
import { PositionsContainer } from '@vegaprotocol/positions';
|
import { PositionsContainer } from '@vegaprotocol/positions';
|
||||||
import {
|
|
||||||
addDecimalsFormatNumber,
|
|
||||||
getDateFormat,
|
|
||||||
t,
|
|
||||||
} from '@vegaprotocol/react-helpers';
|
|
||||||
import { TradesContainer } from '@vegaprotocol/trades';
|
import { TradesContainer } from '@vegaprotocol/trades';
|
||||||
import {
|
|
||||||
AuctionTrigger,
|
|
||||||
AuctionTriggerMapping,
|
|
||||||
MarketTradingMode,
|
|
||||||
MarketTradingModeMapping,
|
|
||||||
} from '@vegaprotocol/types';
|
|
||||||
import { LayoutPriority } from 'allotment';
|
import { LayoutPriority } from 'allotment';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import type { Market_market } from './__generated__/Market';
|
import type { Market_market } from './__generated__/Market';
|
||||||
import type { CandleClose } from '@vegaprotocol/types';
|
|
||||||
import { useGlobalStore } from '../../stores';
|
|
||||||
import { AccountsContainer } from '@vegaprotocol/accounts';
|
import { AccountsContainer } from '@vegaprotocol/accounts';
|
||||||
import { DepthChartContainer } from '@vegaprotocol/market-depth';
|
import { DepthChartContainer } from '@vegaprotocol/market-depth';
|
||||||
import { CandlesChartContainer } from '@vegaprotocol/candles-chart';
|
import { CandlesChartContainer } from '@vegaprotocol/candles-chart';
|
||||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
|
||||||
import { useEnvironment } from '@vegaprotocol/environment';
|
|
||||||
import {
|
import {
|
||||||
Tab,
|
Tab,
|
||||||
Tabs,
|
Tabs,
|
||||||
|
ResizableGrid,
|
||||||
|
ResizableGridPanel,
|
||||||
|
ButtonLink,
|
||||||
|
Tooltip,
|
||||||
PriceCellChange,
|
PriceCellChange,
|
||||||
Link,
|
Link,
|
||||||
Tooltip,
|
|
||||||
ResizableGrid,
|
|
||||||
ButtonLink,
|
|
||||||
ResizableGridPanel,
|
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import {
|
||||||
|
addDecimalsFormatNumber,
|
||||||
|
getDateFormat,
|
||||||
|
t,
|
||||||
|
} from '@vegaprotocol/react-helpers';
|
||||||
|
import { SelectMarketPopover } from '@vegaprotocol/market-list';
|
||||||
|
import { useGlobalStore } from '../../stores';
|
||||||
|
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/environment';
|
||||||
|
import type { CandleClose } from '@vegaprotocol/types';
|
||||||
|
import {
|
||||||
|
AuctionTrigger,
|
||||||
|
AuctionTriggerMapping,
|
||||||
|
MarketTradingMode,
|
||||||
|
MarketTradingModeMapping,
|
||||||
|
} from '@vegaprotocol/types';
|
||||||
import { TradingModeTooltip } from '../../components/trading-mode-tooltip';
|
import { TradingModeTooltip } from '../../components/trading-mode-tooltip';
|
||||||
|
|
||||||
const TradingViews = {
|
const TradingViews = {
|
||||||
|
2
libs/deal-ticket/src/components/deal-ticket/__generated__/index.ts
generated
Normal file
2
libs/deal-ticket/src/components/deal-ticket/__generated__/index.ts
generated
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './DealTicketQuery';
|
||||||
|
export * from './MarketNames';
|
@ -48,7 +48,10 @@ export const DealTicketLimitAmount = ({
|
|||||||
type="number"
|
type="number"
|
||||||
step={priceStep}
|
step={priceStep}
|
||||||
data-testid="order-price"
|
data-testid="order-price"
|
||||||
{...register('price', { required: true, min: 0 })}
|
{...register('price', {
|
||||||
|
required: true,
|
||||||
|
min: 0,
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</div>
|
</div>
|
12
libs/deal-ticket/src/components/deal-ticket/index.ts
Normal file
12
libs/deal-ticket/src/components/deal-ticket/index.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export * from './__generated__';
|
||||||
|
export * from './deal-ticket-amount';
|
||||||
|
export * from './deal-ticket-container';
|
||||||
|
export * from './deal-ticket-limit-amount';
|
||||||
|
export * from './deal-ticket-manager';
|
||||||
|
export * from './deal-ticket-market-amount';
|
||||||
|
export * from './deal-ticket';
|
||||||
|
export * from './expiry-selector';
|
||||||
|
export * from './market-selector';
|
||||||
|
export * from './side-selector';
|
||||||
|
export * from './time-in-force-selector';
|
||||||
|
export * from './type-selector';
|
@ -1,15 +1,2 @@
|
|||||||
export * from './__generated__/DealTicketQuery';
|
|
||||||
export * from './__generated__/MarketInfoQuery';
|
|
||||||
export * from './__generated__/MarketNames';
|
|
||||||
export * from './deal-ticket-amount';
|
|
||||||
export * from './deal-ticket-container';
|
|
||||||
export * from './deal-ticket-limit-amount';
|
|
||||||
export * from './deal-ticket-manager';
|
|
||||||
export * from './deal-ticket-market-amount';
|
|
||||||
export * from './deal-ticket';
|
export * from './deal-ticket';
|
||||||
export * from './expiry-selector';
|
export * from './market-info';
|
||||||
export * from './info-market';
|
|
||||||
export * from './side-selector';
|
|
||||||
export * from './time-in-force-selector';
|
|
||||||
export * from './type-selector';
|
|
||||||
export * from './market-selector';
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// @generated
|
// @generated
|
||||||
// This file was automatically generated and should not be edited.
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
import { Interval, MarketState, AccountType, MarketTradingMode, AuctionTrigger } from "@vegaprotocol/types";
|
import { Interval, MarketState, MarketTradingMode, AccountType, AuctionTrigger } from "@vegaprotocol/types";
|
||||||
|
|
||||||
// ====================================================
|
// ====================================================
|
||||||
// GraphQL query operation: MarketInfoQuery
|
// GraphQL query operation: MarketInfoQuery
|
||||||
@ -191,10 +191,6 @@ export interface MarketInfoQuery_market_data {
|
|||||||
* the mark price (an unsigned integer)
|
* the mark price (an unsigned integer)
|
||||||
*/
|
*/
|
||||||
markPrice: string;
|
markPrice: string;
|
||||||
/**
|
|
||||||
* indicative volume if the auction ended now, 0 if not in auction mode
|
|
||||||
*/
|
|
||||||
indicativeVolume: string;
|
|
||||||
/**
|
/**
|
||||||
* the aggregated volume being bid at the best bid price.
|
* the aggregated volume being bid at the best bid price.
|
||||||
*/
|
*/
|
||||||
@ -211,10 +207,6 @@ export interface MarketInfoQuery_market_data {
|
|||||||
* the aggregated volume being offered at the best static offer price, excluding pegged orders.
|
* the aggregated volume being offered at the best static offer price, excluding pegged orders.
|
||||||
*/
|
*/
|
||||||
bestStaticOfferVolume: string;
|
bestStaticOfferVolume: string;
|
||||||
/**
|
|
||||||
* the sum of the size of all positions greater than 0.
|
|
||||||
*/
|
|
||||||
openInterest: string;
|
|
||||||
/**
|
/**
|
||||||
* the highest price level on an order book for buy orders.
|
* the highest price level on an order book for buy orders.
|
||||||
*/
|
*/
|
||||||
@ -227,6 +219,22 @@ export interface MarketInfoQuery_market_data {
|
|||||||
* what triggered an auction (if an auction was started)
|
* what triggered an auction (if an auction was started)
|
||||||
*/
|
*/
|
||||||
trigger: AuctionTrigger;
|
trigger: AuctionTrigger;
|
||||||
|
/**
|
||||||
|
* the sum of the size of all positions greater than 0.
|
||||||
|
*/
|
||||||
|
openInterest: string;
|
||||||
|
/**
|
||||||
|
* the supplied stake for the market
|
||||||
|
*/
|
||||||
|
suppliedStake: string | null;
|
||||||
|
/**
|
||||||
|
* the amount of stake targeted for this market
|
||||||
|
*/
|
||||||
|
targetStake: string | null;
|
||||||
|
/**
|
||||||
|
* the market value proxy
|
||||||
|
*/
|
||||||
|
marketValueProxy: string;
|
||||||
/**
|
/**
|
||||||
* a list of valid price ranges per associated trigger
|
* a list of valid price ranges per associated trigger
|
||||||
*/
|
*/
|
||||||
@ -287,6 +295,10 @@ export interface MarketInfoQuery_market_tradableInstrument_instrument_product_se
|
|||||||
* The full name of the asset (e.g: Great British Pound)
|
* The full name of the asset (e.g: Great British Pound)
|
||||||
*/
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
|
/**
|
||||||
|
* The precision of the asset. Should match the decimal precision of the asset on its native chain, e.g: for ERC20 assets, it is often 18
|
||||||
|
*/
|
||||||
|
decimals: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MarketInfoQuery_market_tradableInstrument_instrument_product_oracleSpecForSettlementPrice {
|
export interface MarketInfoQuery_market_tradableInstrument_instrument_product_oracleSpecForSettlementPrice {
|
||||||
@ -454,14 +466,14 @@ export interface MarketInfoQuery_market {
|
|||||||
/**
|
/**
|
||||||
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
|
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
|
||||||
* number denominated in the currency of the market. (uint64)
|
* number denominated in the currency of the market. (uint64)
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
* Currency Balance decimalPlaces Real Balance
|
* Currency Balance decimalPlaces Real Balance
|
||||||
* GBP 100 0 GBP 100
|
* GBP 100 0 GBP 100
|
||||||
* GBP 100 2 GBP 1.00
|
* GBP 100 2 GBP 1.00
|
||||||
* GBP 100 4 GBP 0.01
|
* GBP 100 4 GBP 0.01
|
||||||
* GBP 1 4 GBP 0.0001 ( 0.01p )
|
* GBP 1 4 GBP 0.0001 ( 0.01p )
|
||||||
*
|
*
|
||||||
* GBX (pence) 100 0 GBP 1.00 (100p )
|
* GBX (pence) 100 0 GBP 1.00 (100p )
|
||||||
* GBX (pence) 100 2 GBP 0.01 ( 1p )
|
* GBX (pence) 100 2 GBP 0.01 ( 1p )
|
||||||
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )
|
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )
|
||||||
@ -479,6 +491,10 @@ export interface MarketInfoQuery_market {
|
|||||||
* Current state of the market
|
* Current state of the market
|
||||||
*/
|
*/
|
||||||
state: MarketState;
|
state: MarketState;
|
||||||
|
/**
|
||||||
|
* Current mode of execution of the market
|
||||||
|
*/
|
||||||
|
tradingMode: MarketTradingMode;
|
||||||
/**
|
/**
|
||||||
* The proposal that initiated this market
|
* The proposal that initiated this market
|
||||||
*/
|
*/
|
||||||
@ -487,10 +503,6 @@ export interface MarketInfoQuery_market {
|
|||||||
* Get account for a party or market
|
* Get account for a party or market
|
||||||
*/
|
*/
|
||||||
accounts: MarketInfoQuery_market_accounts[] | null;
|
accounts: MarketInfoQuery_market_accounts[] | null;
|
||||||
/**
|
|
||||||
* Current mode of execution of the market
|
|
||||||
*/
|
|
||||||
tradingMode: MarketTradingMode;
|
|
||||||
/**
|
/**
|
||||||
* Fees related data
|
* Fees related data
|
||||||
*/
|
*/
|
1
libs/deal-ticket/src/components/market-info/__generated__/index.ts
generated
Normal file
1
libs/deal-ticket/src/components/market-info/__generated__/index.ts
generated
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './MarketInfoQuery';
|
3
libs/deal-ticket/src/components/market-info/index.ts
Normal file
3
libs/deal-ticket/src/components/market-info/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './__generated__';
|
||||||
|
export * from './info-market-query';
|
||||||
|
export * from './info-market';
|
@ -0,0 +1,110 @@
|
|||||||
|
import {
|
||||||
|
t,
|
||||||
|
addDecimalsFormatNumber,
|
||||||
|
formatNumberPercentage,
|
||||||
|
formatNumber,
|
||||||
|
} from '@vegaprotocol/react-helpers';
|
||||||
|
import {
|
||||||
|
KeyValueTableRow,
|
||||||
|
KeyValueTable,
|
||||||
|
Tooltip,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import startCase from 'lodash/startCase';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
|
import { tooltipMapping } from './tooltip-mapping';
|
||||||
|
|
||||||
|
interface RowProps {
|
||||||
|
field: string;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
value: any;
|
||||||
|
decimalPlaces?: number;
|
||||||
|
asPercentage?: boolean;
|
||||||
|
unformatted?: boolean;
|
||||||
|
assetSymbol?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Row = ({
|
||||||
|
field,
|
||||||
|
value,
|
||||||
|
decimalPlaces,
|
||||||
|
asPercentage,
|
||||||
|
unformatted,
|
||||||
|
assetSymbol = '',
|
||||||
|
}: RowProps) => {
|
||||||
|
const isNumber = typeof value === 'number' || !isNaN(Number(value));
|
||||||
|
const isPrimitive = typeof value === 'string' || isNumber;
|
||||||
|
const className = 'text-black dark:text-white text-ui !px-0 !font-normal';
|
||||||
|
let formattedValue = value;
|
||||||
|
if (isNumber && !unformatted) {
|
||||||
|
if (decimalPlaces) {
|
||||||
|
formattedValue = `${addDecimalsFormatNumber(
|
||||||
|
value,
|
||||||
|
decimalPlaces
|
||||||
|
)} ${assetSymbol}`;
|
||||||
|
} else if (asPercentage && value) {
|
||||||
|
formattedValue = formatNumberPercentage(new BigNumber(value).times(100));
|
||||||
|
} else {
|
||||||
|
formattedValue = `${formatNumber(Number(value))} ${assetSymbol}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isPrimitive) {
|
||||||
|
return (
|
||||||
|
<KeyValueTableRow
|
||||||
|
key={field}
|
||||||
|
inline={isPrimitive}
|
||||||
|
noBorder={true}
|
||||||
|
dtClassName={className}
|
||||||
|
ddClassName={className}
|
||||||
|
>
|
||||||
|
<Tooltip description={tooltipMapping[field]} align="start">
|
||||||
|
<div tabIndex={-1}>{startCase(t(field))}</div>
|
||||||
|
</Tooltip>
|
||||||
|
<span style={{ wordBreak: 'break-word' }}>{formattedValue}</span>
|
||||||
|
</KeyValueTableRow>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface MarketInfoTableProps {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
data: any;
|
||||||
|
decimalPlaces?: number;
|
||||||
|
asPercentage?: boolean;
|
||||||
|
unformatted?: boolean;
|
||||||
|
omits?: string[];
|
||||||
|
link?: ReactNode;
|
||||||
|
assetSymbol?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MarketInfoTable = ({
|
||||||
|
data,
|
||||||
|
decimalPlaces,
|
||||||
|
asPercentage,
|
||||||
|
unformatted,
|
||||||
|
omits = ['__typename'],
|
||||||
|
link,
|
||||||
|
assetSymbol,
|
||||||
|
}: MarketInfoTableProps) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<KeyValueTable>
|
||||||
|
{Object.entries(data)
|
||||||
|
.filter(([key]) => !omits.includes(key))
|
||||||
|
.map(([key, value]) => (
|
||||||
|
<Row
|
||||||
|
key={key}
|
||||||
|
field={key}
|
||||||
|
value={value}
|
||||||
|
decimalPlaces={decimalPlaces}
|
||||||
|
assetSymbol={assetSymbol}
|
||||||
|
asPercentage={asPercentage}
|
||||||
|
unformatted={unformatted || key.toLowerCase().includes('volume')}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</KeyValueTable>
|
||||||
|
{link}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -8,6 +8,7 @@ export const MARKET_INFO_QUERY = gql`
|
|||||||
decimalPlaces
|
decimalPlaces
|
||||||
positionDecimalPlaces
|
positionDecimalPlaces
|
||||||
state
|
state
|
||||||
|
tradingMode
|
||||||
proposal {
|
proposal {
|
||||||
id
|
id
|
||||||
rationale {
|
rationale {
|
||||||
@ -49,15 +50,18 @@ export const MARKET_INFO_QUERY = gql`
|
|||||||
id
|
id
|
||||||
}
|
}
|
||||||
markPrice
|
markPrice
|
||||||
indicativeVolume
|
|
||||||
bestBidVolume
|
bestBidVolume
|
||||||
bestOfferVolume
|
bestOfferVolume
|
||||||
bestStaticBidVolume
|
bestStaticBidVolume
|
||||||
bestStaticOfferVolume
|
bestStaticOfferVolume
|
||||||
openInterest
|
|
||||||
bestBidPrice
|
bestBidPrice
|
||||||
bestOfferPrice
|
bestOfferPrice
|
||||||
trigger
|
trigger
|
||||||
|
openInterest
|
||||||
|
suppliedStake
|
||||||
|
openInterest
|
||||||
|
targetStake
|
||||||
|
marketValueProxy
|
||||||
priceMonitoringBounds {
|
priceMonitoringBounds {
|
||||||
minValidPrice
|
minValidPrice
|
||||||
maxValidPrice
|
maxValidPrice
|
||||||
@ -94,6 +98,7 @@ export const MARKET_INFO_QUERY = gql`
|
|||||||
id
|
id
|
||||||
symbol
|
symbol
|
||||||
name
|
name
|
||||||
|
decimals
|
||||||
}
|
}
|
||||||
oracleSpecForSettlementPrice {
|
oracleSpecForSettlementPrice {
|
||||||
id
|
id
|
@ -1,31 +1,23 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import type { ReactNode } from 'react';
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import {
|
import { formatNumber, t } from '@vegaprotocol/react-helpers';
|
||||||
addDecimalsFormatNumber,
|
import { AsyncRenderer, Splash, Accordion } from '@vegaprotocol/ui-toolkit';
|
||||||
formatLabel,
|
|
||||||
formatNumber,
|
|
||||||
formatNumberPercentage,
|
|
||||||
t,
|
|
||||||
} from '@vegaprotocol/react-helpers';
|
|
||||||
import {
|
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
AsyncRenderer,
|
|
||||||
Splash,
|
|
||||||
Accordion,
|
|
||||||
Tooltip,
|
|
||||||
Link,
|
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
|
||||||
import startCase from 'lodash/startCase';
|
|
||||||
import pick from 'lodash/pick';
|
import pick from 'lodash/pick';
|
||||||
import omit from 'lodash/omit';
|
|
||||||
import type { MarketInfoQuery, MarketInfoQuery_market } from './';
|
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { totalFees } from '@vegaprotocol/market-list';
|
import { totalFees } from '@vegaprotocol/market-list';
|
||||||
import { AccountType, Interval } from '@vegaprotocol/types';
|
import {
|
||||||
|
AccountType,
|
||||||
|
Interval,
|
||||||
|
MarketStateMapping,
|
||||||
|
MarketTradingModeMapping,
|
||||||
|
} from '@vegaprotocol/types';
|
||||||
import { MARKET_INFO_QUERY } from './info-market-query';
|
import { MARKET_INFO_QUERY } from './info-market-query';
|
||||||
|
import type {
|
||||||
|
MarketInfoQuery,
|
||||||
|
MarketInfoQuery_market,
|
||||||
|
MarketInfoQuery_market_candles,
|
||||||
|
} from './__generated__/MarketInfoQuery';
|
||||||
|
import { MarketInfoTable } from './info-key-value-table';
|
||||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
import { generatePath } from 'react-router-dom';
|
import { generatePath } from 'react-router-dom';
|
||||||
@ -42,11 +34,11 @@ export interface InfoProps {
|
|||||||
export const calcCandleVolume = (
|
export const calcCandleVolume = (
|
||||||
m: MarketInfoQuery_market
|
m: MarketInfoQuery_market
|
||||||
): string | undefined => {
|
): string | undefined => {
|
||||||
return m?.candles
|
return m.candles
|
||||||
?.reduce((acc, c) => {
|
?.reduce((acc: BigNumber, c: MarketInfoQuery_market_candles | null) => {
|
||||||
return acc.plus(new BigNumber(c?.volume ?? 0));
|
return acc.plus(new BigNumber(c?.volume ?? 0));
|
||||||
}, new BigNumber(0))
|
}, new BigNumber(m.candles?.[0]?.volume ?? 0))
|
||||||
.toString();
|
?.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface MarketInfoContainerProps {
|
export interface MarketInfoContainerProps {
|
||||||
@ -57,10 +49,16 @@ export const MarketInfoContainer = ({ marketId }: MarketInfoContainerProps) => {
|
|||||||
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
||||||
return new Date(yesterday * 1000).toISOString();
|
return new Date(yesterday * 1000).toISOString();
|
||||||
}, []);
|
}, []);
|
||||||
|
const variables = useMemo(
|
||||||
const { data, loading, error } = useQuery(MARKET_INFO_QUERY, {
|
() => ({ marketId, since: yTimestamp, interval: Interval.INTERVAL_I1H }),
|
||||||
variables: { marketId, interval: Interval.INTERVAL_I1H, since: yTimestamp },
|
[marketId, yTimestamp]
|
||||||
});
|
);
|
||||||
|
const { data, loading, error } = useQuery<MarketInfoQuery>(
|
||||||
|
MARKET_INFO_QUERY,
|
||||||
|
{
|
||||||
|
variables,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AsyncRenderer<MarketInfoQuery> data={data} loading={loading} error={error}>
|
<AsyncRenderer<MarketInfoQuery> data={data} loading={loading} error={error}>
|
||||||
@ -79,6 +77,8 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
const { VEGA_TOKEN_URL } = useEnvironment();
|
const { VEGA_TOKEN_URL } = useEnvironment();
|
||||||
const headerClassName = 'uppercase text-lg';
|
const headerClassName = 'uppercase text-lg';
|
||||||
const dayVolume = calcCandleVolume(market);
|
const dayVolume = calcCandleVolume(market);
|
||||||
|
const assetSymbol =
|
||||||
|
market.tradableInstrument.instrument.product?.settlementAsset.symbol;
|
||||||
const marketDataPanels = [
|
const marketDataPanels = [
|
||||||
{
|
{
|
||||||
title: t('Current fees'),
|
title: t('Current fees'),
|
||||||
@ -137,28 +137,33 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
},
|
},
|
||||||
...(market.accounts || [])
|
...(market.accounts || [])
|
||||||
.filter((a) => a.type === AccountType.ACCOUNT_TYPE_INSURANCE)
|
.filter((a) => a.type === AccountType.ACCOUNT_TYPE_INSURANCE)
|
||||||
.map((a, i) => ({
|
.map((a) => ({
|
||||||
title: t(`Insurance pool`),
|
title: t(`Insurance pool`),
|
||||||
content: (
|
content: (
|
||||||
<MarketInfoTable
|
<MarketInfoTable
|
||||||
data={{
|
data={{
|
||||||
balance: `${a.balance}
|
balance: a.balance,
|
||||||
${market.tradableInstrument.instrument.product?.settlementAsset.symbol}`,
|
|
||||||
}}
|
}}
|
||||||
|
assetSymbol={assetSymbol}
|
||||||
|
decimalPlaces={
|
||||||
|
market.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
.decimals
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
})),
|
})),
|
||||||
];
|
];
|
||||||
|
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||||
const keyDetails = pick(
|
const keyDetails = {
|
||||||
market,
|
...pick(
|
||||||
'name',
|
market,
|
||||||
'decimalPlaces',
|
'name',
|
||||||
'positionDecimalPlaces',
|
'decimalPlaces',
|
||||||
'tradingMode',
|
'positionDecimalPlaces',
|
||||||
'state',
|
'tradingMode'
|
||||||
'id' as 'marketId'
|
),
|
||||||
);
|
state: MarketStateMapping[market.state],
|
||||||
|
};
|
||||||
const marketSpecPanels = [
|
const marketSpecPanels = [
|
||||||
{
|
{
|
||||||
title: t('Key details'),
|
title: t('Key details'),
|
||||||
@ -166,10 +171,10 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
<MarketInfoTable
|
<MarketInfoTable
|
||||||
data={{
|
data={{
|
||||||
...keyDetails,
|
...keyDetails,
|
||||||
marketID: keyDetails.id,
|
marketID: market.id,
|
||||||
id: undefined,
|
|
||||||
tradingMode:
|
tradingMode:
|
||||||
keyDetails.tradingMode && formatLabel(keyDetails.tradingMode),
|
keyDetails.tradingMode &&
|
||||||
|
MarketTradingModeMapping[keyDetails.tradingMode],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@ -251,6 +256,12 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
<MarketInfoTable data={trigger} decimalPlaces={market.decimalPlaces} />
|
<MarketInfoTable data={trigger} decimalPlaces={market.decimalPlaces} />
|
||||||
),
|
),
|
||||||
})),
|
})),
|
||||||
|
...(market.data?.priceMonitoringBounds || []).map((trigger, i) => ({
|
||||||
|
title: t(`Price monitoring bound ${i + 1}`),
|
||||||
|
content: (
|
||||||
|
<MarketInfoTable data={trigger} decimalPlaces={market.decimalPlaces} />
|
||||||
|
),
|
||||||
|
})),
|
||||||
{
|
{
|
||||||
title: t('Liquidity monitoring parameters'),
|
title: t('Liquidity monitoring parameters'),
|
||||||
content: (
|
content: (
|
||||||
@ -263,6 +274,28 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t('Liquidity'),
|
||||||
|
content: (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
targetStake: market.data && market.data.targetStake,
|
||||||
|
suppliedStake: market.data && market.data?.suppliedStake,
|
||||||
|
marketValueProxy: market.data && market.data.marketValueProxy,
|
||||||
|
}}
|
||||||
|
decimalPlaces={
|
||||||
|
market.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
.decimals
|
||||||
|
}
|
||||||
|
assetSymbol={assetSymbol}
|
||||||
|
link={
|
||||||
|
<ExternalLink href={`/liquidity/${market.id}`}>
|
||||||
|
{t('View liquidity provision table')}
|
||||||
|
</ExternalLink>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t('Oracle'),
|
title: t('Oracle'),
|
||||||
content: (
|
content: (
|
||||||
@ -276,6 +309,13 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
market.tradableInstrument.instrument.product
|
market.tradableInstrument.instrument.product
|
||||||
.oracleSpecForTradingTermination.id,
|
.oracleSpecForTradingTermination.id,
|
||||||
}}
|
}}
|
||||||
|
link={
|
||||||
|
<ExternalLink
|
||||||
|
href={`${VEGA_EXPLORER_URL}/oracles#${market.tradableInstrument.instrument.product.oracleSpecForTradingTermination.id}`}
|
||||||
|
>
|
||||||
|
{t('View full oracle details')}
|
||||||
|
</ExternalLink>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -323,172 +363,3 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const tooltipMapping: Record<string, ReactNode> = {
|
|
||||||
makerFee: t(
|
|
||||||
'Maker portion of the fee is transferred to the non-aggressive, or passive party in the trade (the maker, as opposed to the taker).'
|
|
||||||
),
|
|
||||||
liquidityFee: t(
|
|
||||||
'Liquidity portion of the fee is paid to market makers for providing liquidity, and is transferred to the market-maker fee pool for the market.'
|
|
||||||
),
|
|
||||||
infrastructureFee: t(
|
|
||||||
'Fees paid to validators as a reward for running the infrastructure of the network.'
|
|
||||||
),
|
|
||||||
|
|
||||||
markPrice: t(
|
|
||||||
'A concept derived from traditional markets. It is a calculated value for the ‘current market price’ on a market.'
|
|
||||||
),
|
|
||||||
openInterest: t(
|
|
||||||
'The volume of all open positions in a given market (the sum of the size of all positions greater than 0).'
|
|
||||||
),
|
|
||||||
indicativeVolume: t(
|
|
||||||
'The volume at which all trades would occur if the auction was uncrossed now (when in auction mode).'
|
|
||||||
),
|
|
||||||
bestBidVolume: t(
|
|
||||||
'The aggregated volume being bid at the best bid price on the market.'
|
|
||||||
),
|
|
||||||
bestOfferVolume: t(
|
|
||||||
'The aggregated volume being offered at the best offer price on the market.'
|
|
||||||
),
|
|
||||||
bestStaticBidVolume: t(
|
|
||||||
'The aggregated volume being bid at the best static bid price on the market.'
|
|
||||||
),
|
|
||||||
bestStaticOfferVolume: t(
|
|
||||||
'The aggregated volume being offered at the best static offer price on the market.'
|
|
||||||
),
|
|
||||||
|
|
||||||
decimalPlaces: t('The smallest price increment on the book.'),
|
|
||||||
positionDecimalPlaces: t(
|
|
||||||
'How big the smallest order / position on the market can be.'
|
|
||||||
),
|
|
||||||
tradingMode: t('The trading mode the market is currently running.'),
|
|
||||||
state: t('The current state of the market'),
|
|
||||||
|
|
||||||
base: t(
|
|
||||||
'The first currency in a pair for a currency-based derivatives market.'
|
|
||||||
),
|
|
||||||
quote: t(
|
|
||||||
'The second currency in a pair for a currency-based derivatives market.'
|
|
||||||
),
|
|
||||||
class: t(
|
|
||||||
'The classification of the product. Examples: shares, commodities, crypto, FX.'
|
|
||||||
),
|
|
||||||
sector: t(
|
|
||||||
'Data about the sector. Example: "automotive" for a market based on value of Tesla shares.'
|
|
||||||
),
|
|
||||||
|
|
||||||
short: t(
|
|
||||||
'A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.'
|
|
||||||
),
|
|
||||||
long: t(
|
|
||||||
'A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.'
|
|
||||||
),
|
|
||||||
|
|
||||||
tau: (
|
|
||||||
<span>
|
|
||||||
{t('Projection horizon measured as a year fraction used in ')}
|
|
||||||
<Link
|
|
||||||
href="https://vega.xyz/papers/margins-and-credit-risk.pdf#page=7"
|
|
||||||
target="__blank"
|
|
||||||
>
|
|
||||||
{t('Expected Shortfall')}
|
|
||||||
</Link>
|
|
||||||
{t(' calculation when obtaining Risk Factor Long and Risk Factor Short')}
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
riskAversionParameter: (
|
|
||||||
<span>
|
|
||||||
{t('Probability level used in ')}
|
|
||||||
<Link
|
|
||||||
href="https://vega.xyz/papers/margins-and-credit-risk.pdf#page=7"
|
|
||||||
target="__blank"
|
|
||||||
>
|
|
||||||
{t('Expected Shortfall')}
|
|
||||||
</Link>
|
|
||||||
{t(' calculation when obtaining Risk Factor Long and Risk Factor Short')}
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
|
|
||||||
horizonSecs: t('Time horizon of the price projection in seconds.'),
|
|
||||||
probability: t(
|
|
||||||
'Probability level for price projection, e.g. value of 0.95 will result in a price range such that over the specified projection horizon, the prices observed in the market should be in that range 95% of the time.'
|
|
||||||
),
|
|
||||||
auctionExtensionSecs: t(
|
|
||||||
'Auction extension duration in seconds, should the price breach its theoretical level over the specified horizon at the specified probability level.'
|
|
||||||
),
|
|
||||||
|
|
||||||
triggeringRatio: t('The triggering ratio for entering liquidity auction.'),
|
|
||||||
timeWindow: t('The length of time over which open interest is measured.'),
|
|
||||||
scalingFactor: t(
|
|
||||||
'The scaling between the liquidity demand estimate, based on open interest and target stake.'
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
interface RowProps {
|
|
||||||
field: string;
|
|
||||||
value: any;
|
|
||||||
decimalPlaces?: number;
|
|
||||||
asPercentage?: boolean;
|
|
||||||
unformatted?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Row = ({
|
|
||||||
field,
|
|
||||||
value,
|
|
||||||
decimalPlaces,
|
|
||||||
asPercentage,
|
|
||||||
unformatted,
|
|
||||||
}: RowProps) => {
|
|
||||||
const isNumber = typeof value === 'number' || !isNaN(Number(value));
|
|
||||||
const isPrimitive = typeof value === 'string' || isNumber;
|
|
||||||
if (isPrimitive) {
|
|
||||||
return (
|
|
||||||
<KeyValueTableRow key={field} inline={isPrimitive} noBorder={true}>
|
|
||||||
<Tooltip description={tooltipMapping[field]} align="start">
|
|
||||||
<div tabIndex={-1}>{startCase(t(field))}</div>
|
|
||||||
</Tooltip>
|
|
||||||
<span style={{ wordBreak: 'break-word' }}>
|
|
||||||
{isNumber && !unformatted
|
|
||||||
? decimalPlaces
|
|
||||||
? addDecimalsFormatNumber(value, decimalPlaces)
|
|
||||||
: asPercentage
|
|
||||||
? formatNumberPercentage(new BigNumber(value * 100))
|
|
||||||
: formatNumber(Number(value))
|
|
||||||
: value}
|
|
||||||
</span>
|
|
||||||
</KeyValueTableRow>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface MarketInfoTableProps {
|
|
||||||
data: any;
|
|
||||||
decimalPlaces?: number;
|
|
||||||
asPercentage?: boolean;
|
|
||||||
unformatted?: boolean;
|
|
||||||
omits?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MarketInfoTable = ({
|
|
||||||
data,
|
|
||||||
decimalPlaces,
|
|
||||||
asPercentage,
|
|
||||||
unformatted,
|
|
||||||
omits = ['__typename'],
|
|
||||||
}: MarketInfoTableProps) => {
|
|
||||||
return (
|
|
||||||
<KeyValueTable>
|
|
||||||
{Object.entries(omit(data, ...omits) || []).map(([key, value]) => (
|
|
||||||
<Row
|
|
||||||
key={key}
|
|
||||||
field={key}
|
|
||||||
value={value}
|
|
||||||
decimalPlaces={decimalPlaces}
|
|
||||||
asPercentage={asPercentage}
|
|
||||||
unformatted={unformatted || key.toLowerCase().includes('volume')}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</KeyValueTable>
|
|
||||||
);
|
|
||||||
};
|
|
103
libs/deal-ticket/src/components/market-info/tooltip-mapping.tsx
Normal file
103
libs/deal-ticket/src/components/market-info/tooltip-mapping.tsx
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
|
|
||||||
|
export const tooltipMapping: Record<string, ReactNode> = {
|
||||||
|
makerFee: t(
|
||||||
|
'Maker portion of the fee is transferred to the non-aggressive, or passive party in the trade (the maker, as opposed to the taker).'
|
||||||
|
),
|
||||||
|
liquidityFee: t(
|
||||||
|
'Liquidity portion of the fee is paid to market makers for providing liquidity, and is transferred to the liquidity fee pool for the market.'
|
||||||
|
),
|
||||||
|
infrastructureFee: t(
|
||||||
|
'Fees paid to validators as a reward for running the infrastructure of the network.'
|
||||||
|
),
|
||||||
|
|
||||||
|
markPrice: t(
|
||||||
|
'A concept derived from traditional markets. It is a calculated value for the ‘current market price’ on a market.'
|
||||||
|
),
|
||||||
|
openInterest: t(
|
||||||
|
'The volume of all open positions in a given market (the sum of the size of all positions greater than 0).'
|
||||||
|
),
|
||||||
|
indicativeVolume: t(
|
||||||
|
'The volume at which all trades would occur if the auction was uncrossed now (when in auction mode).'
|
||||||
|
),
|
||||||
|
bestBidVolume: t(
|
||||||
|
'The aggregated volume being bid at the best bid price on the market.'
|
||||||
|
),
|
||||||
|
bestOfferVolume: t(
|
||||||
|
'The aggregated volume being offered at the best offer price on the market.'
|
||||||
|
),
|
||||||
|
bestStaticBidVolume: t(
|
||||||
|
'The aggregated volume being bid at the best static bid price on the market.'
|
||||||
|
),
|
||||||
|
bestStaticOfferVolume: t(
|
||||||
|
'The aggregated volume being offered at the best static offer price on the market.'
|
||||||
|
),
|
||||||
|
|
||||||
|
decimalPlaces: t('The smallest price increment on the book.'),
|
||||||
|
positionDecimalPlaces: t(
|
||||||
|
'How big the smallest order / position on the market can be.'
|
||||||
|
),
|
||||||
|
tradingMode: t('The trading mode the market is currently running.'),
|
||||||
|
state: t('The current state of the market'),
|
||||||
|
|
||||||
|
base: t(
|
||||||
|
'The first currency in a pair for a currency-based derivatives market.'
|
||||||
|
),
|
||||||
|
quote: t(
|
||||||
|
'The second currency in a pair for a currency-based derivatives market.'
|
||||||
|
),
|
||||||
|
class: t(
|
||||||
|
'The classification of the product. Examples: shares, commodities, crypto, FX.'
|
||||||
|
),
|
||||||
|
sector: t(
|
||||||
|
'Data about the sector. Example: "automotive" for a market based on value of Tesla shares.'
|
||||||
|
),
|
||||||
|
|
||||||
|
short: t(
|
||||||
|
'A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.'
|
||||||
|
),
|
||||||
|
long: t(
|
||||||
|
'A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.'
|
||||||
|
),
|
||||||
|
|
||||||
|
tau: (
|
||||||
|
<span>
|
||||||
|
{t('Projection horizon measured as a year fraction used in ')}
|
||||||
|
<Link
|
||||||
|
href="https://vega.xyz/papers/margins-and-credit-risk.pdf#page=7"
|
||||||
|
target="__blank"
|
||||||
|
>
|
||||||
|
{t('Expected Shortfall')}
|
||||||
|
</Link>
|
||||||
|
{t(' calculation when obtaining Risk Factor Long and Risk Factor Short')}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
riskAversionParameter: (
|
||||||
|
<span>
|
||||||
|
{t('Probability level used in ')}
|
||||||
|
<Link
|
||||||
|
href="https://vega.xyz/papers/margins-and-credit-risk.pdf#page=7"
|
||||||
|
target="__blank"
|
||||||
|
>
|
||||||
|
{t('Expected Shortfall')}
|
||||||
|
</Link>
|
||||||
|
{t(' calculation when obtaining Risk Factor Long and Risk Factor Short')}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
|
||||||
|
horizonSecs: t('Time horizon of the price projection in seconds.'),
|
||||||
|
probability: t(
|
||||||
|
'Probability level for price projection, e.g. value of 0.95 will result in a price range such that over the specified projection horizon, the prices observed in the market should be in that range 95% of the time.'
|
||||||
|
),
|
||||||
|
auctionExtensionSecs: t(
|
||||||
|
'Auction extension duration in seconds, should the price breach its theoretical level over the specified horizon at the specified probability level.'
|
||||||
|
),
|
||||||
|
|
||||||
|
triggeringRatio: t('The triggering ratio for entering liquidity auction.'),
|
||||||
|
timeWindow: t('The length of time over which open interest is measured.'),
|
||||||
|
scalingFactor: t(
|
||||||
|
'The scaling between the liquidity demand estimate, based on open interest and target stake.'
|
||||||
|
),
|
||||||
|
};
|
4
libs/liquidity/.babelrc
Normal file
4
libs/liquidity/.babelrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"presets": ["@nrwl/next/babel"],
|
||||||
|
"plugins": []
|
||||||
|
}
|
18
libs/liquidity/.eslintrc.json
Normal file
18
libs/liquidity/.eslintrc.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
|
||||||
|
"ignorePatterns": ["!**/*", "__generated__"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
7
libs/liquidity/README.md
Normal file
7
libs/liquidity/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Liquidity
|
||||||
|
|
||||||
|
This library contains liquidity provision data providers and view containers.
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
Run `nx test liquidity` to execute the unit tests via [Jest](https://jestjs.io).
|
15
libs/liquidity/jest.config.js
Normal file
15
libs/liquidity/jest.config.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module.exports = {
|
||||||
|
displayName: 'positions',
|
||||||
|
preset: '../../jest.preset.js',
|
||||||
|
globals: {
|
||||||
|
'ts-jest': {
|
||||||
|
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]sx?$': 'ts-jest',
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||||
|
coverageDirectory: '../../coverage/libs/positions',
|
||||||
|
setupFilesAfterEnv: ['./src/setup-tests.ts'],
|
||||||
|
};
|
4
libs/liquidity/package.json
Normal file
4
libs/liquidity/package.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"name": "@vegaprotocol/liquidity",
|
||||||
|
"version": "0.0.1"
|
||||||
|
}
|
43
libs/liquidity/project.json
Normal file
43
libs/liquidity/project.json
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"root": "libs/liquidity",
|
||||||
|
"sourceRoot": "libs/liquidity/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"executor": "@nrwl/web:rollup",
|
||||||
|
"outputs": ["{options.outputPath}"],
|
||||||
|
"options": {
|
||||||
|
"outputPath": "dist/libs/liquidity",
|
||||||
|
"tsConfig": "libs/liquidity/tsconfig.lib.json",
|
||||||
|
"project": "libs/liquidity/package.json",
|
||||||
|
"entryFile": "libs/liquidity/src/index.ts",
|
||||||
|
"external": ["react/jsx-runtime"],
|
||||||
|
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
|
||||||
|
"compiler": "babel",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "libs/liquidity/README.md",
|
||||||
|
"input": ".",
|
||||||
|
"output": "."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nrwl/linter:eslint",
|
||||||
|
"outputs": ["{options.outputFile}"],
|
||||||
|
"options": {
|
||||||
|
"lintFilePatterns": ["libs/liquidity/**/*.{ts,tsx,js,jsx}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"executor": "@nrwl/jest:jest",
|
||||||
|
"outputs": ["coverage/libs/liquidity"],
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "libs/liquidity/jest.config.js",
|
||||||
|
"passWithNoTests": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
libs/liquidity/src/index.ts
Normal file
1
libs/liquidity/src/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './lib';
|
252
libs/liquidity/src/lib/__generated__/MarketLiquidity.ts
generated
Normal file
252
libs/liquidity/src/lib/__generated__/MarketLiquidity.ts
generated
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { AccountType, LiquidityProvisionStatus } from "@vegaprotocol/types";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL query operation: MarketLiquidity
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_liquidityProvisionsConnection_edges_node_party_accountsConnection_edges_node {
|
||||||
|
__typename: "Account";
|
||||||
|
/**
|
||||||
|
* Account type (General, Margin, etc)
|
||||||
|
*/
|
||||||
|
type: AccountType;
|
||||||
|
/**
|
||||||
|
* Balance as string - current account balance (approx. as balances can be updated several times per second)
|
||||||
|
*/
|
||||||
|
balance: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_liquidityProvisionsConnection_edges_node_party_accountsConnection_edges {
|
||||||
|
__typename: "AccountEdge";
|
||||||
|
/**
|
||||||
|
* The account
|
||||||
|
*/
|
||||||
|
node: MarketLiquidity_market_liquidityProvisionsConnection_edges_node_party_accountsConnection_edges_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_liquidityProvisionsConnection_edges_node_party_accountsConnection {
|
||||||
|
__typename: "AccountsConnection";
|
||||||
|
/**
|
||||||
|
* List of accounts available for the connection
|
||||||
|
*/
|
||||||
|
edges: (MarketLiquidity_market_liquidityProvisionsConnection_edges_node_party_accountsConnection_edges | null)[] | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_liquidityProvisionsConnection_edges_node_party {
|
||||||
|
__typename: "Party";
|
||||||
|
/**
|
||||||
|
* Party identifier
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
/**
|
||||||
|
* Collateral accounts relating to a party
|
||||||
|
*/
|
||||||
|
accountsConnection: MarketLiquidity_market_liquidityProvisionsConnection_edges_node_party_accountsConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_liquidityProvisionsConnection_edges_node {
|
||||||
|
__typename: "LiquidityProvision";
|
||||||
|
/**
|
||||||
|
* Unique identifier for the order (set by the system after consensus)
|
||||||
|
*/
|
||||||
|
id: string | null;
|
||||||
|
/**
|
||||||
|
* The Id of the party making this commitment
|
||||||
|
*/
|
||||||
|
party: MarketLiquidity_market_liquidityProvisionsConnection_edges_node_party;
|
||||||
|
/**
|
||||||
|
* When the liquidity provision was initially created (formatted RFC3339)
|
||||||
|
*/
|
||||||
|
createdAt: string;
|
||||||
|
/**
|
||||||
|
* RFC3339Nano time of when the liquidity provision was updated
|
||||||
|
*/
|
||||||
|
updatedAt: string | null;
|
||||||
|
/**
|
||||||
|
* Specified as a unit-less number that represents the amount of settlement asset of the market.
|
||||||
|
*/
|
||||||
|
commitmentAmount: string;
|
||||||
|
/**
|
||||||
|
* Nominated liquidity fee factor, which is an input to the calculation of maker fees on the market, as per setting fees and rewarding liquidity providers.
|
||||||
|
*/
|
||||||
|
fee: string;
|
||||||
|
/**
|
||||||
|
* The current status of this liquidity provision
|
||||||
|
*/
|
||||||
|
status: LiquidityProvisionStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_liquidityProvisionsConnection_edges {
|
||||||
|
__typename: "LiquidityProvisionsEdge";
|
||||||
|
node: MarketLiquidity_market_liquidityProvisionsConnection_edges_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_liquidityProvisionsConnection {
|
||||||
|
__typename: "LiquidityProvisionsConnection";
|
||||||
|
edges: (MarketLiquidity_market_liquidityProvisionsConnection_edges | null)[] | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_tradableInstrument_instrument_product_settlementAsset {
|
||||||
|
__typename: "Asset";
|
||||||
|
/**
|
||||||
|
* The ID of the asset
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
/**
|
||||||
|
* The symbol of the asset (e.g: GBP)
|
||||||
|
*/
|
||||||
|
symbol: string;
|
||||||
|
/**
|
||||||
|
* The precision of the asset. Should match the decimal precision of the asset on its native chain, e.g: for ERC20 assets, it is often 18
|
||||||
|
*/
|
||||||
|
decimals: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_tradableInstrument_instrument_product {
|
||||||
|
__typename: "Future";
|
||||||
|
/**
|
||||||
|
* The name of the asset (string)
|
||||||
|
*/
|
||||||
|
settlementAsset: MarketLiquidity_market_tradableInstrument_instrument_product_settlementAsset;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_tradableInstrument_instrument {
|
||||||
|
__typename: "Instrument";
|
||||||
|
/**
|
||||||
|
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
|
||||||
|
*/
|
||||||
|
code: string;
|
||||||
|
/**
|
||||||
|
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
|
||||||
|
*/
|
||||||
|
product: MarketLiquidity_market_tradableInstrument_instrument_product;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_tradableInstrument {
|
||||||
|
__typename: "TradableInstrument";
|
||||||
|
/**
|
||||||
|
* An instance of, or reference to, a fully specified instrument.
|
||||||
|
*/
|
||||||
|
instrument: MarketLiquidity_market_tradableInstrument_instrument;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_data_market {
|
||||||
|
__typename: "Market";
|
||||||
|
/**
|
||||||
|
* Market ID
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_data_liquidityProviderFeeShare_party {
|
||||||
|
__typename: "Party";
|
||||||
|
/**
|
||||||
|
* Party identifier
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_data_liquidityProviderFeeShare {
|
||||||
|
__typename: "LiquidityProviderFeeShare";
|
||||||
|
/**
|
||||||
|
* The liquidity provider party ID
|
||||||
|
*/
|
||||||
|
party: MarketLiquidity_market_data_liquidityProviderFeeShare_party;
|
||||||
|
/**
|
||||||
|
* The share owned by this liquidity provider (float)
|
||||||
|
*/
|
||||||
|
equityLikeShare: string;
|
||||||
|
/**
|
||||||
|
* The average entry valuation of the liquidity provider for the market
|
||||||
|
*/
|
||||||
|
averageEntryValuation: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market_data {
|
||||||
|
__typename: "MarketData";
|
||||||
|
/**
|
||||||
|
* market ID of the associated mark price
|
||||||
|
*/
|
||||||
|
market: MarketLiquidity_market_data_market;
|
||||||
|
/**
|
||||||
|
* the supplied stake for the market
|
||||||
|
*/
|
||||||
|
suppliedStake: string | null;
|
||||||
|
/**
|
||||||
|
* the sum of the size of all positions greater than 0.
|
||||||
|
*/
|
||||||
|
openInterest: string;
|
||||||
|
/**
|
||||||
|
* the amount of stake targeted for this market
|
||||||
|
*/
|
||||||
|
targetStake: string | null;
|
||||||
|
/**
|
||||||
|
* the market value proxy
|
||||||
|
*/
|
||||||
|
marketValueProxy: string;
|
||||||
|
/**
|
||||||
|
* the equity like share of liquidity fee for each liquidity provider
|
||||||
|
*/
|
||||||
|
liquidityProviderFeeShare: MarketLiquidity_market_data_liquidityProviderFeeShare[] | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity_market {
|
||||||
|
__typename: "Market";
|
||||||
|
/**
|
||||||
|
* Market ID
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
/**
|
||||||
|
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
|
||||||
|
* number denominated in the currency of the market. (uint64)
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* Currency Balance decimalPlaces Real Balance
|
||||||
|
* GBP 100 0 GBP 100
|
||||||
|
* GBP 100 2 GBP 1.00
|
||||||
|
* GBP 100 4 GBP 0.01
|
||||||
|
* GBP 1 4 GBP 0.0001 ( 0.01p )
|
||||||
|
*
|
||||||
|
* GBX (pence) 100 0 GBP 1.00 (100p )
|
||||||
|
* GBX (pence) 100 2 GBP 0.01 ( 1p )
|
||||||
|
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )
|
||||||
|
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||||
|
*/
|
||||||
|
decimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* positionDecimalPlaces indicates the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||||
|
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||||
|
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||||
|
* This sets how big the smallest order / position on the market can be.
|
||||||
|
*/
|
||||||
|
positionDecimalPlaces: number;
|
||||||
|
/**
|
||||||
|
* The list of the liquidity provision commitments for this market
|
||||||
|
*/
|
||||||
|
liquidityProvisionsConnection: MarketLiquidity_market_liquidityProvisionsConnection;
|
||||||
|
/**
|
||||||
|
* An instance of, or reference to, a tradable instrument.
|
||||||
|
*/
|
||||||
|
tradableInstrument: MarketLiquidity_market_tradableInstrument;
|
||||||
|
/**
|
||||||
|
* marketData for the given market
|
||||||
|
*/
|
||||||
|
data: MarketLiquidity_market_data | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidity {
|
||||||
|
/**
|
||||||
|
* An instrument that is trading on the Vega network
|
||||||
|
*/
|
||||||
|
market: MarketLiquidity_market | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarketLiquidityVariables {
|
||||||
|
marketId: string;
|
||||||
|
partyId?: string | null;
|
||||||
|
}
|
1
libs/liquidity/src/lib/__generated__/index.ts
generated
Normal file
1
libs/liquidity/src/lib/__generated__/index.ts
generated
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './MarketLiquidity';
|
3
libs/liquidity/src/lib/index.ts
Normal file
3
libs/liquidity/src/lib/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './__generated__';
|
||||||
|
export * from './liquidity-data-provider';
|
||||||
|
export * from './liquidity-table';
|
172
libs/liquidity/src/lib/liquidity-data-provider.ts
Normal file
172
libs/liquidity/src/lib/liquidity-data-provider.ts
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
import { gql, useQuery } from '@apollo/client';
|
||||||
|
import type { LiquidityProvisionStatus } from '@vegaprotocol/types';
|
||||||
|
import { AccountType } from '@vegaprotocol/types';
|
||||||
|
import { useNetworkParam } from '@vegaprotocol/react-helpers';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import type {
|
||||||
|
MarketLiquidity,
|
||||||
|
MarketLiquidity_market_data_liquidityProviderFeeShare,
|
||||||
|
} from './__generated__';
|
||||||
|
|
||||||
|
const SISKA_NETWORK_PARAMETER = 'market.liquidity.stakeToCcySiskas';
|
||||||
|
|
||||||
|
const MARKET_LIQUIDITY_QUERY = gql`
|
||||||
|
query MarketLiquidity($marketId: ID!, $partyId: String) {
|
||||||
|
market(id: $marketId) {
|
||||||
|
id
|
||||||
|
decimalPlaces
|
||||||
|
positionDecimalPlaces
|
||||||
|
liquidityProvisionsConnection(party: $partyId) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
party {
|
||||||
|
id
|
||||||
|
accountsConnection(marketId: $marketId, type: ACCOUNT_TYPE_BOND) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
type
|
||||||
|
balance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
commitmentAmount
|
||||||
|
fee
|
||||||
|
status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tradableInstrument {
|
||||||
|
instrument {
|
||||||
|
code
|
||||||
|
product {
|
||||||
|
... on Future {
|
||||||
|
settlementAsset {
|
||||||
|
id
|
||||||
|
symbol
|
||||||
|
decimals
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data {
|
||||||
|
market {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
suppliedStake
|
||||||
|
openInterest
|
||||||
|
targetStake
|
||||||
|
marketValueProxy
|
||||||
|
liquidityProviderFeeShare {
|
||||||
|
party {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
equityLikeShare
|
||||||
|
averageEntryValuation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export interface LiquidityProvision {
|
||||||
|
party: string;
|
||||||
|
commitmentAmount: string | undefined;
|
||||||
|
fee: string | undefined;
|
||||||
|
equityLikeShare: string;
|
||||||
|
averageEntryValuation: string;
|
||||||
|
obligation: string | null;
|
||||||
|
supplied: string | null;
|
||||||
|
status?: LiquidityProvisionStatus;
|
||||||
|
createdAt: string | undefined;
|
||||||
|
updatedAt: string | null | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LiquidityData {
|
||||||
|
liquidityProviders: LiquidityProvision[];
|
||||||
|
suppliedStake?: string | null;
|
||||||
|
targetStake?: string | null;
|
||||||
|
code?: string;
|
||||||
|
symbol?: string;
|
||||||
|
decimalPlaces?: number;
|
||||||
|
positionDecimalPlaces?: number;
|
||||||
|
assetDecimalPlaces?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useLiquidityProvision = ({
|
||||||
|
marketId,
|
||||||
|
partyId,
|
||||||
|
}: {
|
||||||
|
partyId?: string;
|
||||||
|
marketId?: string;
|
||||||
|
}) => {
|
||||||
|
const { data: stakeToCcySiskas } = useNetworkParam(SISKA_NETWORK_PARAMETER);
|
||||||
|
const stakeToCcySiska = stakeToCcySiskas && stakeToCcySiskas[0];
|
||||||
|
const { data, loading, error } = useQuery<MarketLiquidity>(
|
||||||
|
MARKET_LIQUIDITY_QUERY,
|
||||||
|
{
|
||||||
|
variables: { marketId },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const liquidityProviders = (
|
||||||
|
data?.market?.data?.liquidityProviderFeeShare || []
|
||||||
|
)
|
||||||
|
?.filter(
|
||||||
|
(p: MarketLiquidity_market_data_liquidityProviderFeeShare) =>
|
||||||
|
!partyId || p.party.id === partyId
|
||||||
|
) // if partyId is provided, filter out other parties
|
||||||
|
.map((provider: MarketLiquidity_market_data_liquidityProviderFeeShare) => {
|
||||||
|
const liquidityProvisionConnection =
|
||||||
|
data?.market?.liquidityProvisionsConnection.edges?.find(
|
||||||
|
(e) => e?.node.party.id === provider.party.id
|
||||||
|
);
|
||||||
|
const balance =
|
||||||
|
liquidityProvisionConnection?.node?.party.accountsConnection.edges?.reduce(
|
||||||
|
(acc, e) => {
|
||||||
|
return e?.node.type === AccountType.ACCOUNT_TYPE_BOND // just an extra check to make sure we only use bond accounts
|
||||||
|
? acc.plus(new BigNumber(e?.node.balance ?? 0))
|
||||||
|
: acc;
|
||||||
|
},
|
||||||
|
new BigNumber(0)
|
||||||
|
);
|
||||||
|
const obligation =
|
||||||
|
stakeToCcySiska &&
|
||||||
|
new BigNumber(stakeToCcySiska)
|
||||||
|
.times(liquidityProvisionConnection?.node?.commitmentAmount ?? 1)
|
||||||
|
.toString();
|
||||||
|
const supplied =
|
||||||
|
stakeToCcySiska &&
|
||||||
|
new BigNumber(stakeToCcySiska).times(balance ?? 1).toString();
|
||||||
|
return {
|
||||||
|
party: provider.party.id,
|
||||||
|
createdAt: liquidityProvisionConnection?.node?.createdAt,
|
||||||
|
updatedAt: liquidityProvisionConnection?.node?.updatedAt,
|
||||||
|
commitmentAmount: liquidityProvisionConnection?.node?.commitmentAmount,
|
||||||
|
fee: liquidityProvisionConnection?.node?.fee,
|
||||||
|
status: liquidityProvisionConnection?.node?.status,
|
||||||
|
equityLikeShare: provider.equityLikeShare,
|
||||||
|
averageEntryValuation: provider.averageEntryValuation,
|
||||||
|
obligation,
|
||||||
|
supplied,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const liquidityData: LiquidityData = {
|
||||||
|
liquidityProviders,
|
||||||
|
suppliedStake: data?.market?.data?.suppliedStake,
|
||||||
|
targetStake: data?.market?.data?.targetStake,
|
||||||
|
decimalPlaces: data?.market?.decimalPlaces,
|
||||||
|
positionDecimalPlaces: data?.market?.positionDecimalPlaces,
|
||||||
|
code: data?.market?.tradableInstrument.instrument.code,
|
||||||
|
assetDecimalPlaces:
|
||||||
|
data?.market?.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
.decimals,
|
||||||
|
symbol:
|
||||||
|
data?.market?.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
.symbol,
|
||||||
|
};
|
||||||
|
return { data: liquidityData, loading, error };
|
||||||
|
};
|
53
libs/liquidity/src/lib/liquidity-table.spec.tsx
Normal file
53
libs/liquidity/src/lib/liquidity-table.spec.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import LiquidityTable from './liquidity-table';
|
||||||
|
import { act, render, screen, waitFor } from '@testing-library/react';
|
||||||
|
import { LiquidityProvisionStatus } from '@vegaprotocol/types';
|
||||||
|
import type { LiquidityProvision } from './liquidity-data-provider';
|
||||||
|
|
||||||
|
const singleRow: LiquidityProvision = {
|
||||||
|
party: 'a3f762f0a6e998e1d0c6e73017a13ec8a22386c30f7f64a1bdca47330bc592dd',
|
||||||
|
createdAt: '2022-08-19T17:18:36.257028Z',
|
||||||
|
updatedAt: '2022-08-19T17:18:36.257028Z',
|
||||||
|
commitmentAmount: '56298653179',
|
||||||
|
fee: '0.001',
|
||||||
|
status: LiquidityProvisionStatus.STATUS_ACTIVE,
|
||||||
|
equityLikeShare: '0.5',
|
||||||
|
averageEntryValuation: '0.5',
|
||||||
|
supplied: '67895',
|
||||||
|
obligation: '56785',
|
||||||
|
};
|
||||||
|
|
||||||
|
const singleRowData = [singleRow];
|
||||||
|
|
||||||
|
describe('LiquidityTable', () => {
|
||||||
|
it('should render successfully', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
const { baseElement } = render(<LiquidityTable data={[]} />);
|
||||||
|
expect(baseElement).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render correct columns', async () => {
|
||||||
|
act(async () => {
|
||||||
|
render(<LiquidityTable data={singleRowData} />);
|
||||||
|
await waitFor(async () => {
|
||||||
|
const headers = await screen.getAllByRole('columnheader');
|
||||||
|
expect(headers).toHaveLength(9);
|
||||||
|
expect(
|
||||||
|
headers.map((h) =>
|
||||||
|
h.querySelector('[ref="eText"]')?.textContent?.trim()
|
||||||
|
)
|
||||||
|
).toEqual([
|
||||||
|
'Party',
|
||||||
|
'Average entry valuation',
|
||||||
|
'Updated',
|
||||||
|
'Created',
|
||||||
|
'Supplied (siskas)',
|
||||||
|
'Obligation (siskas)',
|
||||||
|
'Share',
|
||||||
|
'Fee',
|
||||||
|
'Status',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
117
libs/liquidity/src/lib/liquidity-table.tsx
Normal file
117
libs/liquidity/src/lib/liquidity-table.tsx
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import { forwardRef } from 'react';
|
||||||
|
import {
|
||||||
|
addDecimalsFormatNumber,
|
||||||
|
formatNumberPercentage,
|
||||||
|
getDateTimeFormat,
|
||||||
|
t,
|
||||||
|
} from '@vegaprotocol/react-helpers';
|
||||||
|
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
|
import { AgGridColumn } from 'ag-grid-react';
|
||||||
|
import type { LiquidityProvision } from './liquidity-data-provider';
|
||||||
|
import type { ValueFormatterParams } from 'ag-grid-community';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import type { LiquidityProvisionStatus } from '@vegaprotocol/types';
|
||||||
|
import { LiquidityProvisionStatusMapping } from '@vegaprotocol/types';
|
||||||
|
|
||||||
|
const assetDecimalsFormatter = ({ value, data }: ValueFormatterParams) => {
|
||||||
|
if (!value) return '-';
|
||||||
|
return addDecimalsFormatNumber(value, data.assetDecimalPlaces);
|
||||||
|
};
|
||||||
|
|
||||||
|
const percentageFormatter = ({ value }: ValueFormatterParams) => {
|
||||||
|
if (!value) return '-';
|
||||||
|
return formatNumberPercentage(new BigNumber(value).times(100), 4) || '-';
|
||||||
|
};
|
||||||
|
|
||||||
|
const dateValueFormatter = ({ value }: { value?: string | null }) => {
|
||||||
|
if (!value) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return getDateTimeFormat().format(new Date(value));
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface LiquidityTableProps {
|
||||||
|
data: LiquidityProvision[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
|
||||||
|
(props, ref) => {
|
||||||
|
return (
|
||||||
|
<AgGrid
|
||||||
|
style={{ width: '100%', height: '100%' }}
|
||||||
|
overlayNoRowsTemplate="No liquidity provisions"
|
||||||
|
getRowId={({ data }) => data.party}
|
||||||
|
rowHeight={34}
|
||||||
|
ref={ref}
|
||||||
|
defaultColDef={{
|
||||||
|
flex: 1,
|
||||||
|
resizable: true,
|
||||||
|
minWidth: 100,
|
||||||
|
}}
|
||||||
|
rowData={props.data}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<AgGridColumn headerName={t('Party')} field="party" />
|
||||||
|
<AgGridColumn
|
||||||
|
headerName={t('Commitment')}
|
||||||
|
field="commitmentAmount"
|
||||||
|
type="rightAligned"
|
||||||
|
valueFormatter={assetDecimalsFormatter}
|
||||||
|
/>
|
||||||
|
<AgGridColumn
|
||||||
|
headerName={t('Share')}
|
||||||
|
field="equityLikeShare"
|
||||||
|
type="rightAligned"
|
||||||
|
valueFormatter={percentageFormatter}
|
||||||
|
/>
|
||||||
|
<AgGridColumn
|
||||||
|
headerName={t('Fee')}
|
||||||
|
field="fee"
|
||||||
|
type="rightAligned"
|
||||||
|
valueFormatter={percentageFormatter}
|
||||||
|
/>
|
||||||
|
<AgGridColumn
|
||||||
|
headerName={t('Average entry valuation')}
|
||||||
|
field="averageEntryValuation"
|
||||||
|
type="rightAligned"
|
||||||
|
valueFormatter={assetDecimalsFormatter}
|
||||||
|
/>
|
||||||
|
<AgGridColumn
|
||||||
|
headerName={t('Obligation (siskas)')}
|
||||||
|
field="obligation"
|
||||||
|
type="rightAligned"
|
||||||
|
valueFormatter={assetDecimalsFormatter}
|
||||||
|
/>
|
||||||
|
<AgGridColumn
|
||||||
|
headerName={t('Supplied (siskas)')}
|
||||||
|
field="supplied"
|
||||||
|
type="rightAligned"
|
||||||
|
valueFormatter={assetDecimalsFormatter}
|
||||||
|
/>
|
||||||
|
<AgGridColumn
|
||||||
|
headerName={t('Status')}
|
||||||
|
field="status"
|
||||||
|
valueFormatter={({ value }: { value: LiquidityProvisionStatus }) => {
|
||||||
|
if (!value) return value;
|
||||||
|
return LiquidityProvisionStatusMapping[value];
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<AgGridColumn
|
||||||
|
headerName={t('Created')}
|
||||||
|
field="createdAt"
|
||||||
|
type="rightAligned"
|
||||||
|
valueFormatter={dateValueFormatter}
|
||||||
|
/>
|
||||||
|
<AgGridColumn
|
||||||
|
headerName={t('Updated')}
|
||||||
|
field="updatedAt"
|
||||||
|
type="rightAligned"
|
||||||
|
valueFormatter={dateValueFormatter}
|
||||||
|
/>
|
||||||
|
</AgGrid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default LiquidityTable;
|
1
libs/liquidity/src/setup-tests.ts
Normal file
1
libs/liquidity/src/setup-tests.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
import '@testing-library/jest-dom';
|
25
libs/liquidity/tsconfig.json
Normal file
25
libs/liquidity/tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.lib.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
22
libs/liquidity/tsconfig.lib.json
Normal file
22
libs/liquidity/tsconfig.lib.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"types": ["node"]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
|
||||||
|
"../../node_modules/@nrwl/next/typings/image.d.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.test.ts",
|
||||||
|
"**/*.spec.tsx",
|
||||||
|
"**/*.test.tsx",
|
||||||
|
"**/*.spec.js",
|
||||||
|
"**/*.test.js",
|
||||||
|
"**/*.spec.jsx",
|
||||||
|
"**/*.test.jsx"
|
||||||
|
],
|
||||||
|
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
|
||||||
|
}
|
20
libs/liquidity/tsconfig.spec.json
Normal file
20
libs/liquidity/tsconfig.spec.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": ["jest", "node", "@testing-library/jest-dom"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.test.ts",
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.test.tsx",
|
||||||
|
"**/*.spec.tsx",
|
||||||
|
"**/*.test.js",
|
||||||
|
"**/*.spec.js",
|
||||||
|
"**/*.test.jsx",
|
||||||
|
"**/*.spec.jsx",
|
||||||
|
"**/*.d.ts",
|
||||||
|
"../react-helpers/src/lib/grid-cells/summary-row.spec.ts"
|
||||||
|
]
|
||||||
|
}
|
@ -100,8 +100,7 @@ export const SelectMarketPopover = ({
|
|||||||
marketName: string;
|
marketName: string;
|
||||||
onSelect: (id: string) => void;
|
onSelect: (id: string) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const triggerClasses =
|
const triggerClasses = 'flex items-center gap-4 whitespace-nowrap';
|
||||||
'sm:text-lg md:text-xl lg:text-2xl flex items-center gap-4 whitespace-nowrap';
|
|
||||||
const { keypair } = useVegaWallet();
|
const { keypair } = useVegaWallet();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const { data, loading: marketsLoading } = useMarketList();
|
const { data, loading: marketsLoading } = useMarketList();
|
||||||
|
@ -83,7 +83,7 @@ describe('OrderFeedback', () => {
|
|||||||
'1.00'
|
'1.00'
|
||||||
);
|
);
|
||||||
expect(screen.getByText('Size').nextElementSibling).toHaveTextContent(
|
expect(screen.getByText('Size').nextElementSibling).toHaveTextContent(
|
||||||
`+ 200`
|
`+200`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,20 +1,15 @@
|
|||||||
import { useEnvironment } from '@vegaprotocol/environment';
|
import { useEnvironment } from '@vegaprotocol/environment';
|
||||||
import type { OrderEvent_busEvents_event_Order } from '../../order-hooks/__generated__/OrderEvent';
|
import type { OrderEvent_busEvents_event_Order } from '../../order-hooks/__generated__/OrderEvent';
|
||||||
import {
|
import { addDecimalsFormatNumber, Size, t } from '@vegaprotocol/react-helpers';
|
||||||
addDecimalsFormatNumber,
|
|
||||||
t,
|
|
||||||
positiveClassNames,
|
|
||||||
negativeClassNames,
|
|
||||||
} from '@vegaprotocol/react-helpers';
|
|
||||||
import {
|
import {
|
||||||
OrderRejectionReasonMapping,
|
OrderRejectionReasonMapping,
|
||||||
OrderStatus,
|
OrderStatus,
|
||||||
OrderStatusMapping,
|
OrderStatusMapping,
|
||||||
OrderTimeInForceMapping,
|
OrderTimeInForceMapping,
|
||||||
OrderType,
|
OrderType,
|
||||||
Side,
|
|
||||||
} from '@vegaprotocol/types';
|
} from '@vegaprotocol/types';
|
||||||
import type { VegaTxState } from '@vegaprotocol/wallet';
|
import type { VegaTxState } from '@vegaprotocol/wallet';
|
||||||
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
export interface OrderFeedbackProps {
|
export interface OrderFeedbackProps {
|
||||||
transaction: VegaTxState;
|
transaction: VegaTxState;
|
||||||
@ -51,20 +46,12 @@ export const OrderFeedback = ({ transaction, order }: OrderFeedbackProps) => {
|
|||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<p className={labelClass}>{t(`Size`)}</p>
|
<p className={labelClass}>{t(`Size`)}</p>
|
||||||
<p
|
<p>
|
||||||
className={
|
<Size
|
||||||
order.side === Side.SIDE_BUY
|
value={order.size}
|
||||||
? positiveClassNames
|
side={order.side}
|
||||||
: negativeClassNames
|
positionDecimalPlaces={order.market.positionDecimalPlaces}
|
||||||
}
|
/>
|
||||||
>
|
|
||||||
{`${
|
|
||||||
order.side === Side.SIDE_BUY ? '+' : '-'
|
|
||||||
} ${addDecimalsFormatNumber(
|
|
||||||
order.size,
|
|
||||||
order.market?.positionDecimalPlaces ?? 0
|
|
||||||
)}
|
|
||||||
`}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -72,8 +59,7 @@ export const OrderFeedback = ({ transaction, order }: OrderFeedbackProps) => {
|
|||||||
{transaction.txHash && (
|
{transaction.txHash && (
|
||||||
<div>
|
<div>
|
||||||
<p className={labelClass}>{t('Transaction')}</p>
|
<p className={labelClass}>{t('Transaction')}</p>
|
||||||
<a
|
<Link
|
||||||
className="underline"
|
|
||||||
style={{ wordBreak: 'break-word' }}
|
style={{ wordBreak: 'break-word' }}
|
||||||
data-testid="tx-block-explorer"
|
data-testid="tx-block-explorer"
|
||||||
href={`${VEGA_EXPLORER_URL}/txs/0x${transaction.txHash}`}
|
href={`${VEGA_EXPLORER_URL}/txs/0x${transaction.txHash}`}
|
||||||
@ -81,7 +67,7 @@ export const OrderFeedback = ({ transaction, order }: OrderFeedbackProps) => {
|
|||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
{transaction.txHash}
|
{transaction.txHash}
|
||||||
</a>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -2,8 +2,9 @@ import {
|
|||||||
t,
|
t,
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
toDecimal,
|
toDecimal,
|
||||||
|
Size,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { OrderType, Side } from '@vegaprotocol/types';
|
import { OrderType } from '@vegaprotocol/types';
|
||||||
import {
|
import {
|
||||||
FormGroup,
|
FormGroup,
|
||||||
Input,
|
Input,
|
||||||
@ -64,16 +65,15 @@ export const OrderEditDialog = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<p className={headerClassName}>{t(`Remaining size`)}</p>
|
<p className={headerClassName}>{t(`Size`)}</p>
|
||||||
<p
|
<p>
|
||||||
className={
|
{
|
||||||
order.side === Side.SIDE_BUY
|
<Size
|
||||||
? 'text-dark-green dark:text-vega-green'
|
value={order.size}
|
||||||
: 'text-red dark:text-vega-red'
|
side={order.side}
|
||||||
|
positionDecimalPlaces={order.market.positionDecimalPlaces}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
>
|
|
||||||
{order.side === Side.SIDE_BUY ? '+' : '-'}
|
|
||||||
{order.size}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
|
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
|
||||||
"ignorePatterns": ["!**/*"],
|
"ignorePatterns": ["!**/*", "__generated__"],
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||||
|
27
libs/react-helpers/src/hooks/__generated__/NetworkParams.ts
generated
Normal file
27
libs/react-helpers/src/hooks/__generated__/NetworkParams.ts
generated
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL query operation: NetworkParams
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface NetworkParams_networkParameters {
|
||||||
|
__typename: "NetworkParameter";
|
||||||
|
/**
|
||||||
|
* The name of the network parameter
|
||||||
|
*/
|
||||||
|
key: string;
|
||||||
|
/**
|
||||||
|
* The value of the network parameter
|
||||||
|
*/
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NetworkParams {
|
||||||
|
/**
|
||||||
|
* return the full list of network parameters
|
||||||
|
*/
|
||||||
|
networkParameters: NetworkParams_networkParameters[] | null;
|
||||||
|
}
|
1
libs/react-helpers/src/hooks/__generated__/index.ts
generated
Normal file
1
libs/react-helpers/src/hooks/__generated__/index.ts
generated
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './NetworkParams';
|
@ -1,7 +1,8 @@
|
|||||||
export * from './use-apply-grid-transaction';
|
export * from './use-apply-grid-transaction';
|
||||||
export * from './use-data-provider';
|
export * from './use-data-provider';
|
||||||
export * from './use-theme-switcher';
|
|
||||||
export * from './use-fetch';
|
export * from './use-fetch';
|
||||||
export * from './use-resize';
|
export * from './use-network-params';
|
||||||
export * from './use-outside-click';
|
export * from './use-outside-click';
|
||||||
|
export * from './use-resize';
|
||||||
export * from './use-screen-dimensions';
|
export * from './use-screen-dimensions';
|
||||||
|
export * from './use-theme-switcher';
|
||||||
|
37
libs/react-helpers/src/hooks/use-network-params.ts
Normal file
37
libs/react-helpers/src/hooks/use-network-params.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { gql, useQuery } from '@apollo/client';
|
||||||
|
import type { NetworkParams } from './__generated__/NetworkParams';
|
||||||
|
|
||||||
|
export const NETWORK_PARAMETERS_QUERY = gql`
|
||||||
|
query NetworkParams {
|
||||||
|
networkParameters {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const useNetworkParam = (param: string) => {
|
||||||
|
const { data, loading, error } = useQuery<NetworkParams, never>(
|
||||||
|
NETWORK_PARAMETERS_QUERY
|
||||||
|
);
|
||||||
|
const foundParams = data?.networkParameters?.filter((p) => param === p.key);
|
||||||
|
return {
|
||||||
|
data: foundParams ? foundParams.map((f) => f.value) : null,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useNetworkParams = (params: string[]) => {
|
||||||
|
const { data, loading, error } = useQuery<NetworkParams, never>(
|
||||||
|
NETWORK_PARAMETERS_QUERY
|
||||||
|
);
|
||||||
|
const foundParams = data?.networkParameters
|
||||||
|
?.filter((p) => params.includes(p.key))
|
||||||
|
.sort((a, b) => params.indexOf(a.key) - params.indexOf(b.key));
|
||||||
|
return {
|
||||||
|
data: foundParams ? foundParams.map((f) => f.value) : null,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
};
|
@ -1,5 +1,5 @@
|
|||||||
export * from './date';
|
export * from './date';
|
||||||
export * from './number';
|
export * from './number';
|
||||||
export * from './truncate';
|
|
||||||
export * from './size';
|
export * from './size';
|
||||||
|
export * from './truncate';
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
|
@ -3,5 +3,6 @@ export * from './cumulative-vol-cell';
|
|||||||
export * from './flash-cell';
|
export * from './flash-cell';
|
||||||
export * from './price-cell';
|
export * from './price-cell';
|
||||||
export * from './price-flash-cell';
|
export * from './price-flash-cell';
|
||||||
|
export * from './size';
|
||||||
export * from './summary-rows';
|
export * from './summary-rows';
|
||||||
export * from './vol-cell';
|
export * from './vol-cell';
|
47
libs/react-helpers/src/lib/grid/size.tsx
Normal file
47
libs/react-helpers/src/lib/grid/size.tsx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { Side } from '@vegaprotocol/types';
|
||||||
|
import type { ICellRendererParams } from 'ag-grid-community';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { addDecimalsFormatNumber } from '../format';
|
||||||
|
import { negativeClassNames, positiveClassNames } from './cell-class-rules';
|
||||||
|
|
||||||
|
export const Size = ({
|
||||||
|
value,
|
||||||
|
side,
|
||||||
|
positionDecimalPlaces = 0,
|
||||||
|
}: {
|
||||||
|
value: string;
|
||||||
|
side: Side;
|
||||||
|
positionDecimalPlaces?: number;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
data-testid="size"
|
||||||
|
className={classNames('text-right', {
|
||||||
|
[positiveClassNames]: side === Side.SIDE_BUY,
|
||||||
|
[negativeClassNames]: side === Side.SIDE_SELL,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{side === Side.SIDE_BUY ? '+' : side === Side.SIDE_SELL ? '-' : ''}
|
||||||
|
{addDecimalsFormatNumber(value, positionDecimalPlaces)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ISizeCellProps extends ICellRendererParams {
|
||||||
|
value: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SizeCell = ({ value, data }: ISizeCellProps) => {
|
||||||
|
if ((!value && value !== 0) || isNaN(Number(value))) {
|
||||||
|
return <span data-testid="size">-</span>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Size
|
||||||
|
value={value.toString()}
|
||||||
|
side={data.side}
|
||||||
|
positionDecimalPlaces={data.positionDecimalPlaces}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
SizeCell.displayName = 'SizeCell';
|
12
libs/react-helpers/src/lib/index.ts
Normal file
12
libs/react-helpers/src/lib/index.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export * from './context';
|
||||||
|
export * from './format';
|
||||||
|
export * from './grid';
|
||||||
|
export * from './storage';
|
||||||
|
export * from './validate';
|
||||||
|
export * from './assets';
|
||||||
|
export * from './determine-id';
|
||||||
|
export * from './generic-data-provider';
|
||||||
|
export * from './i18n';
|
||||||
|
export * from './pagination';
|
||||||
|
export * from './remove-0x';
|
||||||
|
export * from './time';
|
12
libs/types/src/__generated__/globalTypes.ts
generated
12
libs/types/src/__generated__/globalTypes.ts
generated
@ -98,6 +98,18 @@ export enum Interval {
|
|||||||
INTERVAL_I6H = "INTERVAL_I6H",
|
INTERVAL_I6H = "INTERVAL_I6H",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status of a liquidity provision order
|
||||||
|
*/
|
||||||
|
export enum LiquidityProvisionStatus {
|
||||||
|
STATUS_ACTIVE = "STATUS_ACTIVE",
|
||||||
|
STATUS_CANCELLED = "STATUS_CANCELLED",
|
||||||
|
STATUS_PENDING = "STATUS_PENDING",
|
||||||
|
STATUS_REJECTED = "STATUS_REJECTED",
|
||||||
|
STATUS_STOPPED = "STATUS_STOPPED",
|
||||||
|
STATUS_UNDEPLOYED = "STATUS_UNDEPLOYED",
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current state of a market
|
* The current state of a market
|
||||||
*/
|
*/
|
||||||
|
@ -17,6 +17,18 @@ export enum AccountTypeMapping {
|
|||||||
ACCOUNT_TYPE_SETTLEMENT = 'Settlement',
|
ACCOUNT_TYPE_SETTLEMENT = 'Settlement',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status of a liquidity provision order
|
||||||
|
*/
|
||||||
|
export enum LiquidityProvisionStatusMapping {
|
||||||
|
STATUS_ACTIVE = 'Active',
|
||||||
|
STATUS_CANCELLED = 'Cancelled',
|
||||||
|
STATUS_PENDING = 'Pending',
|
||||||
|
STATUS_REJECTED = 'Rejected',
|
||||||
|
STATUS_STOPPED = 'Stopped',
|
||||||
|
STATUS_UNDEPLOYED = 'Undeployed',
|
||||||
|
}
|
||||||
|
|
||||||
export enum AuctionTriggerMapping {
|
export enum AuctionTriggerMapping {
|
||||||
AUCTION_TRIGGER_BATCH = 'batch',
|
AUCTION_TRIGGER_BATCH = 'batch',
|
||||||
AUCTION_TRIGGER_LIQUIDITY = 'liquidity',
|
AUCTION_TRIGGER_LIQUIDITY = 'liquidity',
|
||||||
@ -25,17 +37,6 @@ export enum AuctionTriggerMapping {
|
|||||||
AUCTION_TRIGGER_UNSPECIFIED = 'unspecified',
|
AUCTION_TRIGGER_UNSPECIFIED = 'unspecified',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Comparator describes the type of comparison.
|
|
||||||
*/
|
|
||||||
export enum ConditionOperatorMapping {
|
|
||||||
OPERATOR_EQUALS = 'EQUALS',
|
|
||||||
OPERATOR_GREATER_THAN = 'GREATER_THAN',
|
|
||||||
OPERATOR_GREATER_THAN_OR_EQUAL = 'GREATER_THAN_OR_EQUAL',
|
|
||||||
OPERATOR_LESS_THAN = 'LESS_THAN',
|
|
||||||
OPERATOR_LESS_THAN_OR_EQUAL = 'LESS_THAN_OR_EQUAL',
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The status of a deposit
|
* The status of a deposit
|
||||||
*/
|
*/
|
||||||
@ -201,7 +202,7 @@ export enum ProposalRejectionReasonMapping {
|
|||||||
PROPOSAL_ERROR_INVALID_SHAPE = 'Invalid shape',
|
PROPOSAL_ERROR_INVALID_SHAPE = 'Invalid shape',
|
||||||
PROPOSAL_ERROR_MAJORITY_THRESHOLD_NOT_REACHED = 'Majority threshold not reached',
|
PROPOSAL_ERROR_MAJORITY_THRESHOLD_NOT_REACHED = 'Majority threshold not reached',
|
||||||
PROPOSAL_ERROR_MARKET_MISSING_LIQUIDITY_COMMITMENT = 'Market missing liquidity commitment',
|
PROPOSAL_ERROR_MARKET_MISSING_LIQUIDITY_COMMITMENT = 'Market missing liquidity commitment',
|
||||||
PROPOSAL_ERROR_MISSING_BUILTIN_ASSET_FIELD = 'Missing builtin asset field',
|
PROPOSAL_ERROR_MISSING_BUILTIN_ASSET_FIELD = 'Missing built-in asset field',
|
||||||
PROPOSAL_ERROR_MISSING_COMMITMENT_AMOUNT = 'Missing commitment amount',
|
PROPOSAL_ERROR_MISSING_COMMITMENT_AMOUNT = 'Missing commitment amount',
|
||||||
PROPOSAL_ERROR_MISSING_ERC20_CONTRACT_ADDRESS = 'Missing ERC20 contract address',
|
PROPOSAL_ERROR_MISSING_ERC20_CONTRACT_ADDRESS = 'Missing ERC20 contract address',
|
||||||
PROPOSAL_ERROR_NETWORK_PARAMETER_INVALID_KEY = 'Network parameter invalid key',
|
PROPOSAL_ERROR_NETWORK_PARAMETER_INVALID_KEY = 'Network parameter invalid key',
|
||||||
|
@ -5,11 +5,12 @@ import { Children, isValidElement, useState } from 'react';
|
|||||||
|
|
||||||
interface TabsProps {
|
interface TabsProps {
|
||||||
children: ReactElement<TabProps>[];
|
children: ReactElement<TabProps>[];
|
||||||
|
active?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Tabs = ({ children }: TabsProps) => {
|
export const Tabs = ({ children, active: activeDefaultId }: TabsProps) => {
|
||||||
const [activeTab, setActiveTab] = useState<string>(() => {
|
const [activeTab, setActiveTab] = useState<string>(() => {
|
||||||
return children[0].props.id;
|
return activeDefaultId ?? children[0].props.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -24,7 +25,7 @@ export const Tabs = ({ children }: TabsProps) => {
|
|||||||
role="tablist"
|
role="tablist"
|
||||||
>
|
>
|
||||||
{Children.map(children, (child) => {
|
{Children.map(children, (child) => {
|
||||||
if (!isValidElement(child)) return null;
|
if (!isValidElement(child) || child.props.hidden) return null;
|
||||||
const isActive = child.props.id === activeTab;
|
const isActive = child.props.id === activeTab;
|
||||||
const triggerClass = classNames(
|
const triggerClass = classNames(
|
||||||
'relative px-4 py-2 border-r border-neutral-300 dark:border-neutral-700',
|
'relative px-4 py-2 border-r border-neutral-300 dark:border-neutral-700',
|
||||||
@ -51,7 +52,7 @@ export const Tabs = ({ children }: TabsProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="h-full overflow-auto">
|
<div className="h-full overflow-auto">
|
||||||
{Children.map(children, (child) => {
|
{Children.map(children, (child) => {
|
||||||
if (!isValidElement(child)) return null;
|
if (!isValidElement(child) || child.props.hidden) return null;
|
||||||
return (
|
return (
|
||||||
<TabsPrimitive.Content
|
<TabsPrimitive.Content
|
||||||
value={child.props.id}
|
value={child.props.id}
|
||||||
@ -71,6 +72,7 @@ interface TabProps {
|
|||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
hidden?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Tab = ({ children, ...props }: TabProps) => {
|
export const Tab = ({ children, ...props }: TabProps) => {
|
||||||
|
@ -10,3 +10,4 @@ export * from './lib/use-verify-withdrawal';
|
|||||||
export * from './lib/use-withdrawals';
|
export * from './lib/use-withdrawals';
|
||||||
export * from './lib/__generated__/Withdrawals';
|
export * from './lib/__generated__/Withdrawals';
|
||||||
export * from './lib/__generated__/WithdrawalFields';
|
export * from './lib/__generated__/WithdrawalFields';
|
||||||
|
export * from './lib/__generated__/WithdrawFormQuery';
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
"@vegaprotocol/environment": ["libs/environment/src/index.ts"],
|
"@vegaprotocol/environment": ["libs/environment/src/index.ts"],
|
||||||
"@vegaprotocol/fills": ["libs/fills/src/index.ts"],
|
"@vegaprotocol/fills": ["libs/fills/src/index.ts"],
|
||||||
"@vegaprotocol/governance": ["libs/governance/src/index.ts"],
|
"@vegaprotocol/governance": ["libs/governance/src/index.ts"],
|
||||||
|
"@vegaprotocol/liquidity": ["libs/liquidity/src/index.ts"],
|
||||||
"@vegaprotocol/market-depth": ["libs/market-depth/src/index.ts"],
|
"@vegaprotocol/market-depth": ["libs/market-depth/src/index.ts"],
|
||||||
"@vegaprotocol/market-list": ["libs/market-list/src/index.ts"],
|
"@vegaprotocol/market-list": ["libs/market-list/src/index.ts"],
|
||||||
"@vegaprotocol/network-info": ["libs/network-info/src/index.ts"],
|
"@vegaprotocol/network-info": ["libs/network-info/src/index.ts"],
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"explorer-e2e": "apps/explorer-e2e",
|
"explorer-e2e": "apps/explorer-e2e",
|
||||||
"fills": "libs/fills",
|
"fills": "libs/fills",
|
||||||
"governance": "libs/governance",
|
"governance": "libs/governance",
|
||||||
|
"liquidity": "libs/liquidity",
|
||||||
"market-depth": "libs/market-depth",
|
"market-depth": "libs/market-depth",
|
||||||
"market-list": "libs/market-list",
|
"market-list": "libs/market-list",
|
||||||
"network-info": "libs/network-info",
|
"network-info": "libs/network-info",
|
||||||
|
Loading…
Reference in New Issue
Block a user