feat(deal-ticket): update fields in margin details (#5722)
This commit is contained in:
parent
f62e29c67f
commit
b4e98e285e
@ -33,7 +33,7 @@ def test_should_display_info_and_button_for_deposit(continuous_market, page: Pag
|
|||||||
"You may not have enough margin available to open this position.")
|
"You may not have enough margin available to open this position.")
|
||||||
page.get_by_test_id(deal_ticket_warning_margin).hover()
|
page.get_by_test_id(deal_ticket_warning_margin).hover()
|
||||||
expect(page.get_by_test_id("tooltip-content").nth(0)).to_have_text(
|
expect(page.get_by_test_id("tooltip-content").nth(0)).to_have_text(
|
||||||
"1,661,896.6317 tDAI is currently required.You have only 1,000,000.00.Deposit tDAI")
|
"1,661,888.12901 tDAI is currently required.You have only 999,991.49731.Deposit tDAI")
|
||||||
page.get_by_test_id(deal_ticket_deposit_dialog_button).nth(0).click()
|
page.get_by_test_id(deal_ticket_deposit_dialog_button).nth(0).click()
|
||||||
expect(page.get_by_test_id("sidebar-content")
|
expect(page.get_by_test_id("sidebar-content")
|
||||||
).to_contain_text("DepositFrom")
|
).to_contain_text("DepositFrom")
|
||||||
|
@ -3,27 +3,13 @@ import { getAsset, getQuoteName } from '@vegaprotocol/markets';
|
|||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import { AccountBreakdownDialog } from '@vegaprotocol/accounts';
|
import { AccountBreakdownDialog } from '@vegaprotocol/accounts';
|
||||||
import { formatRange, formatValue } from '@vegaprotocol/utils';
|
import { formatRange, formatValue } from '@vegaprotocol/utils';
|
||||||
import { marketMarginDataProvider } from '@vegaprotocol/accounts';
|
|
||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
|
||||||
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import {
|
import {
|
||||||
MARGIN_DIFF_TOOLTIP_TEXT,
|
|
||||||
DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT,
|
|
||||||
TOTAL_MARGIN_AVAILABLE,
|
|
||||||
LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT,
|
LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT,
|
||||||
EST_TOTAL_MARGIN_TOOLTIP_TEXT,
|
|
||||||
MARGIN_ACCOUNT_TOOLTIP_TEXT,
|
MARGIN_ACCOUNT_TOOLTIP_TEXT,
|
||||||
} from '../../constants';
|
} from '../../constants';
|
||||||
import { KeyValue } from './key-value';
|
import { KeyValue } from './key-value';
|
||||||
import {
|
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||||
Accordion,
|
|
||||||
AccordionChevron,
|
|
||||||
AccordionPanel,
|
|
||||||
ExternalLink,
|
|
||||||
Tooltip,
|
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { useT, ns } from '../../use-t';
|
import { useT, ns } from '../../use-t';
|
||||||
import { Trans } from 'react-i18next';
|
import { Trans } from 'react-i18next';
|
||||||
import type { Market } from '@vegaprotocol/markets';
|
import type { Market } from '@vegaprotocol/markets';
|
||||||
@ -31,9 +17,9 @@ import { emptyValue } from './deal-ticket-fee-details';
|
|||||||
import type { EstimatePositionQuery } from '@vegaprotocol/positions';
|
import type { EstimatePositionQuery } from '@vegaprotocol/positions';
|
||||||
|
|
||||||
export interface DealTicketMarginDetailsProps {
|
export interface DealTicketMarginDetailsProps {
|
||||||
generalAccountBalance?: string;
|
generalAccountBalance: string;
|
||||||
marginAccountBalance?: string;
|
marginAccountBalance: string;
|
||||||
orderMarginAccountBalance?: string;
|
orderMarginAccountBalance: string;
|
||||||
market: Market;
|
market: Market;
|
||||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
assetSymbol: string;
|
assetSymbol: string;
|
||||||
@ -54,25 +40,13 @@ export const DealTicketMarginDetails = ({
|
|||||||
const t = useT();
|
const t = useT();
|
||||||
const [breakdownDialog, setBreakdownDialog] = useState(false);
|
const [breakdownDialog, setBreakdownDialog] = useState(false);
|
||||||
const { pubKey: partyId } = useVegaWallet();
|
const { pubKey: partyId } = useVegaWallet();
|
||||||
const { data: currentMargins } = useDataProvider({
|
|
||||||
dataProvider: marketMarginDataProvider,
|
|
||||||
variables: { marketId: market.id, partyId: partyId || '' },
|
|
||||||
skip: !partyId,
|
|
||||||
});
|
|
||||||
const isInIsolatedMode =
|
|
||||||
positionEstimate?.margin.bestCase.marginMode ===
|
|
||||||
Schema.MarginMode.MARGIN_MODE_ISOLATED_MARGIN;
|
|
||||||
const liquidationEstimate = positionEstimate?.liquidation;
|
const liquidationEstimate = positionEstimate?.liquidation;
|
||||||
const marginEstimate = positionEstimate?.margin;
|
|
||||||
const totalMarginAccountBalance =
|
const totalMarginAccountBalance =
|
||||||
BigInt(marginAccountBalance || '0') +
|
BigInt(marginAccountBalance || '0') +
|
||||||
BigInt(orderMarginAccountBalance || '0');
|
BigInt(orderMarginAccountBalance || '0');
|
||||||
const totalBalance =
|
|
||||||
BigInt(generalAccountBalance || '0') + totalMarginAccountBalance;
|
|
||||||
const asset = getAsset(market);
|
const asset = getAsset(market);
|
||||||
const { decimals: assetDecimals, quantum } = asset;
|
const { decimals: assetDecimals, quantum } = asset;
|
||||||
let marginRequiredBestCase: string | undefined = undefined;
|
|
||||||
let marginRequiredWorstCase: string | undefined = undefined;
|
|
||||||
|
|
||||||
const collateralIncreaseEstimateBestCase = BigInt(
|
const collateralIncreaseEstimateBestCase = BigInt(
|
||||||
positionEstimate?.collateralIncreaseEstimate.bestCase ?? '0'
|
positionEstimate?.collateralIncreaseEstimate.bestCase ?? '0'
|
||||||
@ -80,102 +54,6 @@ export const DealTicketMarginDetails = ({
|
|||||||
const collateralIncreaseEstimateWorstCase = BigInt(
|
const collateralIncreaseEstimateWorstCase = BigInt(
|
||||||
positionEstimate?.collateralIncreaseEstimate.worstCase ?? '0'
|
positionEstimate?.collateralIncreaseEstimate.worstCase ?? '0'
|
||||||
);
|
);
|
||||||
const marginEstimateBestCase = isInIsolatedMode
|
|
||||||
? totalMarginAccountBalance + collateralIncreaseEstimateBestCase
|
|
||||||
: BigInt(marginEstimate?.bestCase.initialLevel ?? 0);
|
|
||||||
const marginEstimateWorstCase = isInIsolatedMode
|
|
||||||
? totalMarginAccountBalance + collateralIncreaseEstimateWorstCase
|
|
||||||
: BigInt(marginEstimate?.worstCase.initialLevel ?? 0);
|
|
||||||
if (isInIsolatedMode) {
|
|
||||||
marginRequiredBestCase = collateralIncreaseEstimateBestCase.toString();
|
|
||||||
marginRequiredWorstCase = collateralIncreaseEstimateWorstCase.toString();
|
|
||||||
} else if (marginEstimate) {
|
|
||||||
if (currentMargins) {
|
|
||||||
const currentMargin = BigInt(currentMargins.initialLevel);
|
|
||||||
marginRequiredBestCase = (
|
|
||||||
marginEstimateBestCase - currentMargin
|
|
||||||
).toString();
|
|
||||||
if (marginRequiredBestCase.startsWith('-')) {
|
|
||||||
marginRequiredBestCase = '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
marginRequiredWorstCase = (
|
|
||||||
marginEstimateWorstCase - currentMargin
|
|
||||||
).toString();
|
|
||||||
|
|
||||||
if (marginRequiredWorstCase.startsWith('-')) {
|
|
||||||
marginRequiredWorstCase = '0';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
marginRequiredBestCase = marginEstimateBestCase.toString();
|
|
||||||
marginRequiredWorstCase = marginEstimateWorstCase.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalMarginAvailable = (
|
|
||||||
currentMargins
|
|
||||||
? totalBalance - BigInt(currentMargins.maintenanceLevel)
|
|
||||||
: totalBalance
|
|
||||||
).toString();
|
|
||||||
|
|
||||||
let deductionFromCollateral = null;
|
|
||||||
let projectedMargin = null;
|
|
||||||
if (totalMarginAccountBalance) {
|
|
||||||
const deductionFromCollateralBestCase =
|
|
||||||
marginEstimateBestCase - totalMarginAccountBalance;
|
|
||||||
|
|
||||||
const deductionFromCollateralWorstCase =
|
|
||||||
marginEstimateWorstCase - totalMarginAccountBalance;
|
|
||||||
|
|
||||||
deductionFromCollateral = (
|
|
||||||
<KeyValue
|
|
||||||
indent
|
|
||||||
label={t('Deduction from collateral')}
|
|
||||||
value={formatRange(
|
|
||||||
deductionFromCollateralBestCase > 0
|
|
||||||
? deductionFromCollateralBestCase.toString()
|
|
||||||
: '0',
|
|
||||||
deductionFromCollateralWorstCase > 0
|
|
||||||
? deductionFromCollateralWorstCase.toString()
|
|
||||||
: '0',
|
|
||||||
assetDecimals
|
|
||||||
)}
|
|
||||||
formattedValue={formatValue(
|
|
||||||
deductionFromCollateralWorstCase > 0
|
|
||||||
? deductionFromCollateralWorstCase.toString()
|
|
||||||
: '0',
|
|
||||||
assetDecimals,
|
|
||||||
quantum
|
|
||||||
)}
|
|
||||||
symbol={assetSymbol}
|
|
||||||
labelDescription={t(
|
|
||||||
'DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT',
|
|
||||||
DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT,
|
|
||||||
{ assetSymbol }
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
projectedMargin = (
|
|
||||||
<KeyValue
|
|
||||||
label={t('Projected margin')}
|
|
||||||
value={formatRange(
|
|
||||||
marginEstimateBestCase.toString(),
|
|
||||||
marginEstimateWorstCase.toString(),
|
|
||||||
assetDecimals
|
|
||||||
)}
|
|
||||||
formattedValue={formatValue(
|
|
||||||
marginEstimateWorstCase.toString(),
|
|
||||||
assetDecimals,
|
|
||||||
quantum
|
|
||||||
)}
|
|
||||||
symbol={assetSymbol}
|
|
||||||
labelDescription={t(
|
|
||||||
'EST_TOTAL_MARGIN_TOOLTIP_TEXT',
|
|
||||||
EST_TOTAL_MARGIN_TOOLTIP_TEXT
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let liquidationPriceEstimate = emptyValue;
|
let liquidationPriceEstimate = emptyValue;
|
||||||
let liquidationPriceEstimateRange = emptyValue;
|
let liquidationPriceEstimateRange = emptyValue;
|
||||||
@ -232,128 +110,50 @@ export const DealTicketMarginDetails = ({
|
|||||||
const quoteName = getQuoteName(market);
|
const quoteName = getQuoteName(market);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col w-full gap-2">
|
<div className="flex flex-col w-full gap-2 mt-2">
|
||||||
<Accordion>
|
|
||||||
<AccordionPanel
|
|
||||||
itemId="margin"
|
|
||||||
trigger={
|
|
||||||
<AccordionPrimitive.Trigger
|
|
||||||
data-testid="accordion-toggle"
|
|
||||||
className={classNames(
|
|
||||||
'w-full pt-2',
|
|
||||||
'flex items-center gap-2 text-xs',
|
|
||||||
'group'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
data-testid={`deal-ticket-fee-margin-required`}
|
|
||||||
key={'value-dropdown'}
|
|
||||||
className="flex items-center justify-between w-full gap-2"
|
|
||||||
>
|
|
||||||
<div className="flex items-center text-left gap-1">
|
|
||||||
<Tooltip
|
|
||||||
description={t(
|
|
||||||
'MARGIN_DIFF_TOOLTIP_TEXT',
|
|
||||||
MARGIN_DIFF_TOOLTIP_TEXT,
|
|
||||||
{ assetSymbol }
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<span className="text-muted">{t('Margin required')}</span>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<AccordionChevron size={10} />
|
|
||||||
</div>
|
|
||||||
<Tooltip
|
|
||||||
description={
|
|
||||||
formatRange(
|
|
||||||
marginRequiredBestCase,
|
|
||||||
marginRequiredWorstCase,
|
|
||||||
assetDecimals
|
|
||||||
) ?? '-'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className="font-mono text-right">
|
|
||||||
{formatValue(
|
|
||||||
marginRequiredWorstCase,
|
|
||||||
assetDecimals,
|
|
||||||
quantum
|
|
||||||
)}{' '}
|
|
||||||
{assetSymbol || ''}
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</AccordionPrimitive.Trigger>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className="flex flex-col w-full gap-2">
|
|
||||||
<KeyValue
|
|
||||||
label={t('Total margin available')}
|
|
||||||
indent
|
|
||||||
value={formatValue(totalMarginAvailable, assetDecimals)}
|
|
||||||
formattedValue={formatValue(
|
|
||||||
totalMarginAvailable,
|
|
||||||
assetDecimals,
|
|
||||||
quantum
|
|
||||||
)}
|
|
||||||
symbol={assetSymbol}
|
|
||||||
labelDescription={t(
|
|
||||||
'TOTAL_MARGIN_AVAILABLE',
|
|
||||||
TOTAL_MARGIN_AVAILABLE,
|
|
||||||
{
|
|
||||||
generalAccountBalance: formatValue(
|
|
||||||
generalAccountBalance,
|
|
||||||
assetDecimals,
|
|
||||||
quantum
|
|
||||||
),
|
|
||||||
marginAccountBalance: formatValue(
|
|
||||||
marginAccountBalance,
|
|
||||||
assetDecimals,
|
|
||||||
quantum
|
|
||||||
),
|
|
||||||
orderMarginAccountBalance: formatValue(
|
|
||||||
orderMarginAccountBalance,
|
|
||||||
assetDecimals,
|
|
||||||
quantum
|
|
||||||
),
|
|
||||||
marginMaintenance: formatValue(
|
|
||||||
currentMargins?.maintenanceLevel,
|
|
||||||
assetDecimals,
|
|
||||||
quantum
|
|
||||||
),
|
|
||||||
assetSymbol,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{deductionFromCollateral}
|
|
||||||
<KeyValue
|
|
||||||
label={t('Current margin allocation')}
|
|
||||||
indent
|
|
||||||
onClick={
|
|
||||||
generalAccountBalance
|
|
||||||
? () => setBreakdownDialog(true)
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
value={formatValue(
|
|
||||||
totalMarginAccountBalance.toString(),
|
|
||||||
assetDecimals
|
|
||||||
)}
|
|
||||||
symbol={assetSymbol}
|
|
||||||
labelDescription={t(
|
|
||||||
'MARGIN_ACCOUNT_TOOLTIP_TEXT',
|
|
||||||
MARGIN_ACCOUNT_TOOLTIP_TEXT
|
|
||||||
)}
|
|
||||||
formattedValue={formatValue(
|
|
||||||
totalMarginAccountBalance.toString(),
|
|
||||||
assetDecimals,
|
|
||||||
quantum
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</AccordionPanel>
|
|
||||||
</Accordion>
|
|
||||||
{projectedMargin}
|
|
||||||
<KeyValue
|
<KeyValue
|
||||||
label={t('Liquidation')}
|
label={t('Current margin')}
|
||||||
|
onClick={
|
||||||
|
generalAccountBalance ? () => setBreakdownDialog(true) : undefined
|
||||||
|
}
|
||||||
|
value={formatValue(totalMarginAccountBalance.toString(), assetDecimals)}
|
||||||
|
symbol={assetSymbol}
|
||||||
|
labelDescription={t(
|
||||||
|
'MARGIN_ACCOUNT_TOOLTIP_TEXT',
|
||||||
|
MARGIN_ACCOUNT_TOOLTIP_TEXT
|
||||||
|
)}
|
||||||
|
formattedValue={formatValue(
|
||||||
|
totalMarginAccountBalance.toString(),
|
||||||
|
assetDecimals,
|
||||||
|
quantum
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<KeyValue
|
||||||
|
label={t('Available collateral')}
|
||||||
|
value={formatValue(generalAccountBalance, assetDecimals)}
|
||||||
|
formattedValue={formatValue(
|
||||||
|
generalAccountBalance.toString(),
|
||||||
|
assetDecimals,
|
||||||
|
quantum
|
||||||
|
)}
|
||||||
|
symbol={assetSymbol}
|
||||||
|
/>
|
||||||
|
<KeyValue
|
||||||
|
label={t('Additional margin required')}
|
||||||
|
value={formatRange(
|
||||||
|
collateralIncreaseEstimateBestCase.toString(),
|
||||||
|
collateralIncreaseEstimateWorstCase.toString(),
|
||||||
|
assetDecimals
|
||||||
|
)}
|
||||||
|
formattedValue={formatValue(
|
||||||
|
collateralIncreaseEstimateBestCase.toString(),
|
||||||
|
assetDecimals,
|
||||||
|
quantum
|
||||||
|
)}
|
||||||
|
symbol={assetSymbol}
|
||||||
|
/>
|
||||||
|
<KeyValue
|
||||||
|
label={t('Liquidation estimate')}
|
||||||
value={liquidationPriceEstimateRange}
|
value={liquidationPriceEstimateRange}
|
||||||
formattedValue={liquidationPriceEstimate}
|
formattedValue={liquidationPriceEstimate}
|
||||||
symbol={quoteName}
|
symbol={quoteName}
|
||||||
|
@ -73,7 +73,7 @@ import {
|
|||||||
} from '../../hooks';
|
} from '../../hooks';
|
||||||
import { DealTicketSizeIceberg } from './deal-ticket-size-iceberg';
|
import { DealTicketSizeIceberg } from './deal-ticket-size-iceberg';
|
||||||
import noop from 'lodash/noop';
|
import noop from 'lodash/noop';
|
||||||
import { isNonPersistentOrder } from '../../utils/time-in-force-persistance';
|
import { isNonPersistentOrder } from '../../utils/time-in-force-persistence';
|
||||||
import { KeyValue } from './key-value';
|
import { KeyValue } from './key-value';
|
||||||
import { DocsLinks } from '@vegaprotocol/environment';
|
import { DocsLinks } from '@vegaprotocol/environment';
|
||||||
import { useT } from '../../use-t';
|
import { useT } from '../../use-t';
|
||||||
@ -177,12 +177,6 @@ export const DealTicket = ({
|
|||||||
loading: loadingGeneralAccountBalance,
|
loading: loadingGeneralAccountBalance,
|
||||||
} = useAccountBalance(asset.id);
|
} = useAccountBalance(asset.id);
|
||||||
|
|
||||||
const balance = (
|
|
||||||
BigInt(marginAccountBalance) +
|
|
||||||
BigInt(generalAccountBalance) +
|
|
||||||
BigInt(orderMarginAccountBalance)
|
|
||||||
).toString();
|
|
||||||
|
|
||||||
const { marketState, marketTradingMode } = marketData;
|
const { marketState, marketTradingMode } = marketData;
|
||||||
const timeInForce = watch('timeInForce');
|
const timeInForce = watch('timeInForce');
|
||||||
|
|
||||||
@ -729,17 +723,11 @@ export const DealTicket = ({
|
|||||||
error={summaryError}
|
error={summaryError}
|
||||||
asset={asset}
|
asset={asset}
|
||||||
marketTradingMode={marketData.marketTradingMode}
|
marketTradingMode={marketData.marketTradingMode}
|
||||||
balance={balance}
|
balance={generalAccountBalance}
|
||||||
margin={(
|
margin={
|
||||||
BigInt(
|
positionEstimate?.estimatePosition?.collateralIncreaseEstimate
|
||||||
positionEstimate?.estimatePosition?.margin.bestCase.initialLevel ||
|
.bestCase || '0'
|
||||||
'0'
|
}
|
||||||
) +
|
|
||||||
BigInt(
|
|
||||||
positionEstimate?.estimatePosition?.margin.bestCase
|
|
||||||
.orderMarginLevel || '0'
|
|
||||||
)
|
|
||||||
).toString()}
|
|
||||||
isReadOnly={isReadOnly}
|
isReadOnly={isReadOnly}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
onDeposit={onDeposit}
|
onDeposit={onDeposit}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||||
import classnames from 'classnames';
|
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
|
|
||||||
export interface KeyValuePros {
|
export interface KeyValuePros {
|
||||||
@ -19,7 +18,6 @@ export const KeyValue = ({
|
|||||||
value,
|
value,
|
||||||
labelDescription,
|
labelDescription,
|
||||||
symbol,
|
symbol,
|
||||||
indent,
|
|
||||||
onClick,
|
onClick,
|
||||||
formattedValue,
|
formattedValue,
|
||||||
}: KeyValuePros) => {
|
}: KeyValuePros) => {
|
||||||
@ -43,10 +41,7 @@ export const KeyValue = ({
|
|||||||
: id
|
: id
|
||||||
}`}
|
}`}
|
||||||
key={typeof label === 'string' ? label : 'value-dropdown'}
|
key={typeof label === 'string' ? label : 'value-dropdown'}
|
||||||
className={classnames(
|
className="text-xs flex justify-between items-center gap-4 flex-wrap text-right"
|
||||||
'text-xs flex justify-between items-center gap-4 flex-wrap text-right',
|
|
||||||
{ 'ml-2': indent }
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
<Tooltip description={labelDescription}>
|
<Tooltip description={labelDescription}>
|
||||||
<div className="text-muted text-left">{label}</div>
|
<div className="text-muted text-left">{label}</div>
|
||||||
|
@ -29,6 +29,7 @@ import { usePositionEstimate } from '../../hooks/use-position-estimate';
|
|||||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||||
import { getAsset, useMarket } from '@vegaprotocol/markets';
|
import { getAsset, useMarket } from '@vegaprotocol/markets';
|
||||||
import { NoWalletWarning } from './deal-ticket';
|
import { NoWalletWarning } from './deal-ticket';
|
||||||
|
import { DealTicketMarginDetails } from './deal-ticket-margin-details';
|
||||||
|
|
||||||
const defaultLeverage = 10;
|
const defaultLeverage = 10;
|
||||||
|
|
||||||
@ -93,66 +94,78 @@ export const MarginChange = ({
|
|||||||
},
|
},
|
||||||
skip
|
skip
|
||||||
);
|
);
|
||||||
if (
|
if (!asset || !estimateMargin?.estimatePosition) {
|
||||||
!asset ||
|
|
||||||
!estimateMargin?.estimatePosition?.collateralIncreaseEstimate.worstCase ||
|
|
||||||
estimateMargin.estimatePosition.collateralIncreaseEstimate.worstCase === '0'
|
|
||||||
) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const collateralIncreaseEstimate = BigInt(
|
const collateralIncreaseEstimate = BigInt(
|
||||||
estimateMargin.estimatePosition.collateralIncreaseEstimate.worstCase
|
estimateMargin.estimatePosition.collateralIncreaseEstimate.worstCase
|
||||||
);
|
);
|
||||||
if (!collateralIncreaseEstimate) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let positionWarning = '';
|
let positionWarning = '';
|
||||||
if (orders?.length && openVolume !== '0') {
|
|
||||||
positionWarning = t(
|
|
||||||
'youHaveOpenPositionAndOrders',
|
|
||||||
'You have an existing position and open orders on this market.',
|
|
||||||
{
|
|
||||||
count: orders.length,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else if (!orders?.length) {
|
|
||||||
positionWarning = t('You have an existing position on this market.');
|
|
||||||
} else {
|
|
||||||
positionWarning = t(
|
|
||||||
'youHaveOpenOrders',
|
|
||||||
'You have open orders on this market.',
|
|
||||||
{
|
|
||||||
count: orders.length,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let marginChangeWarning = '';
|
let marginChangeWarning = '';
|
||||||
const amount = addDecimalsFormatNumber(
|
if (collateralIncreaseEstimate) {
|
||||||
collateralIncreaseEstimate.toString(),
|
if (orders?.length && openVolume !== '0') {
|
||||||
asset?.decimals
|
positionWarning = t(
|
||||||
);
|
'youHaveOpenPositionAndOrders',
|
||||||
const { symbol } = asset;
|
'You have an existing position and open orders on this market.',
|
||||||
const interpolation = { amount, symbol };
|
{
|
||||||
if (marginMode === Schema.MarginMode.MARGIN_MODE_CROSS_MARGIN) {
|
count: orders.length,
|
||||||
marginChangeWarning = t(
|
}
|
||||||
'Changing the margin mode will move {{amount}} {{symbol}} from your general account to fund the position.',
|
);
|
||||||
interpolation
|
} else if (!orders?.length) {
|
||||||
);
|
positionWarning = t('You have an existing position on this market.');
|
||||||
} else {
|
} else {
|
||||||
marginChangeWarning = t(
|
positionWarning = t(
|
||||||
'Changing the margin mode and leverage will move {{amount}} {{symbol}} from your general account to fund the position.',
|
'youHaveOpenOrders',
|
||||||
interpolation
|
'You have open orders on this market.',
|
||||||
|
{
|
||||||
|
count: orders.length,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const amount = addDecimalsFormatNumber(
|
||||||
|
collateralIncreaseEstimate.toString(),
|
||||||
|
asset?.decimals
|
||||||
);
|
);
|
||||||
|
const { symbol } = asset;
|
||||||
|
const interpolation = { amount, symbol };
|
||||||
|
if (marginMode === Schema.MarginMode.MARGIN_MODE_CROSS_MARGIN) {
|
||||||
|
marginChangeWarning = t(
|
||||||
|
'Changing the margin mode will move {{amount}} {{symbol}} from your general account to fund the position.',
|
||||||
|
interpolation
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
marginChangeWarning = t(
|
||||||
|
'Changing the margin mode and leverage will move {{amount}} {{symbol}} from your general account to fund the position.',
|
||||||
|
interpolation
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<Notification
|
{positionWarning && marginChangeWarning && (
|
||||||
intent={Intent.Warning}
|
<Notification
|
||||||
message={
|
intent={Intent.Warning}
|
||||||
<>
|
message={
|
||||||
<p>{positionWarning}</p>
|
<>
|
||||||
<p>{marginChangeWarning}</p>
|
<p>{positionWarning}</p>
|
||||||
</>
|
<p>{marginChangeWarning}</p>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<DealTicketMarginDetails
|
||||||
|
marginAccountBalance={marginAccountBalance}
|
||||||
|
generalAccountBalance={generalAccountBalance}
|
||||||
|
orderMarginAccountBalance={orderMarginAccountBalance}
|
||||||
|
assetSymbol={asset.symbol}
|
||||||
|
market={market}
|
||||||
|
positionEstimate={estimateMargin.estimatePosition}
|
||||||
|
side={
|
||||||
|
openVolume.startsWith('-')
|
||||||
|
? Schema.Side.SIDE_SELL
|
||||||
|
: Schema.Side.SIDE_BUY
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,7 +9,7 @@ import type {
|
|||||||
} from '../hooks/use-form-values';
|
} from '../hooks/use-form-values';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { removeDecimal, toNanoSeconds } from '@vegaprotocol/utils';
|
import { removeDecimal, toNanoSeconds } from '@vegaprotocol/utils';
|
||||||
import { isPersistentOrder } from './time-in-force-persistance';
|
import { isPersistentOrder } from './time-in-force-persistence';
|
||||||
|
|
||||||
export const mapFormValuesToOrderSubmission = (
|
export const mapFormValuesToOrderSubmission = (
|
||||||
order: OrderFormValues,
|
order: OrderFormValues,
|
||||||
|
@ -2,9 +2,9 @@ import { OrderTimeInForce } from '@vegaprotocol/types';
|
|||||||
import {
|
import {
|
||||||
isNonPersistentOrder,
|
isNonPersistentOrder,
|
||||||
isPersistentOrder,
|
isPersistentOrder,
|
||||||
} from './time-in-force-persistance';
|
} from './time-in-force-persistence';
|
||||||
|
|
||||||
it('isNonPeristentOrder', () => {
|
it('isNonPersistentOrder', () => {
|
||||||
expect(isNonPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_FOK)).toBe(true);
|
expect(isNonPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_FOK)).toBe(true);
|
||||||
expect(isNonPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_IOC)).toBe(true);
|
expect(isNonPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_IOC)).toBe(true);
|
||||||
expect(isNonPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_GTC)).toBe(false);
|
expect(isNonPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_GTC)).toBe(false);
|
||||||
@ -13,7 +13,7 @@ it('isNonPeristentOrder', () => {
|
|||||||
expect(isNonPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_GFN)).toBe(false);
|
expect(isNonPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_GFN)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('isPeristentOrder', () => {
|
it('isPersistentOrder', () => {
|
||||||
expect(isPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_FOK)).toBe(false);
|
expect(isPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_FOK)).toBe(false);
|
||||||
expect(isPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_IOC)).toBe(false);
|
expect(isPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_IOC)).toBe(false);
|
||||||
expect(isPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_GTC)).toBe(true);
|
expect(isPersistentOrder(OrderTimeInForce.TIME_IN_FORCE_GTC)).toBe(true);
|
@ -67,26 +67,6 @@ query EstimatePosition(
|
|||||||
# we can set this variable to true so that we can format with market.decimalPlaces
|
# we can set this variable to true so that we can format with market.decimalPlaces
|
||||||
scaleLiquidationPriceToMarketDecimals: true
|
scaleLiquidationPriceToMarketDecimals: true
|
||||||
) {
|
) {
|
||||||
margin {
|
|
||||||
worstCase {
|
|
||||||
maintenanceLevel
|
|
||||||
searchLevel
|
|
||||||
initialLevel
|
|
||||||
collateralReleaseLevel
|
|
||||||
marginMode
|
|
||||||
marginFactor
|
|
||||||
orderMarginLevel
|
|
||||||
}
|
|
||||||
bestCase {
|
|
||||||
maintenanceLevel
|
|
||||||
searchLevel
|
|
||||||
initialLevel
|
|
||||||
collateralReleaseLevel
|
|
||||||
marginMode
|
|
||||||
marginFactor
|
|
||||||
orderMarginLevel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
collateralIncreaseEstimate {
|
collateralIncreaseEstimate {
|
||||||
worstCase
|
worstCase
|
||||||
bestCase
|
bestCase
|
||||||
|
22
libs/positions/src/lib/__generated__/Positions.ts
generated
22
libs/positions/src/lib/__generated__/Positions.ts
generated
@ -33,7 +33,7 @@ export type EstimatePositionQueryVariables = Types.Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type EstimatePositionQuery = { __typename?: 'Query', estimatePosition?: { __typename?: 'PositionEstimate', margin: { __typename?: 'MarginEstimate', worstCase: { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string, marginMode: Types.MarginMode, marginFactor: string, orderMarginLevel: string }, bestCase: { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: string, marginMode: Types.MarginMode, marginFactor: string, orderMarginLevel: string } }, collateralIncreaseEstimate: { __typename?: 'CollateralIncreaseEstimate', worstCase: string, bestCase: string }, liquidation?: { __typename?: 'LiquidationEstimate', worstCase: { __typename?: 'LiquidationPrice', open_volume_only: string, including_buy_orders: string, including_sell_orders: string }, bestCase: { __typename?: 'LiquidationPrice', open_volume_only: string, including_buy_orders: string, including_sell_orders: string } } | null } | null };
|
export type EstimatePositionQuery = { __typename?: 'Query', estimatePosition?: { __typename?: 'PositionEstimate', collateralIncreaseEstimate: { __typename?: 'CollateralIncreaseEstimate', worstCase: string, bestCase: string }, liquidation?: { __typename?: 'LiquidationEstimate', worstCase: { __typename?: 'LiquidationPrice', open_volume_only: string, including_buy_orders: string, including_sell_orders: string }, bestCase: { __typename?: 'LiquidationPrice', open_volume_only: string, including_buy_orders: string, including_sell_orders: string } } | null } | null };
|
||||||
|
|
||||||
export const PositionFieldsFragmentDoc = gql`
|
export const PositionFieldsFragmentDoc = gql`
|
||||||
fragment PositionFields on Position {
|
fragment PositionFields on Position {
|
||||||
@ -144,26 +144,6 @@ export const EstimatePositionDocument = gql`
|
|||||||
includeCollateralIncreaseInAvailableCollateral: $includeCollateralIncreaseInAvailableCollateral
|
includeCollateralIncreaseInAvailableCollateral: $includeCollateralIncreaseInAvailableCollateral
|
||||||
scaleLiquidationPriceToMarketDecimals: true
|
scaleLiquidationPriceToMarketDecimals: true
|
||||||
) {
|
) {
|
||||||
margin {
|
|
||||||
worstCase {
|
|
||||||
maintenanceLevel
|
|
||||||
searchLevel
|
|
||||||
initialLevel
|
|
||||||
collateralReleaseLevel
|
|
||||||
marginMode
|
|
||||||
marginFactor
|
|
||||||
orderMarginLevel
|
|
||||||
}
|
|
||||||
bestCase {
|
|
||||||
maintenanceLevel
|
|
||||||
searchLevel
|
|
||||||
initialLevel
|
|
||||||
collateralReleaseLevel
|
|
||||||
marginMode
|
|
||||||
marginFactor
|
|
||||||
orderMarginLevel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
collateralIncreaseEstimate {
|
collateralIncreaseEstimate {
|
||||||
worstCase
|
worstCase
|
||||||
bestCase
|
bestCase
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import type { PartialDeep } from 'type-fest';
|
import type { PartialDeep } from 'type-fest';
|
||||||
import merge from 'lodash/merge';
|
import merge from 'lodash/merge';
|
||||||
import type { EstimatePositionQuery } from './__generated__/Positions';
|
import type { EstimatePositionQuery } from './__generated__/Positions';
|
||||||
import { MarginMode } from '@vegaprotocol/types';
|
|
||||||
|
|
||||||
export const estimatePositionQuery = (
|
export const estimatePositionQuery = (
|
||||||
override?: PartialDeep<EstimatePositionQuery>
|
override?: PartialDeep<EstimatePositionQuery>
|
||||||
@ -9,26 +8,6 @@ export const estimatePositionQuery = (
|
|||||||
const defaultResult: EstimatePositionQuery = {
|
const defaultResult: EstimatePositionQuery = {
|
||||||
estimatePosition: {
|
estimatePosition: {
|
||||||
__typename: 'PositionEstimate',
|
__typename: 'PositionEstimate',
|
||||||
margin: {
|
|
||||||
bestCase: {
|
|
||||||
collateralReleaseLevel: '1000000',
|
|
||||||
initialLevel: '500000',
|
|
||||||
maintenanceLevel: '200000',
|
|
||||||
searchLevel: '300000',
|
|
||||||
marginFactor: '1',
|
|
||||||
orderMarginLevel: '0',
|
|
||||||
marginMode: MarginMode.MARGIN_MODE_CROSS_MARGIN,
|
|
||||||
},
|
|
||||||
worstCase: {
|
|
||||||
collateralReleaseLevel: '1100000',
|
|
||||||
initialLevel: '600000',
|
|
||||||
maintenanceLevel: '300000',
|
|
||||||
searchLevel: '400000',
|
|
||||||
marginFactor: '1',
|
|
||||||
orderMarginLevel: '0',
|
|
||||||
marginMode: MarginMode.MARGIN_MODE_CROSS_MARGIN,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
collateralIncreaseEstimate: {
|
collateralIncreaseEstimate: {
|
||||||
bestCase: '0',
|
bestCase: '0',
|
||||||
worstCase: '0',
|
worstCase: '0',
|
||||||
|
@ -30,26 +30,6 @@ describe('LiquidationPrice', () => {
|
|||||||
result: {
|
result: {
|
||||||
data: {
|
data: {
|
||||||
estimatePosition: {
|
estimatePosition: {
|
||||||
margin: {
|
|
||||||
worstCase: {
|
|
||||||
maintenanceLevel: '100',
|
|
||||||
searchLevel: '100',
|
|
||||||
initialLevel: '100',
|
|
||||||
collateralReleaseLevel: '100',
|
|
||||||
orderMarginLevel: '0',
|
|
||||||
marginFactor: '0',
|
|
||||||
marginMode: MarginMode.MARGIN_MODE_CROSS_MARGIN,
|
|
||||||
},
|
|
||||||
bestCase: {
|
|
||||||
maintenanceLevel: '100',
|
|
||||||
searchLevel: '100',
|
|
||||||
initialLevel: '100',
|
|
||||||
collateralReleaseLevel: '100',
|
|
||||||
orderMarginLevel: '0',
|
|
||||||
marginFactor: '0',
|
|
||||||
marginMode: MarginMode.MARGIN_MODE_CROSS_MARGIN,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
collateralIncreaseEstimate: {
|
collateralIncreaseEstimate: {
|
||||||
bestCase: '0',
|
bestCase: '0',
|
||||||
worstCase: '0',
|
worstCase: '0',
|
||||||
|
Loading…
Reference in New Issue
Block a user