feat: use margin modes in deal ticket margin estimations
This commit is contained in:
@@ -1,47 +1,14 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { getAsset, getQuoteName } from '@vegaprotocol/markets';
|
||||
import { getAsset } from '@vegaprotocol/markets';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
import type { EstimatePositionQuery } from '@vegaprotocol/positions';
|
||||
import { AccountBreakdownDialog } from '@vegaprotocol/accounts';
|
||||
|
||||
import {
|
||||
formatNumberPercentage,
|
||||
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 {
|
||||
MARGIN_DIFF_TOOLTIP_TEXT,
|
||||
DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT,
|
||||
TOTAL_MARGIN_AVAILABLE,
|
||||
LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT,
|
||||
EST_TOTAL_MARGIN_TOOLTIP_TEXT,
|
||||
MARGIN_ACCOUNT_TOOLTIP_TEXT,
|
||||
} from '../../constants';
|
||||
import { formatNumberPercentage, formatValue } from '@vegaprotocol/utils';
|
||||
import { useEstimateFees } from '../../hooks/use-estimate-fees';
|
||||
import { KeyValue } from './key-value';
|
||||
import {
|
||||
Accordion,
|
||||
AccordionChevron,
|
||||
AccordionPanel,
|
||||
Intent,
|
||||
ExternalLink,
|
||||
Pill,
|
||||
Tooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import classNames from 'classnames';
|
||||
import { Intent, Pill } from '@vegaprotocol/ui-toolkit';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { FeesBreakdown } from '../fees-breakdown';
|
||||
import { getTotalDiscountFactor, getDiscountedFee } from '../discounts';
|
||||
import { useT, ns } from '../../use-t';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { useT } from '../../use-t';
|
||||
|
||||
export const emptyValue = '-';
|
||||
|
||||
@@ -119,337 +86,3 @@ export const DealTicketFeeDetails = ({
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export interface DealTicketMarginDetailsProps {
|
||||
generalAccountBalance?: string;
|
||||
marginAccountBalance?: string;
|
||||
market: Market;
|
||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||
assetSymbol: string;
|
||||
positionEstimate: EstimatePositionQuery['estimatePosition'];
|
||||
side: Schema.Side;
|
||||
}
|
||||
|
||||
export const DealTicketMarginDetails = ({
|
||||
marginAccountBalance,
|
||||
generalAccountBalance,
|
||||
assetSymbol,
|
||||
market,
|
||||
onMarketClick,
|
||||
positionEstimate,
|
||||
side,
|
||||
}: DealTicketMarginDetailsProps) => {
|
||||
const t = useT();
|
||||
const [breakdownDialog, setBreakdownDialog] = useState(false);
|
||||
const { pubKey: partyId } = useVegaWallet();
|
||||
const { data: currentMargins } = useDataProvider({
|
||||
dataProvider: marketMarginDataProvider,
|
||||
variables: { marketId: market.id, partyId: partyId || '' },
|
||||
skip: !partyId,
|
||||
});
|
||||
const liquidationEstimate = positionEstimate?.liquidation;
|
||||
const marginEstimate = positionEstimate?.margin;
|
||||
const totalBalance =
|
||||
BigInt(generalAccountBalance || '0') + BigInt(marginAccountBalance || '0');
|
||||
const asset = getAsset(market);
|
||||
const { decimals: assetDecimals, quantum } = asset;
|
||||
let marginRequiredBestCase: string | undefined = undefined;
|
||||
let marginRequiredWorstCase: string | undefined = undefined;
|
||||
if (marginEstimate) {
|
||||
if (currentMargins) {
|
||||
marginRequiredBestCase = (
|
||||
BigInt(marginEstimate.bestCase.initialLevel) -
|
||||
BigInt(currentMargins.initialLevel)
|
||||
).toString();
|
||||
if (marginRequiredBestCase.startsWith('-')) {
|
||||
marginRequiredBestCase = '0';
|
||||
}
|
||||
marginRequiredWorstCase = (
|
||||
BigInt(marginEstimate.worstCase.initialLevel) -
|
||||
BigInt(currentMargins.initialLevel)
|
||||
).toString();
|
||||
if (marginRequiredWorstCase.startsWith('-')) {
|
||||
marginRequiredWorstCase = '0';
|
||||
}
|
||||
} else {
|
||||
marginRequiredBestCase = marginEstimate.bestCase.initialLevel;
|
||||
marginRequiredWorstCase = marginEstimate.worstCase.initialLevel;
|
||||
}
|
||||
}
|
||||
|
||||
const totalMarginAvailable = (
|
||||
currentMargins
|
||||
? totalBalance - BigInt(currentMargins.maintenanceLevel)
|
||||
: totalBalance
|
||||
).toString();
|
||||
|
||||
let deductionFromCollateral = null;
|
||||
let projectedMargin = null;
|
||||
if (marginAccountBalance) {
|
||||
const deductionFromCollateralBestCase =
|
||||
BigInt(marginEstimate?.bestCase.initialLevel ?? 0) -
|
||||
BigInt(marginAccountBalance);
|
||||
|
||||
const deductionFromCollateralWorstCase =
|
||||
BigInt(marginEstimate?.worstCase.initialLevel ?? 0) -
|
||||
BigInt(marginAccountBalance);
|
||||
|
||||
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(
|
||||
marginEstimate?.bestCase.initialLevel,
|
||||
marginEstimate?.worstCase.initialLevel,
|
||||
assetDecimals
|
||||
)}
|
||||
formattedValue={formatValue(
|
||||
marginEstimate?.worstCase.initialLevel,
|
||||
assetDecimals,
|
||||
quantum
|
||||
)}
|
||||
symbol={assetSymbol}
|
||||
labelDescription={t(
|
||||
'EST_TOTAL_MARGIN_TOOLTIP_TEXT',
|
||||
EST_TOTAL_MARGIN_TOOLTIP_TEXT
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
let liquidationPriceEstimate = emptyValue;
|
||||
let liquidationPriceEstimateRange = emptyValue;
|
||||
|
||||
if (liquidationEstimate) {
|
||||
const liquidationEstimateBestCaseIncludingBuyOrders = BigInt(
|
||||
liquidationEstimate.bestCase.including_buy_orders.replace(/\..*/, '')
|
||||
);
|
||||
const liquidationEstimateBestCaseIncludingSellOrders = BigInt(
|
||||
liquidationEstimate.bestCase.including_sell_orders.replace(/\..*/, '')
|
||||
);
|
||||
const liquidationEstimateBestCase =
|
||||
side === Schema.Side.SIDE_BUY
|
||||
? liquidationEstimateBestCaseIncludingBuyOrders
|
||||
: liquidationEstimateBestCaseIncludingSellOrders;
|
||||
|
||||
const liquidationEstimateWorstCaseIncludingBuyOrders = BigInt(
|
||||
liquidationEstimate.worstCase.including_buy_orders.replace(/\..*/, '')
|
||||
);
|
||||
const liquidationEstimateWorstCaseIncludingSellOrders = BigInt(
|
||||
liquidationEstimate.worstCase.including_sell_orders.replace(/\..*/, '')
|
||||
);
|
||||
const liquidationEstimateWorstCase =
|
||||
side === Schema.Side.SIDE_BUY
|
||||
? liquidationEstimateWorstCaseIncludingBuyOrders
|
||||
: liquidationEstimateWorstCaseIncludingSellOrders;
|
||||
|
||||
liquidationPriceEstimate = formatValue(
|
||||
liquidationEstimateWorstCase.toString(),
|
||||
market.decimalPlaces,
|
||||
undefined,
|
||||
market.decimalPlaces
|
||||
);
|
||||
liquidationPriceEstimateRange = formatRange(
|
||||
(liquidationEstimateBestCase < liquidationEstimateWorstCase
|
||||
? liquidationEstimateBestCase
|
||||
: liquidationEstimateWorstCase
|
||||
).toString(),
|
||||
(liquidationEstimateBestCase > liquidationEstimateWorstCase
|
||||
? liquidationEstimateBestCase
|
||||
: liquidationEstimateWorstCase
|
||||
).toString(),
|
||||
market.decimalPlaces,
|
||||
undefined,
|
||||
market.decimalPlaces
|
||||
);
|
||||
}
|
||||
|
||||
const onAccountBreakdownDialogClose = useCallback(
|
||||
() => setBreakdownDialog(false),
|
||||
[]
|
||||
);
|
||||
|
||||
const quoteName = getQuoteName(market);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col w-full gap-2 pt-2">
|
||||
<Accordion>
|
||||
<AccordionPanel
|
||||
itemId="margin"
|
||||
trigger={
|
||||
<AccordionPrimitive.Trigger
|
||||
data-testid="accordion-toggle"
|
||||
className={classNames(
|
||||
'w-full',
|
||||
'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
|
||||
),
|
||||
marginMaintenance: formatValue(
|
||||
currentMargins?.maintenanceLevel,
|
||||
assetDecimals,
|
||||
quantum
|
||||
),
|
||||
assetSymbol,
|
||||
}
|
||||
)}
|
||||
/>
|
||||
{deductionFromCollateral}
|
||||
<KeyValue
|
||||
label={t('Current margin allocation')}
|
||||
indent
|
||||
onClick={
|
||||
generalAccountBalance
|
||||
? () => setBreakdownDialog(true)
|
||||
: undefined
|
||||
}
|
||||
value={formatValue(marginAccountBalance, assetDecimals)}
|
||||
symbol={assetSymbol}
|
||||
labelDescription={t(
|
||||
'MARGIN_ACCOUNT_TOOLTIP_TEXT',
|
||||
MARGIN_ACCOUNT_TOOLTIP_TEXT
|
||||
)}
|
||||
formattedValue={formatValue(
|
||||
marginAccountBalance,
|
||||
assetDecimals,
|
||||
quantum
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</AccordionPanel>
|
||||
</Accordion>
|
||||
{projectedMargin}
|
||||
<KeyValue
|
||||
label={t('Liquidation')}
|
||||
value={liquidationPriceEstimateRange}
|
||||
formattedValue={liquidationPriceEstimate}
|
||||
symbol={quoteName}
|
||||
labelDescription={
|
||||
<>
|
||||
<span>
|
||||
{t(
|
||||
'LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT',
|
||||
LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT
|
||||
)}
|
||||
</span>{' '}
|
||||
<span>
|
||||
<Trans
|
||||
defaults="For full details please see <0>liquidation price estimate documentation</0>."
|
||||
components={[
|
||||
<ExternalLink
|
||||
href={
|
||||
'https://github.com/vegaprotocol/specs/blob/master/non-protocol-specs/0012-NP-LIPE-liquidation-price-estimate.md'
|
||||
}
|
||||
>
|
||||
liquidation price estimate documentation
|
||||
</ExternalLink>,
|
||||
]}
|
||||
ns={ns}
|
||||
/>
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
{partyId && (
|
||||
<AccountBreakdownDialog
|
||||
assetId={breakdownDialog ? asset.id : undefined}
|
||||
partyId={partyId}
|
||||
onMarketClick={onMarketClick}
|
||||
onClose={onAccountBreakdownDialogClose}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -26,12 +26,25 @@ import {
|
||||
import classNames from 'classnames';
|
||||
import { useT, ns } from '../../use-t';
|
||||
import { Trans } from 'react-i18next';
|
||||
import type { DealTicketMarginDetailsProps } from './deal-ticket-fee-details';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
import { emptyValue } from './deal-ticket-fee-details';
|
||||
import type { EstimatePositionQuery } from '@vegaprotocol/positions';
|
||||
|
||||
export interface DealTicketMarginDetailsProps {
|
||||
generalAccountBalance?: string;
|
||||
marginAccountBalance?: string;
|
||||
orderMarginAccountBalance?: string;
|
||||
market: Market;
|
||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||
assetSymbol: string;
|
||||
positionEstimate: EstimatePositionQuery['estimatePosition'];
|
||||
side: Schema.Side;
|
||||
}
|
||||
|
||||
export const DealTicketMarginDetails = ({
|
||||
marginAccountBalance,
|
||||
generalAccountBalance,
|
||||
orderMarginAccountBalance,
|
||||
assetSymbol,
|
||||
market,
|
||||
onMarketClick,
|
||||
@@ -48,31 +61,44 @@ export const DealTicketMarginDetails = ({
|
||||
});
|
||||
const liquidationEstimate = positionEstimate?.liquidation;
|
||||
const marginEstimate = positionEstimate?.margin;
|
||||
const totalMarginAccountBalance =
|
||||
BigInt(marginAccountBalance || '0') +
|
||||
BigInt(orderMarginAccountBalance || '0');
|
||||
const totalBalance =
|
||||
BigInt(generalAccountBalance || '0') + BigInt(marginAccountBalance || '0');
|
||||
BigInt(generalAccountBalance || '0') + totalMarginAccountBalance;
|
||||
const asset = getAsset(market);
|
||||
const { decimals: assetDecimals, quantum } = asset;
|
||||
let marginRequiredBestCase: string | undefined = undefined;
|
||||
let marginRequiredWorstCase: string | undefined = undefined;
|
||||
const marginEstimateBestCase =
|
||||
BigInt(marginEstimate?.bestCase.initialLevel ?? 0) +
|
||||
BigInt(marginEstimate?.bestCase.orderMarginLevel ?? 0);
|
||||
const marginEstimateWorstCase =
|
||||
BigInt(marginEstimate?.worstCase.initialLevel ?? 0) +
|
||||
BigInt(marginEstimate?.worstCase.orderMarginLevel ?? 0);
|
||||
if (marginEstimate) {
|
||||
if (currentMargins) {
|
||||
const currentMargin =
|
||||
BigInt(currentMargins.initialLevel) +
|
||||
BigInt(currentMargins.orderMarginLevel);
|
||||
|
||||
marginRequiredBestCase = (
|
||||
BigInt(marginEstimate.bestCase.initialLevel) -
|
||||
BigInt(currentMargins.initialLevel)
|
||||
marginEstimateBestCase - currentMargin
|
||||
).toString();
|
||||
if (marginRequiredBestCase.startsWith('-')) {
|
||||
marginRequiredBestCase = '0';
|
||||
}
|
||||
|
||||
marginRequiredWorstCase = (
|
||||
BigInt(marginEstimate.worstCase.initialLevel) -
|
||||
BigInt(currentMargins.initialLevel)
|
||||
marginEstimateWorstCase - currentMargin
|
||||
).toString();
|
||||
|
||||
if (marginRequiredWorstCase.startsWith('-')) {
|
||||
marginRequiredWorstCase = '0';
|
||||
}
|
||||
} else {
|
||||
marginRequiredBestCase = marginEstimate.bestCase.initialLevel;
|
||||
marginRequiredWorstCase = marginEstimate.worstCase.initialLevel;
|
||||
marginRequiredBestCase = marginEstimateBestCase.toString();
|
||||
marginRequiredWorstCase = marginEstimateWorstCase.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,14 +110,12 @@ export const DealTicketMarginDetails = ({
|
||||
|
||||
let deductionFromCollateral = null;
|
||||
let projectedMargin = null;
|
||||
if (marginAccountBalance) {
|
||||
if (totalMarginAccountBalance) {
|
||||
const deductionFromCollateralBestCase =
|
||||
BigInt(marginEstimate?.bestCase.initialLevel ?? 0) -
|
||||
BigInt(marginAccountBalance);
|
||||
marginEstimateBestCase - totalMarginAccountBalance;
|
||||
|
||||
const deductionFromCollateralWorstCase =
|
||||
BigInt(marginEstimate?.worstCase.initialLevel ?? 0) -
|
||||
BigInt(marginAccountBalance);
|
||||
marginEstimateWorstCase - totalMarginAccountBalance;
|
||||
|
||||
deductionFromCollateral = (
|
||||
<KeyValue
|
||||
@@ -125,12 +149,12 @@ export const DealTicketMarginDetails = ({
|
||||
<KeyValue
|
||||
label={t('Projected margin')}
|
||||
value={formatRange(
|
||||
marginEstimate?.bestCase.initialLevel,
|
||||
marginEstimate?.worstCase.initialLevel,
|
||||
marginEstimateBestCase.toString(),
|
||||
marginEstimateWorstCase.toString(),
|
||||
assetDecimals
|
||||
)}
|
||||
formattedValue={formatValue(
|
||||
marginEstimate?.worstCase.initialLevel,
|
||||
marginEstimateWorstCase.toString(),
|
||||
assetDecimals,
|
||||
quantum
|
||||
)}
|
||||
@@ -276,6 +300,11 @@ export const DealTicketMarginDetails = ({
|
||||
assetDecimals,
|
||||
quantum
|
||||
),
|
||||
orderMarginAccountBalance: formatValue(
|
||||
orderMarginAccountBalance,
|
||||
assetDecimals,
|
||||
quantum
|
||||
),
|
||||
marginMaintenance: formatValue(
|
||||
currentMargins?.maintenanceLevel,
|
||||
assetDecimals,
|
||||
@@ -294,14 +323,17 @@ export const DealTicketMarginDetails = ({
|
||||
? () => setBreakdownDialog(true)
|
||||
: undefined
|
||||
}
|
||||
value={formatValue(marginAccountBalance, assetDecimals)}
|
||||
value={formatValue(
|
||||
totalMarginAccountBalance.toString(),
|
||||
assetDecimals
|
||||
)}
|
||||
symbol={assetSymbol}
|
||||
labelDescription={t(
|
||||
'MARGIN_ACCOUNT_TOOLTIP_TEXT',
|
||||
MARGIN_ACCOUNT_TOOLTIP_TEXT
|
||||
)}
|
||||
formattedValue={formatValue(
|
||||
marginAccountBalance,
|
||||
totalMarginAccountBalance.toString(),
|
||||
assetDecimals,
|
||||
quantum
|
||||
)}
|
||||
|
||||
@@ -178,7 +178,9 @@ export const DealTicket = ({
|
||||
} = useAccountBalance(asset.id);
|
||||
|
||||
const balance = (
|
||||
BigInt(marginAccountBalance) + BigInt(generalAccountBalance)
|
||||
BigInt(marginAccountBalance) +
|
||||
BigInt(generalAccountBalance) +
|
||||
BigInt(orderMarginAccountBalance)
|
||||
).toString();
|
||||
|
||||
const { marketState, marketTradingMode } = marketData;
|
||||
@@ -279,9 +281,9 @@ export const DealTicket = ({
|
||||
openVolume,
|
||||
averageEntryPrice,
|
||||
orders,
|
||||
marginAccountBalance,
|
||||
generalAccountBalance,
|
||||
orderMarginAccountBalance,
|
||||
marginAccountBalance: marginAccountBalance || '0',
|
||||
generalAccountBalance: generalAccountBalance || '0',
|
||||
orderMarginAccountBalance: orderMarginAccountBalance || '0',
|
||||
marginFactor: margin?.marginFactor || '1',
|
||||
marginMode:
|
||||
margin?.marginMode || Schema.MarginMode.MARGIN_MODE_CROSS_MARGIN,
|
||||
@@ -337,7 +339,9 @@ export const DealTicket = ({
|
||||
}
|
||||
|
||||
const hasNoBalance =
|
||||
!BigInt(generalAccountBalance) && !BigInt(marginAccountBalance);
|
||||
!BigInt(generalAccountBalance) &&
|
||||
!BigInt(marginAccountBalance) &&
|
||||
!BigInt(orderMarginAccountBalance);
|
||||
if (
|
||||
hasNoBalance &&
|
||||
!(loadingMarginAccountBalance || loadingGeneralAccountBalance)
|
||||
@@ -367,6 +371,7 @@ export const DealTicket = ({
|
||||
marketTradingMode,
|
||||
generalAccountBalance,
|
||||
marginAccountBalance,
|
||||
orderMarginAccountBalance,
|
||||
loadingMarginAccountBalance,
|
||||
loadingGeneralAccountBalance,
|
||||
pubKey,
|
||||
@@ -725,10 +730,16 @@ export const DealTicket = ({
|
||||
asset={asset}
|
||||
marketTradingMode={marketData.marketTradingMode}
|
||||
balance={balance}
|
||||
margin={
|
||||
positionEstimate?.estimatePosition?.margin.bestCase.initialLevel ||
|
||||
'0'
|
||||
}
|
||||
margin={(
|
||||
BigInt(
|
||||
positionEstimate?.estimatePosition?.margin.bestCase.initialLevel ||
|
||||
'0'
|
||||
) +
|
||||
BigInt(
|
||||
positionEstimate?.estimatePosition?.margin.bestCase
|
||||
.orderMarginLevel || '0'
|
||||
)
|
||||
).toString()}
|
||||
isReadOnly={isReadOnly}
|
||||
pubKey={pubKey}
|
||||
onDeposit={onDeposit}
|
||||
@@ -761,6 +772,7 @@ export const DealTicket = ({
|
||||
onMarketClick={onMarketClick}
|
||||
assetSymbol={asset.symbol}
|
||||
marginAccountBalance={marginAccountBalance}
|
||||
orderMarginAccountBalance={orderMarginAccountBalance}
|
||||
generalAccountBalance={generalAccountBalance}
|
||||
positionEstimate={positionEstimate?.estimatePosition}
|
||||
market={market}
|
||||
|
||||
@@ -5,6 +5,8 @@ import {
|
||||
TradingInput as Input,
|
||||
FormGroup,
|
||||
LeverageSlider,
|
||||
Notification,
|
||||
Intent,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { MarginMode, useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
@@ -43,9 +45,15 @@ export const MarginChange = ({
|
||||
const t = useT();
|
||||
const { data: market } = useMarket(marketId);
|
||||
const asset = market && getAsset(market);
|
||||
const { marginAccountBalance, orderMarginAccountBalance } =
|
||||
useMarginAccountBalance(marketId);
|
||||
const { accountBalance: generalAccountBalance } = useAccountBalance(marketId);
|
||||
const {
|
||||
marginAccountBalance,
|
||||
orderMarginAccountBalance,
|
||||
loading: marginAccountBalanceLoading,
|
||||
} = useMarginAccountBalance(marketId);
|
||||
const {
|
||||
accountBalance: generalAccountBalance,
|
||||
loading: generalAccountBalanceLoading,
|
||||
} = useAccountBalance(asset?.id);
|
||||
const { openVolume, averageEntryPrice } = useOpenVolume(
|
||||
partyId,
|
||||
marketId
|
||||
@@ -65,35 +73,35 @@ export const MarginChange = ({
|
||||
side: order.side,
|
||||
}))
|
||||
: [];
|
||||
const skip = !orders?.length || openVolume === '0';
|
||||
const skip =
|
||||
(!orders?.length && openVolume === '0') ||
|
||||
marginAccountBalanceLoading ||
|
||||
generalAccountBalanceLoading;
|
||||
const estimateMargin = usePositionEstimate(
|
||||
{
|
||||
generalAccountBalance,
|
||||
marginAccountBalance,
|
||||
generalAccountBalance: generalAccountBalance || '0',
|
||||
marginAccountBalance: marginAccountBalance || '0',
|
||||
marginFactor,
|
||||
marginMode,
|
||||
averageEntryPrice,
|
||||
openVolume,
|
||||
marketId,
|
||||
orderMarginAccountBalance,
|
||||
orderMarginAccountBalance: orderMarginAccountBalance || '0',
|
||||
includeCollateralIncreaseInAvailableCollateral: true,
|
||||
orders,
|
||||
},
|
||||
skip
|
||||
);
|
||||
const currentMargin =
|
||||
BigInt(marginAccountBalance) + BigInt(orderMarginAccountBalance);
|
||||
if (
|
||||
!asset ||
|
||||
!estimateMargin?.estimatePosition?.margin.worstCase.initialLevel ||
|
||||
currentMargin.toString() === '0'
|
||||
!estimateMargin?.estimatePosition?.collateralIncreaseEstimate.worstCase ||
|
||||
estimateMargin.estimatePosition.collateralIncreaseEstimate.worstCase === '0'
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
const initialLevel = BigInt(
|
||||
estimateMargin.estimatePosition?.margin.worstCase.initialLevel
|
||||
const diff = BigInt(
|
||||
estimateMargin.estimatePosition.collateralIncreaseEstimate.worstCase
|
||||
);
|
||||
const diff = initialLevel - currentMargin;
|
||||
if (!diff) {
|
||||
return null;
|
||||
}
|
||||
@@ -145,15 +153,22 @@ export const MarginChange = ({
|
||||
);
|
||||
} else {
|
||||
marginChangeWarning = t(
|
||||
'Changing to this margin mode and leverage will result in {{amount}} {{symbol}} will be moved from yur general account to fund the position.',
|
||||
'Changing to this margin mode and leverage will result in {{amount}} {{symbol}} will be moved from your general account to fund the position.',
|
||||
interpolation
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<p>{positionWarning}</p>
|
||||
<p>{marginChangeWarning}</p>
|
||||
<div className="mb-2">
|
||||
<Notification
|
||||
intent={Intent.Warning}
|
||||
message={
|
||||
<>
|
||||
<p>{positionWarning}</p>
|
||||
<p>{marginChangeWarning}</p>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -203,7 +218,7 @@ const CrossMarginModeDialog = ({
|
||||
<MarginChange
|
||||
marketId={marketId}
|
||||
partyId={partyId}
|
||||
marginMode={MarginMode.MARGIN_MODE_CROSS_MARGIN}
|
||||
marginMode={Types.MarginMode.MARGIN_MODE_CROSS_MARGIN}
|
||||
marginFactor="1"
|
||||
/>
|
||||
<Button
|
||||
@@ -307,7 +322,7 @@ const IsolatedMarginModeDialog = ({
|
||||
<MarginChange
|
||||
marketId={marketId}
|
||||
partyId={partyId}
|
||||
marginMode={MarginMode.MARGIN_MODE_ISOLATED_MARGIN}
|
||||
marginMode={Types.MarginMode.MARGIN_MODE_ISOLATED_MARGIN}
|
||||
marginFactor={`${1 / leverage}`}
|
||||
/>
|
||||
<Button className="w-full" type="submit">
|
||||
|
||||
@@ -8,7 +8,7 @@ export const DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT =
|
||||
'To cover the required margin, this amount will be drawn from your general ({{assetSymbol}}) account.';
|
||||
|
||||
export const TOTAL_MARGIN_AVAILABLE =
|
||||
'Total margin available = general {{assetSymbol}} balance ({{generalAccountBalance}} {{assetSymbol}}) + margin balance ({{marginAccountBalance}} {{assetSymbol}}) - maintenance level ({{marginMaintenance}} {{assetSymbol}}).';
|
||||
'Total margin available = general {{assetSymbol}} balance ({{generalAccountBalance}} {{assetSymbol}}) + margin balance ({{marginAccountBalance}} {{assetSymbol}}) + order margin balance ({{orderMarginAccountBalance}} {{assetSymbol}}) - maintenance level ({{marginMaintenance}} {{assetSymbol}}).';
|
||||
|
||||
export const CONTRACTS_MARGIN_TOOLTIP_TEXT =
|
||||
'The number of contracts determines how many units of the futures contract to buy or sell. For example, this is similar to buying one share of a listed company. The value of 1 contract is equivalent to the price of the contract. For example, if the current price is $50, then one contract is worth $50.';
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"Any orders placed now will not trade until the auction ends": "Any orders placed now will not trade until the auction ends",
|
||||
"below": "below",
|
||||
"Cancel": "Cancel",
|
||||
"Changing to this margin mode and leverage will result in {{amount}} {{symbol}} will be moved from yur general account to fund the position.": "Changing to this margin mode and leverage will result in {{amount}} {{symbol}} will be moved from yur general account to fund the position.",
|
||||
"Changing to this margin mode and leverage will result in {{amount}} {{symbol}} will be moved from your general account to fund the position.": "Changing to this margin mode and leverage will result in {{amount}} {{symbol}} will be moved from your general account to fund the position.",
|
||||
"Changing to this margin mode and leverage will result in {{amount}} {{symbol}} will be released to your general account.": "Changing to this margin mode and leverage will result in {{amount}} {{symbol}} will be released to your general account.",
|
||||
"Changing to this margin mode will result in {{amount}} {{symbol}} will be moved from your general account to fund the position.": "Changing to this margin mode will result in {{amount}} {{symbol}} will be moved from your general account to fund the position.",
|
||||
"Changing to this margin mode will result in {{amount}} {{symbol}} will be released to your general account.": "Changing to this margin mode will result in {{amount}} {{symbol}} will be released to your general account.",
|
||||
@@ -135,7 +135,7 @@
|
||||
"Total": "Total",
|
||||
"Total fees": "Total fees",
|
||||
"Total margin available": "Total margin available",
|
||||
"TOTAL_MARGIN_AVAILABLE": "Total margin available = general {{assetSymbol}} balance ({{generalAccountBalance}} {{assetSymbol}}) + margin balance ({{marginAccountBalance}} {{assetSymbol}}) - maintenance level ({{marginMaintenance}} {{assetSymbol}}).",
|
||||
"TOTAL_MARGIN_AVAILABLE": "Total margin available = general {{assetSymbol}} balance ({{generalAccountBalance}} {{assetSymbol}}) + margin balance ({{marginAccountBalance}} {{assetSymbol}}) + order margin balance ({{orderMarginAccountBalance}} {{assetSymbol}}) - maintenance level ({{marginMaintenance}} {{assetSymbol}}).",
|
||||
"No trading": "No trading",
|
||||
"Trailing percent offset cannot be higher than 99.9": "Trailing percent offset cannot be higher than 99.9",
|
||||
"Trailing percent offset cannot be lower than {{trailingPercentOffsetStep}}": "Trailing percent offset cannot be lower than {{trailingPercentOffsetStep}}",
|
||||
|
||||
@@ -73,12 +73,18 @@ query EstimatePosition(
|
||||
searchLevel
|
||||
initialLevel
|
||||
collateralReleaseLevel
|
||||
marginMode
|
||||
marginFactor
|
||||
orderMarginLevel
|
||||
}
|
||||
bestCase {
|
||||
maintenanceLevel
|
||||
searchLevel
|
||||
initialLevel
|
||||
collateralReleaseLevel
|
||||
marginMode
|
||||
marginFactor
|
||||
orderMarginLevel
|
||||
}
|
||||
}
|
||||
collateralIncreaseEstimate {
|
||||
|
||||
+7
-1
@@ -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 }, bestCase: { __typename?: 'MarginLevels', maintenanceLevel: string, searchLevel: string, initialLevel: string, collateralReleaseLevel: 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', 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 const PositionFieldsFragmentDoc = gql`
|
||||
fragment PositionFields on Position {
|
||||
@@ -150,12 +150,18 @@ export const EstimatePositionDocument = gql`
|
||||
searchLevel
|
||||
initialLevel
|
||||
collateralReleaseLevel
|
||||
marginMode
|
||||
marginFactor
|
||||
orderMarginLevel
|
||||
}
|
||||
bestCase {
|
||||
maintenanceLevel
|
||||
searchLevel
|
||||
initialLevel
|
||||
collateralReleaseLevel
|
||||
marginMode
|
||||
marginFactor
|
||||
orderMarginLevel
|
||||
}
|
||||
}
|
||||
collateralIncreaseEstimate {
|
||||
|
||||
Reference in New Issue
Block a user