Compare commits

...
18 changed files with 206 additions and 273 deletions
@@ -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
-108
View File
@@ -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>
</>
);
+16 -17
View File
@@ -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;
+72 -74
View File
@@ -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% {
+1 -1
View File
@@ -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'}
@@ -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',
+1 -1
View File
@@ -50,7 +50,7 @@ export const Nav = ({
title,
}: NavbarProps) => {
const themeWrapperClasses = classNames(
'w-full overflow-y-hidden overflow-x-auto md:overflow-x-hidden font-alpha calt lg:text-lg',
'w-full overflow-y-hidden overflow-x-auto md:overflow-x-hidden font-alpha lg:text-lg',
{
dark: navbarTheme === 'dark',
}
@@ -155,7 +155,7 @@ export const Toast = ({
'w-[320px] rounded-md overflow-hidden',
'shadow-[8px_8px_16px_0_rgba(0,0,0,0.4)]',
'text-black dark:text-white',
'font-alpha calt text-[14px] leading-[19px]',
'font-alpha text-[14px] leading-[19px]',
// background
{
'bg-vega-light-100 dark:bg-vega-dark-100 ': intent === Intent.None,