Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8af8adc3e7 | ||
|
|
adbffe133f | ||
|
|
4eb6e09bd4 | ||
|
|
a02100b079 | ||
|
|
718dd5a4e4 | ||
|
|
09bbc75729 | ||
|
|
d27758b7f4 | ||
|
|
89530d3a8c | ||
|
|
d76dd79df2 | ||
|
|
8f070432ab | ||
|
|
bf37712ac5 |
@@ -184,9 +184,8 @@ export const MarketDetails = ({
|
||||
content: (
|
||||
<>
|
||||
<p className="text-xs mb-4">
|
||||
{`For liquidity orders count towards a commitment they have to be
|
||||
within either the liquidity or price monitoring bounds (whichever is
|
||||
tighter).`}
|
||||
{`For liquidity orders to count towards a commitment, they must be
|
||||
within the liquidity monitoring bounds.`}
|
||||
</p>
|
||||
<p className="text-xs mb-4">
|
||||
{`The liquidity price range is a ${liquidityPriceRange} difference from the mid
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
.pre-loader {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.pre-loader .loader-item {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #000;
|
||||
}
|
||||
.pre-loader .pre-loader-center {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.pre-loader .pre-loader-wrapper {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.loader-item:nth-child(0) {
|
||||
animation-delay: 0ms;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:first-child {
|
||||
animation-delay: -0.2s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(2) {
|
||||
animation-delay: 0.4s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(3) {
|
||||
animation-delay: -0.15s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(4) {
|
||||
animation-delay: 0.6s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(5) {
|
||||
animation-delay: -1s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(6) {
|
||||
animation-delay: 0.3s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(7) {
|
||||
animation-delay: -0.35s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(8) {
|
||||
animation-delay: 2s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(9) {
|
||||
animation-delay: -0.45s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(10) {
|
||||
animation-delay: 2s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(11) {
|
||||
animation-delay: -0.55s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(12) {
|
||||
animation-delay: 1.2s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(13) {
|
||||
animation-delay: -2.6s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(14) {
|
||||
animation-delay: 2.8s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(15) {
|
||||
animation-delay: -3s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(16) {
|
||||
animation-delay: 1.6s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item {
|
||||
animation: flickering 0.4s linear infinite alternate;
|
||||
}
|
||||
@keyframes flickering {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
25% {
|
||||
opacity: 1;
|
||||
}
|
||||
26% {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ export const Preloader = () => {
|
||||
`}
|
||||
</style>
|
||||
<div className="pre-loader">
|
||||
<Loader forceTheme="light" />
|
||||
<Loader forceTheme="light" preloader />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -4,10 +4,17 @@
|
||||
min-height: 100vh;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.loader-item {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: black;
|
||||
|
||||
@for $i from 0 through 16 {
|
||||
.loader-item:nth-child(#{$i}) {
|
||||
@if $i % 2 == 0 {
|
||||
animation-delay: #{$i * 50 * random(5)}ms;
|
||||
animation-direction: reverse;
|
||||
} @else {
|
||||
animation-delay: #{$i * -50 * random(5)}ms;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
}
|
||||
}
|
||||
.pre-loader-center {
|
||||
align-items: center;
|
||||
@@ -20,21 +27,13 @@
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
@for $i from 0 through 16 {
|
||||
.loader-item:nth-child(#{$i}) {
|
||||
@if $i % 2 == 0 {
|
||||
animation-delay: #{$i * 50 * random(5)}ms;
|
||||
animation-direction: reverse;
|
||||
} @else {
|
||||
animation-delay: #{$i * -50 * random(5)}ms;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: black;
|
||||
animation: flickering 0.4s steps(2, jump-none) alternate infinite;
|
||||
}
|
||||
}
|
||||
.loader-item {
|
||||
animation: flickering 0.4s linear alternate infinite;
|
||||
}
|
||||
@keyframes flickering {
|
||||
0% {
|
||||
opacity: 1;
|
||||
|
||||
@@ -5,10 +5,73 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.pre-loader .loader-item {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #000;
|
||||
.pre-loader .loader-item:nth-child(0) {
|
||||
animation-delay: 0ms;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:first-child {
|
||||
animation-delay: -0.2s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(2) {
|
||||
animation-delay: 0.1s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(3) {
|
||||
animation-delay: -0.15s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(4) {
|
||||
animation-delay: 1s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(5) {
|
||||
animation-delay: -0.25s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(6) {
|
||||
animation-delay: 0.3s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(7) {
|
||||
animation-delay: -1.05s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(8) {
|
||||
animation-delay: 0.8s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(9) {
|
||||
animation-delay: -0.9s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(10) {
|
||||
animation-delay: 0.5s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(11) {
|
||||
animation-delay: -2.75s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(12) {
|
||||
animation-delay: 2.4s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(13) {
|
||||
animation-delay: -0.65s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(14) {
|
||||
animation-delay: 0.7s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(15) {
|
||||
animation-delay: -3s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(16) {
|
||||
animation-delay: 2.4s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .pre-loader-center {
|
||||
align-items: center;
|
||||
@@ -21,76 +84,11 @@
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.loader-item:nth-child(0) {
|
||||
animation-delay: 0ms;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:first-child {
|
||||
animation-delay: -0.2s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(2) {
|
||||
animation-delay: 0.4s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(3) {
|
||||
animation-delay: -0.15s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(4) {
|
||||
animation-delay: 0.6s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(5) {
|
||||
animation-delay: -1s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(6) {
|
||||
animation-delay: 0.3s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(7) {
|
||||
animation-delay: -0.35s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(8) {
|
||||
animation-delay: 2s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(9) {
|
||||
animation-delay: -0.45s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(10) {
|
||||
animation-delay: 2s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(11) {
|
||||
animation-delay: -0.55s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(12) {
|
||||
animation-delay: 1.2s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(13) {
|
||||
animation-delay: -2.6s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(14) {
|
||||
animation-delay: 2.8s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item:nth-child(15) {
|
||||
animation-delay: -3s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.loader-item:nth-child(16) {
|
||||
animation-delay: 1.6s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.loader-item {
|
||||
animation: flickering 0.4s linear infinite alternate;
|
||||
.pre-loader .loader-item {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #000;
|
||||
animation: flickering 0.4s steps(2, jump-none) infinite alternate;
|
||||
}
|
||||
@keyframes flickering {
|
||||
0% {
|
||||
|
||||
@@ -98,7 +98,7 @@ export const AssetDetailsDialog = ({
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
<p className="text-sm mb-4">
|
||||
<p className="text-sm my-4">
|
||||
{t(
|
||||
'There is 1 unit of the settlement asset (%s) to every 1 quote unit.',
|
||||
[assetSymbol]
|
||||
|
||||
@@ -12,7 +12,7 @@ export const DealTicketButton = ({ disabled, variant }: Props) => {
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
const isDisabled = !pubKey || isReadOnly || disabled;
|
||||
return (
|
||||
<div className="mb-4">
|
||||
<div className="mb-2">
|
||||
<Button
|
||||
variant={variant}
|
||||
fill
|
||||
|
||||
@@ -31,7 +31,7 @@ export const DealTicketFeeDetails = ({
|
||||
<div>
|
||||
{details.map(({ label, value, labelDescription, symbol }) => (
|
||||
<div
|
||||
key={label}
|
||||
key={typeof label === 'string' ? label : 'value-dropdown'}
|
||||
className="text-xs mt-2 flex justify-between items-center gap-4 flex-wrap"
|
||||
>
|
||||
<div>
|
||||
|
||||
@@ -38,7 +38,7 @@ export const DealTicketLimitAmount = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mb-6">
|
||||
<div className="mb-2">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex-1">
|
||||
<FormGroup
|
||||
|
||||
@@ -29,9 +29,9 @@ export const DealTicketMarketAmount = ({
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<div className="mb-6">
|
||||
<div className="mb-2">
|
||||
<div className="flex items-end gap-4 mb-2">
|
||||
<div className="flex-1 text-sm">Size</div>
|
||||
<div className="flex-1 text-sm">{t('Size')}</div>
|
||||
<div />
|
||||
<div className="flex-2 text-sm text-right">
|
||||
{isMarketInAuction(marketData.marketTradingMode) && (
|
||||
|
||||
@@ -307,7 +307,7 @@ const SummaryMessage = memo(
|
||||
);
|
||||
if (isReadOnly) {
|
||||
return (
|
||||
<div className="mb-4">
|
||||
<div className="mb-2">
|
||||
<InputError testId="dealticket-error-message-summary">
|
||||
{
|
||||
'You need to connect your own wallet to start trading on this market'
|
||||
@@ -318,7 +318,7 @@ const SummaryMessage = memo(
|
||||
}
|
||||
if (!pubKey) {
|
||||
return (
|
||||
<div className="mb-4">
|
||||
<div className="mb-2">
|
||||
<Notification
|
||||
testId={'deal-ticket-connect-wallet'}
|
||||
intent={Intent.Warning}
|
||||
@@ -343,7 +343,7 @@ const SummaryMessage = memo(
|
||||
}
|
||||
if (errorMessage === SummaryValidationType.NoCollateral) {
|
||||
return (
|
||||
<div className="mb-4">
|
||||
<div className="mb-2">
|
||||
<ZeroBalanceError
|
||||
asset={market.tradableInstrument.instrument.product.settlementAsset}
|
||||
onClickCollateral={onClickCollateral}
|
||||
@@ -356,7 +356,7 @@ const SummaryMessage = memo(
|
||||
// submission render that first
|
||||
if (errorMessage) {
|
||||
return (
|
||||
<div className="mb-4">
|
||||
<div className="mb-2">
|
||||
<InputError testId="dealticket-error-message-summary">
|
||||
{errorMessage}
|
||||
</InputError>
|
||||
@@ -368,7 +368,7 @@ const SummaryMessage = memo(
|
||||
// balance render the margin warning, but still allow submission
|
||||
if (balanceError) {
|
||||
return (
|
||||
<div className="mb-4">
|
||||
<div className="mb-2">
|
||||
<MarginWarning balance={balance} margin={margin} asset={asset} />;
|
||||
</div>
|
||||
);
|
||||
@@ -383,7 +383,7 @@ const SummaryMessage = memo(
|
||||
].includes(marketData.marketTradingMode)
|
||||
) {
|
||||
return (
|
||||
<div className="mb-4">
|
||||
<div className="mb-2">
|
||||
<Notification
|
||||
intent={Intent.Warning}
|
||||
testId={'dealticket-warning-auction'}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
export interface MarginLevels {
|
||||
initialLevel?: string;
|
||||
searchLevel?: string;
|
||||
maintenanceLevel?: string;
|
||||
collateralReleaseLevel?: string;
|
||||
}
|
||||
|
||||
export const MarginBreakdown = ({
|
||||
marginLevels,
|
||||
assetDecimalPlaces,
|
||||
assetSymbol,
|
||||
}: {
|
||||
marginLevels?: MarginLevels;
|
||||
assetDecimalPlaces: number;
|
||||
assetSymbol: string;
|
||||
}) => {
|
||||
if (!marginLevels) return null;
|
||||
const formatNumberWithAssetDp = (value: string | number | null | undefined) =>
|
||||
value && !isNaN(Number(value))
|
||||
? `${addDecimalsFormatNumber(value, assetDecimalPlaces)} ${assetSymbol}`
|
||||
: '-';
|
||||
|
||||
return (
|
||||
<dl className="grid grid-cols-8">
|
||||
<Tooltip
|
||||
description={t(
|
||||
'This is the minimum margin required for a party to place a new order on the network'
|
||||
)}
|
||||
>
|
||||
{<dt className="col-span-3">{t('Initial level')}</dt>}
|
||||
</Tooltip>
|
||||
<dd className="text-right col-span-5">
|
||||
{formatNumberWithAssetDp(marginLevels.initialLevel)}
|
||||
</dd>
|
||||
<Tooltip
|
||||
description={t(
|
||||
'If the margin is between maintenance and search, the network will initiate a collateral search'
|
||||
)}
|
||||
>
|
||||
{<dt className="col-span-3">{t('Search level')}</dt>}
|
||||
</Tooltip>
|
||||
<dd className="text-right col-span-5">
|
||||
{formatNumberWithAssetDp(marginLevels.searchLevel)}
|
||||
</dd>
|
||||
<Tooltip
|
||||
description={t(
|
||||
'Minimal margin for the position to be maintained in the network'
|
||||
)}
|
||||
>
|
||||
{<dt className="col-span-3">{t('Maintenance level')}</dt>}
|
||||
</Tooltip>
|
||||
<dd className="text-right col-span-5">
|
||||
{formatNumberWithAssetDp(marginLevels.maintenanceLevel)}
|
||||
</dd>
|
||||
<Tooltip
|
||||
description={t(
|
||||
'If the margin of the party is greater than this level, then collateral will be released from the margin account into the general account of the party for the given asset.'
|
||||
)}
|
||||
>
|
||||
{<dt className="col-span-3">{t('Collateral release level')}</dt>}
|
||||
</Tooltip>
|
||||
<dd className="text-right col-span-5">
|
||||
{formatNumberWithAssetDp(marginLevels.collateralReleaseLevel)}
|
||||
</dd>
|
||||
</dl>
|
||||
);
|
||||
};
|
||||
@@ -24,7 +24,35 @@ query EstimateOrder(
|
||||
liquidityFee
|
||||
}
|
||||
marginLevels {
|
||||
market {
|
||||
id
|
||||
state
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
code
|
||||
name
|
||||
}
|
||||
marginCalculator {
|
||||
scalingFactors {
|
||||
searchLevel
|
||||
initialMargin
|
||||
collateralRelease
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
asset {
|
||||
id
|
||||
name
|
||||
}
|
||||
party {
|
||||
id
|
||||
}
|
||||
initialLevel
|
||||
searchLevel
|
||||
maintenanceLevel
|
||||
collateralReleaseLevel
|
||||
timestamp
|
||||
}
|
||||
totalFeeAmount
|
||||
}
|
||||
|
||||
+29
-1
@@ -15,7 +15,7 @@ export type EstimateOrderQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type EstimateOrderQuery = { __typename?: 'Query', estimateOrder: { __typename?: 'OrderEstimate', totalFeeAmount: string, fee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, marginLevels: { __typename?: 'MarginLevels', initialLevel: string } } };
|
||||
export type EstimateOrderQuery = { __typename?: 'Query', estimateOrder: { __typename?: 'OrderEstimate', totalFeeAmount: string, fee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, marginLevels: { __typename?: 'MarginLevels', initialLevel: string, searchLevel: string, maintenanceLevel: string, collateralReleaseLevel: string, timestamp: any, market: { __typename?: 'Market', id: string, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', code: string, name: string }, marginCalculator?: { __typename?: 'MarginCalculator', scalingFactors: { __typename?: 'ScalingFactors', searchLevel: number, initialMargin: number, collateralRelease: number } } | null } }, asset: { __typename?: 'Asset', id: string, name: string }, party: { __typename?: 'Party', id: string } } } };
|
||||
|
||||
|
||||
export const EstimateOrderDocument = gql`
|
||||
@@ -36,7 +36,35 @@ export const EstimateOrderDocument = gql`
|
||||
liquidityFee
|
||||
}
|
||||
marginLevels {
|
||||
market {
|
||||
id
|
||||
state
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
code
|
||||
name
|
||||
}
|
||||
marginCalculator {
|
||||
scalingFactors {
|
||||
searchLevel
|
||||
initialMargin
|
||||
collateralRelease
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
asset {
|
||||
id
|
||||
name
|
||||
}
|
||||
party {
|
||||
id
|
||||
}
|
||||
initialLevel
|
||||
searchLevel
|
||||
maintenanceLevel
|
||||
collateralReleaseLevel
|
||||
timestamp
|
||||
}
|
||||
totalFeeAmount
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import { useOrderCloseOut } from './use-order-closeout';
|
||||
import { useOrderMargin } from './use-order-margin';
|
||||
import type { OrderMargin } from './use-order-margin';
|
||||
import { getDerivedPrice } from '../utils/get-price';
|
||||
import { Icon } from '@vegaprotocol/ui-toolkit';
|
||||
import { MarginBreakdown } from '../components/margin-levels/margin-levels';
|
||||
|
||||
export const useFeeDealTicketDetails = (
|
||||
order: OrderSubmissionBody['orderSubmission'],
|
||||
@@ -148,6 +150,7 @@ export const getFeeDetailsValues = ({
|
||||
`An estimate of the most you would be expected to pay in fees, in the market's settlement asset ${assetSymbol}.`
|
||||
)}
|
||||
</span>
|
||||
|
||||
<FeesBreakdown
|
||||
fees={estMargin?.fees}
|
||||
feeFactors={market.fees.factors}
|
||||
@@ -159,16 +162,31 @@ export const getFeeDetailsValues = ({
|
||||
symbol: assetSymbol,
|
||||
},
|
||||
{
|
||||
label: t('Margin'),
|
||||
label: (
|
||||
<div className="flex items-center gap-2">
|
||||
<span>{t('Margin')} </span>
|
||||
<Icon name="chevron-down" size={3} />
|
||||
</div>
|
||||
),
|
||||
value:
|
||||
estMargin?.margin && `~${formatValueWithAssetDp(estMargin?.margin)}`,
|
||||
symbol: assetSymbol,
|
||||
labelDescription: EST_MARGIN_TOOLTIP_TEXT(assetSymbol),
|
||||
labelDescription: (
|
||||
<>
|
||||
<span>{EST_MARGIN_TOOLTIP_TEXT(assetSymbol)}</span>
|
||||
{/* <span></span>
|
||||
<MarginBreakdown
|
||||
marginLevels={estMargin?.marginLevels}
|
||||
assetDecimalPlaces={assetDecimals}
|
||||
assetSymbol={assetSymbol}
|
||||
/> */}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: t('Liquidation'),
|
||||
value: estCloseOut && `~${formatValueWithMarketDp(estCloseOut)}`,
|
||||
symbol: market.tradableInstrument.instrument.product.quoteName,
|
||||
symbol: quoteName,
|
||||
labelDescription: EST_CLOSEOUT_TOOLTIP_TEXT(quoteName),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useMarketPositions } from './use-market-positions';
|
||||
import { useEstimateOrderQuery } from './__generated__/EstimateOrder';
|
||||
import type { Market, MarketData } from '@vegaprotocol/market-list';
|
||||
import { getDerivedPrice } from '../utils/get-price';
|
||||
import type { MarginLevels } from './use-fee-deal-ticket-details';
|
||||
|
||||
export interface Props {
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
@@ -23,6 +24,7 @@ export interface OrderMargin {
|
||||
liquidityFee: string;
|
||||
infrastructureFee: string;
|
||||
};
|
||||
marginLevels: MarginLevels;
|
||||
}
|
||||
|
||||
export const useOrderMargin = ({
|
||||
@@ -50,7 +52,12 @@ export const useOrderMargin = ({
|
||||
});
|
||||
const { makerFee, liquidityFee, infrastructureFee } = data?.estimateOrder
|
||||
.fee || { makerFee: '', liquidityFee: '', infrastructureFee: '' };
|
||||
const { initialLevel } = data?.estimateOrder.marginLevels ?? {};
|
||||
const {
|
||||
initialLevel,
|
||||
searchLevel,
|
||||
maintenanceLevel,
|
||||
collateralReleaseLevel,
|
||||
} = data?.estimateOrder.marginLevels ?? {};
|
||||
return useMemo(() => {
|
||||
if (initialLevel) {
|
||||
const margin = BigNumber.maximum(
|
||||
@@ -63,6 +70,12 @@ export const useOrderMargin = ({
|
||||
.toString();
|
||||
return {
|
||||
margin,
|
||||
marginLevels: {
|
||||
searchLevel,
|
||||
maintenanceLevel,
|
||||
collateralReleaseLevel,
|
||||
initialLevel,
|
||||
},
|
||||
totalFees: fees,
|
||||
fees: {
|
||||
makerFee,
|
||||
@@ -72,5 +85,14 @@ export const useOrderMargin = ({
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}, [initialLevel, makerFee, liquidityFee, infrastructureFee, balance]);
|
||||
}, [
|
||||
initialLevel,
|
||||
balance,
|
||||
makerFee,
|
||||
liquidityFee,
|
||||
infrastructureFee,
|
||||
searchLevel,
|
||||
maintenanceLevel,
|
||||
collateralReleaseLevel,
|
||||
]);
|
||||
};
|
||||
|
||||
@@ -145,7 +145,7 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
||||
}}
|
||||
decimalPlaces={market.decimalPlaces}
|
||||
/>
|
||||
<p className="text-xs">
|
||||
<p className="text-xs mt-4">
|
||||
{t(
|
||||
'There is 1 unit of the settlement asset (%s) to every 1 quote unit (%s).',
|
||||
[assetSymbol, quoteUnit]
|
||||
@@ -249,7 +249,7 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
||||
dtClassName="text-black dark:text-white text-ui !px-0 !font-normal"
|
||||
ddClassName="text-black dark:text-white text-ui !px-0 !font-normal max-w-full"
|
||||
/>
|
||||
<p className="text-xs">
|
||||
<p className="text-xs mt-4">
|
||||
{t(
|
||||
'There is 1 unit of the settlement asset (%s) to every 1 quote unit (%s).',
|
||||
[assetSymbol, quoteUnit]
|
||||
@@ -309,27 +309,40 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
||||
),
|
||||
},
|
||||
...(market.priceMonitoringSettings?.parameters?.triggers || []).map(
|
||||
(trigger, i) => ({
|
||||
title: t(`Price monitoring trigger ${i + 1}`),
|
||||
content: <MarketInfoTable data={trigger} />,
|
||||
})
|
||||
(trigger, i) => {
|
||||
const bounds = market.data?.priceMonitoringBounds?.[i];
|
||||
return {
|
||||
title: t(`Price monitoring bounds ${i + 1}`),
|
||||
content: (
|
||||
<div className="text-xs">
|
||||
<div className="grid grid-cols-2 text-xs mb-4">
|
||||
<p className="col-span-1">
|
||||
{t('%s% probability of trading', [
|
||||
formatNumber(trigger.probability * 100),
|
||||
])}
|
||||
</p>
|
||||
<p className="col-span-1 text-right">
|
||||
{t('Within %s seconds', [formatNumber(trigger.horizonSecs)])}
|
||||
</p>
|
||||
</div>
|
||||
<div className="pl-2 pb-0 text-xs border-l-2">
|
||||
{bounds && (
|
||||
<MarketInfoTable
|
||||
data={{
|
||||
highestPrice: bounds.maxValidPrice,
|
||||
lowestPrice: bounds.minValidPrice,
|
||||
referencePrice: bounds.referencePrice,
|
||||
}}
|
||||
decimalPlaces={assetDecimals}
|
||||
assetSymbol={quoteUnit}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
}
|
||||
),
|
||||
...(market.data?.priceMonitoringBounds || []).map((trigger, i) => ({
|
||||
title: t(`Price monitoring bound ${i + 1}`),
|
||||
content: (
|
||||
<>
|
||||
<MarketInfoTable
|
||||
data={trigger}
|
||||
decimalPlaces={market.decimalPlaces}
|
||||
omits={['referencePrice', '__typename']}
|
||||
/>
|
||||
<MarketInfoTable
|
||||
data={{ referencePrice: trigger.referencePrice }}
|
||||
decimalPlaces={assetDecimals}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
})),
|
||||
{
|
||||
title: t('Liquidity monitoring parameters'),
|
||||
content: (
|
||||
@@ -369,37 +382,38 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
||||
content: (
|
||||
<>
|
||||
<p className="text-xs mb-4">
|
||||
{`For liquidity orders count towards a commitment they have to be
|
||||
within either the liquidity or price monitoring bounds (whichever is
|
||||
tighter).`}
|
||||
{`For liquidity orders to count towards a commitment, they must be
|
||||
within the liquidity monitoring bounds.`}
|
||||
</p>
|
||||
<p className="text-xs mb-4">
|
||||
{`The liquidity price range is a ${liquidityPriceRange} difference from the mid
|
||||
price.`}
|
||||
</p>
|
||||
<MarketInfoTable
|
||||
data={{
|
||||
liquidityPriceRange: `${liquidityPriceRange} of mid price`,
|
||||
lowestPrice:
|
||||
market.data?.midPrice &&
|
||||
`${addDecimalsFormatNumber(
|
||||
new BigNumber(1)
|
||||
.minus(market.lpPriceRange)
|
||||
.times(market.data.midPrice)
|
||||
.toString(),
|
||||
market.decimalPlaces
|
||||
)} ${quoteUnit}`,
|
||||
highestPrice:
|
||||
market.data?.midPrice &&
|
||||
`${addDecimalsFormatNumber(
|
||||
new BigNumber(1)
|
||||
.plus(market.lpPriceRange)
|
||||
.times(market.data.midPrice)
|
||||
.toString(),
|
||||
market.decimalPlaces
|
||||
)} ${quoteUnit}`,
|
||||
}}
|
||||
></MarketInfoTable>
|
||||
<div className="pl-2 pb-0 text-xs border-l-2">
|
||||
<MarketInfoTable
|
||||
data={{
|
||||
liquidityPriceRange: `${liquidityPriceRange} of mid price`,
|
||||
lowestPrice:
|
||||
market.data?.midPrice &&
|
||||
`${addDecimalsFormatNumber(
|
||||
new BigNumber(1)
|
||||
.minus(market.lpPriceRange)
|
||||
.times(market.data.midPrice)
|
||||
.toString(),
|
||||
market.decimalPlaces
|
||||
)} ${quoteUnit}`,
|
||||
highestPrice:
|
||||
market.data?.midPrice &&
|
||||
`${addDecimalsFormatNumber(
|
||||
new BigNumber(1)
|
||||
.plus(market.lpPriceRange)
|
||||
.times(market.data.midPrice)
|
||||
.toString(),
|
||||
market.decimalPlaces
|
||||
)} ${quoteUnit}`,
|
||||
}}
|
||||
></MarketInfoTable>
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
formatNumber,
|
||||
formatNumberPercentage,
|
||||
isNumeric,
|
||||
toDecimal,
|
||||
toNumberParts,
|
||||
} from './number';
|
||||
|
||||
@@ -197,3 +198,20 @@ describe('compactNumber', () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('toDecimal', () => {
|
||||
it.each([
|
||||
{ v: 0, o: '1' },
|
||||
{ v: 1, o: '0.1' },
|
||||
{ v: 2, o: '0.01' },
|
||||
{ v: 3, o: '0.001' },
|
||||
{ v: 4, o: '0.0001' },
|
||||
{ v: 5, o: '0.00001' },
|
||||
{ v: 6, o: '0.000001' },
|
||||
{ v: 7, o: '0.0000001' },
|
||||
{ v: 8, o: '0.00000001' },
|
||||
{ v: 9, o: '0.000000001' },
|
||||
])('formats with toNumber given number correctly', ({ v, o }) => {
|
||||
expect(toDecimal(v)).toStrictEqual(o);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ export const FormGroup = ({
|
||||
labelAlign = 'left',
|
||||
hideLabel = false,
|
||||
}: FormGroupProps) => {
|
||||
const wrapperClasses = classNames('relative mb-6', className);
|
||||
const wrapperClasses = classNames('relative mb-2', className);
|
||||
const labelClasses = classNames('block mb-2 text-sm', {
|
||||
'text-right': labelAlign === 'right',
|
||||
'sr-only': hideLabel,
|
||||
|
||||
@@ -24,11 +24,7 @@ export const KeyValueTable = ({
|
||||
return (
|
||||
<React.Fragment>
|
||||
{title && <TitleTag className={`text-xl my-2`}>{title}</TitleTag>}
|
||||
<div
|
||||
data-testid="key-value-table"
|
||||
{...rest}
|
||||
className={classNames('mb-4', className)}
|
||||
>
|
||||
<div data-testid="key-value-table" {...rest} className={className}>
|
||||
<div>
|
||||
{children &&
|
||||
React.Children.map(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import classNames from 'classnames';
|
||||
import { useMemo } from 'react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
const pseudoRandom = (seed: number) => {
|
||||
let value = seed;
|
||||
@@ -12,9 +12,26 @@ const pseudoRandom = (seed: number) => {
|
||||
export interface LoaderProps {
|
||||
size?: 'small' | 'large';
|
||||
forceTheme?: 'dark' | 'light';
|
||||
preloader?: boolean;
|
||||
}
|
||||
|
||||
export const Loader = ({ size = 'large', forceTheme }: LoaderProps) => {
|
||||
export const Loader = ({
|
||||
size = 'large',
|
||||
forceTheme,
|
||||
preloader,
|
||||
}: LoaderProps) => {
|
||||
const [, forceRender] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = preloader
|
||||
? undefined
|
||||
: setInterval(() => {
|
||||
forceRender((x) => !x);
|
||||
}, 100);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [preloader]);
|
||||
|
||||
const itemClasses = classNames('loader-item', {
|
||||
'dark:bg-white bg-black': !forceTheme,
|
||||
'bg-white': forceTheme === 'dark',
|
||||
|
||||
Reference in New Issue
Block a user