Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3506fce0b6 | ||
|
|
3bfd13d261 | ||
|
|
3bbbcd9be1 | ||
|
|
042e5fd23b | ||
|
|
13a47f6439 | ||
|
|
b1ea86b081 | ||
|
|
b943adfe13 | ||
|
|
16f88e9577 | ||
|
|
2944e578d8 | ||
|
|
51ab1005b9 | ||
|
|
f6965ce119 | ||
|
|
9bffbbd557 | ||
|
|
ea3af6a234 |
@@ -296,7 +296,7 @@ export const ApplyCodeForm = ({ onSuccess }: { onSuccess?: () => void }) => {
|
|||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
data-testid="referral-apply-code-form"
|
data-testid="referral-apply-code-form"
|
||||||
className="bg-vega-clight-800 dark:bg-vega-cdark-800 mx-auto w-2/3 max-w-md rounded-lg p-8"
|
className="bg-vega-clight-800 dark:bg-vega-cdark-800 mx-auto md:w-2/3 max-w-md rounded-lg p-8"
|
||||||
>
|
>
|
||||||
<h3 className="calt mb-4 text-center text-2xl">
|
<h3 className="calt mb-4 text-center text-2xl">
|
||||||
{t('Apply a referral code')}
|
{t('Apply a referral code')}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ export const GRADIENT =
|
|||||||
'bg-gradient-to-b from-vega-clight-800 dark:from-vega-cdark-800 to-transparent';
|
'bg-gradient-to-b from-vega-clight-800 dark:from-vega-cdark-800 to-transparent';
|
||||||
|
|
||||||
export const SKY_BACKGROUND =
|
export const SKY_BACKGROUND =
|
||||||
'bg-[url(/sky-light.png)] dark:bg-[url(/sky-dark.png)] bg-[40%_0px] bg-[length:1440px] bg-no-repeat bg-local';
|
'bg-[url(/sky-light.png)] dark:bg-[url(/sky-dark.png)] bg-[37%_0px] bg-[length:1440px] bg-no-repeat bg-local';
|
||||||
|
|
||||||
// TODO: Update the links to use the correct referral related pages
|
// TODO: Update the links to use the correct referral related pages
|
||||||
export const REFERRAL_DOCS_LINK =
|
export const REFERRAL_DOCS_LINK =
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const CreateCodeForm = () => {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-testid="referral-create-code-form"
|
data-testid="referral-create-code-form"
|
||||||
className="w-2/3 max-w-md mx-auto bg-vega-clight-800 dark:bg-vega-cdark-800 p-8 rounded-lg"
|
className="md:w-2/3 max-w-md mx-auto bg-vega-clight-800 dark:bg-vega-cdark-800 p-8 rounded-lg"
|
||||||
>
|
>
|
||||||
<h3 className="mb-4 text-2xl text-center calt">
|
<h3 className="mb-4 text-2xl text-center calt">
|
||||||
{t('Create a referral code')}
|
{t('Create a referral code')}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
import { Table } from './table';
|
import { Table } from '../../components/table';
|
||||||
|
|
||||||
export const HowItWorksTable = () => {
|
export const HowItWorksTable = () => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
|
|||||||
@@ -5,16 +5,16 @@ import { useT } from '../../lib/use-t';
|
|||||||
export const LandingBanner = () => {
|
export const LandingBanner = () => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
return (
|
return (
|
||||||
<div className={classNames('relative mb-20')}>
|
<div className={classNames('relative mb-10 lg:mb-20')}>
|
||||||
<div className="">
|
<div className="">
|
||||||
<div
|
<div
|
||||||
aria-hidden
|
aria-hidden
|
||||||
className="absolute top-20 right-[120px] md:right-[240px] max-sm:hidden"
|
className="absolute top-20 right-[220px] md:right-[240px] max-sm:hidden"
|
||||||
>
|
>
|
||||||
<AnimatedDudeWithWire />
|
<AnimatedDudeWithWire />
|
||||||
</div>
|
</div>
|
||||||
<div className="pt-20 sm:w-[50%]">
|
<div className="pt-10 lg:pt-20 sm:w-[50%]">
|
||||||
<h1 className="text-6xl font-alpha calt mb-10">
|
<h1 className="text-3xl _text-[6vw] lg:!text-6xl leading-[1em] font-alpha calt mb-10">
|
||||||
{t('Vega community referrals')}
|
{t('Vega community referrals')}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg mb-1">
|
<p className="text-lg mb-1">
|
||||||
@@ -22,7 +22,7 @@ export const LandingBanner = () => {
|
|||||||
'Referral programs can be proposed and created via community governance.'
|
'Referral programs can be proposed and created via community governance.'
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-lg mb-10">
|
<p className="text-lg mb-1">
|
||||||
{t(
|
{t(
|
||||||
'Once live, users can generate referral codes to share with their friends and earn commission on their trades, while referred traders can access fee discounts based on the running volume of the group.'
|
'Once live, users can generate referral codes to share with their friends and earn commission on their trades, while referred traders can access fee discounts based on the running volume of the group.'
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const Layout = ({
|
|||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'max-w-[1440px]',
|
'max-w-[1440px]',
|
||||||
'mx-auto px-16 md:px-32 pb-32',
|
'mx-auto px-4 lg:px-32 pb-32',
|
||||||
'relative z-0',
|
'relative z-0',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
useUpdateReferees,
|
useUpdateReferees,
|
||||||
} from './hooks/use-referral';
|
} from './hooks/use-referral';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Table } from './table';
|
import { Table } from '../../components/table';
|
||||||
import {
|
import {
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
getDateFormat,
|
getDateFormat,
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export const Referrals = () => {
|
|||||||
{showNav && <Nav />}
|
{showNav && <Nav />}
|
||||||
<div
|
<div
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'py-16': showNav,
|
'py-8 lg:py-16': showNav,
|
||||||
'h-[300px] relative': loading || error,
|
'h-[300px] relative': loading || error,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import {
|
|||||||
getDateTimeFormat,
|
getDateTimeFormat,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { useReferralProgram } from './hooks/use-referral-program';
|
import { useReferralProgram } from './hooks/use-referral-program';
|
||||||
import { Table } from './table';
|
import { Table } from '../../components/table';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { BORDER_COLOR, GRADIENT } from './constants';
|
import { BORDER_COLOR, GRADIENT } from './constants';
|
||||||
import { Tag } from './tag';
|
import { Tag } from '../../components/helpers/tag';
|
||||||
import type { ComponentProps, ReactNode } from 'react';
|
import { getTierColor, getTierGradient } from '../../components/helpers/tiers';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
import { ExternalLink, truncateMiddle } from '@vegaprotocol/ui-toolkit';
|
import { ExternalLink, truncateMiddle } from '@vegaprotocol/ui-toolkit';
|
||||||
import {
|
import {
|
||||||
DApp,
|
DApp,
|
||||||
@@ -19,25 +20,6 @@ import {
|
|||||||
import { useT, ns } from '../../lib/use-t';
|
import { useT, ns } from '../../lib/use-t';
|
||||||
import { Trans } from 'react-i18next';
|
import { Trans } from 'react-i18next';
|
||||||
|
|
||||||
// rainbow-ish order
|
|
||||||
const TIER_COLORS: Array<ComponentProps<typeof Tag>['color']> = [
|
|
||||||
'pink',
|
|
||||||
'orange',
|
|
||||||
'yellow',
|
|
||||||
'green',
|
|
||||||
'blue',
|
|
||||||
'purple',
|
|
||||||
];
|
|
||||||
|
|
||||||
const getTierColor = (tier: number) => {
|
|
||||||
const tiers = Object.keys(TIER_COLORS).length;
|
|
||||||
let index = Math.abs(tier - 1);
|
|
||||||
if (tier >= tiers) {
|
|
||||||
index = index % tiers;
|
|
||||||
}
|
|
||||||
return TIER_COLORS[index];
|
|
||||||
};
|
|
||||||
|
|
||||||
const Loading = ({ variant }: { variant: 'large' | 'inline' }) => (
|
const Loading = ({ variant }: { variant: 'large' | 'inline' }) => (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@@ -53,10 +35,12 @@ const StakingTier = ({
|
|||||||
tier,
|
tier,
|
||||||
referralRewardMultiplier,
|
referralRewardMultiplier,
|
||||||
minimumStakedTokens,
|
minimumStakedTokens,
|
||||||
|
max,
|
||||||
}: {
|
}: {
|
||||||
tier: number;
|
tier: number;
|
||||||
referralRewardMultiplier: string;
|
referralRewardMultiplier: string;
|
||||||
minimumStakedTokens: string;
|
minimumStakedTokens: string;
|
||||||
|
max?: number;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const minimum = addDecimalsFormatNumber(minimumStakedTokens, 18);
|
const minimum = addDecimalsFormatNumber(minimumStakedTokens, 18);
|
||||||
@@ -97,7 +81,7 @@ const StakingTier = ({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<Tag color={getTierColor(tier)}>
|
<Tag color={getTierColor(tier, max)}>
|
||||||
{t('Multiplier')} {referralRewardMultiplier}x
|
{t('Multiplier')} {referralRewardMultiplier}x
|
||||||
</Tag>
|
</Tag>
|
||||||
<p className="mt-1 text-sm text-vega-clight-100 dark:text-vega-cdark-100">
|
<p className="mt-1 text-sm text-vega-clight-100 dark:text-vega-cdark-100">
|
||||||
@@ -159,7 +143,9 @@ export const TiersContainer = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h2 className="text-3xl mt-10">{t('Current program details')}</h2>
|
<h2 className="text-3xl mt-10 font-alpha calt">
|
||||||
|
{t('Current program details')}
|
||||||
|
</h2>
|
||||||
{details?.id && (
|
{details?.id && (
|
||||||
<p>
|
<p>
|
||||||
<Trans
|
<Trans
|
||||||
@@ -198,7 +184,18 @@ export const TiersContainer = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Container */}
|
{/* Container */}
|
||||||
<div className="bg-vega-clight-800 dark:bg-vega-cdark-800 text-black dark:text-white rounded-lg p-6 mt-1 mb-20">
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'md:bg-vega-clight-800',
|
||||||
|
'md:dark:bg-vega-cdark-800',
|
||||||
|
'md:text-black',
|
||||||
|
'md:dark:text-white',
|
||||||
|
'md:rounded-lg',
|
||||||
|
'md:p-6',
|
||||||
|
'mt-1',
|
||||||
|
'mb-20'
|
||||||
|
)}
|
||||||
|
>
|
||||||
{/* Benefit tiers */}
|
{/* Benefit tiers */}
|
||||||
<div className="flex flex-col mb-5">
|
<div className="flex flex-col mb-5">
|
||||||
<h3 className="text-2xl calt">{t('Benefit tiers')}</h3>
|
<h3 className="text-2xl calt">{t('Benefit tiers')}</h3>
|
||||||
@@ -261,6 +258,7 @@ const StakingTiers = ({
|
|||||||
<StakingTier
|
<StakingTier
|
||||||
key={i}
|
key={i}
|
||||||
tier={tier}
|
tier={tier}
|
||||||
|
max={data.length}
|
||||||
referralRewardMultiplier={referralRewardMultiplier}
|
referralRewardMultiplier={referralRewardMultiplier}
|
||||||
minimumStakedTokens={minimumStakedTokens}
|
minimumStakedTokens={minimumStakedTokens}
|
||||||
/>
|
/>
|
||||||
@@ -322,22 +320,7 @@ const TiersTable = ({
|
|||||||
className="bg-white dark:bg-vega-cdark-900"
|
className="bg-white dark:bg-vega-cdark-900"
|
||||||
data={data.map((d) => ({
|
data={data.map((d) => ({
|
||||||
...d,
|
...d,
|
||||||
className: classNames({
|
className: classNames(getTierGradient(d.tier, data.length)),
|
||||||
'from-vega-yellow-400 dark:from-vega-yellow-600 to-20% bg-highlight':
|
|
||||||
'yellow' === getTierColor(d.tier),
|
|
||||||
'from-vega-green-400 dark:from-vega-green-600 to-20% bg-highlight':
|
|
||||||
'green' === getTierColor(d.tier),
|
|
||||||
'from-vega-blue-400 dark:from-vega-blue-600 to-20% bg-highlight':
|
|
||||||
'blue' === getTierColor(d.tier),
|
|
||||||
'from-vega-purple-400 dark:from-vega-purple-600 to-20% bg-highlight':
|
|
||||||
'purple' === getTierColor(d.tier),
|
|
||||||
'from-vega-pink-400 dark:from-vega-pink-600 to-20% bg-highlight':
|
|
||||||
'pink' === getTierColor(d.tier),
|
|
||||||
'from-vega-orange-400 dark:from-vega-orange-600 to-20% bg-highlight':
|
|
||||||
'orange' === getTierColor(d.tier),
|
|
||||||
'from-vega-clight-200 dark:from-vega-cdark-200 to-20% bg-highlight':
|
|
||||||
'none' === getTierColor(d.tier),
|
|
||||||
}),
|
|
||||||
}))}
|
}))}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ export const Tile = ({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'rounded-lg overflow-hidden relative',
|
'text-black dark:text-white',
|
||||||
'bg-vega-clight-800 dark:bg-vega-cdark-800 text-black dark:text-white',
|
'overflow-hidden relative',
|
||||||
'p-6',
|
'p-3 md:p-6',
|
||||||
|
'rounded-lg',
|
||||||
|
'bg-vega-clight-800 dark:bg-vega-cdark-800',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -55,7 +57,10 @@ export const StatTile = ({
|
|||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
</h3>
|
</h3>
|
||||||
<div data-testid={`${testId}-value`} className="text-5xl text-left">
|
<div
|
||||||
|
data-testid={`${testId}-value`}
|
||||||
|
className="text-2xl lg:text-5xl text-left"
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
{description && (
|
{description && (
|
||||||
@@ -119,7 +124,7 @@ export const CodeTile = ({
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'relative bg-rainbow bg-clip-text text-transparent text-5xl overflow-hidden',
|
'relative bg-rainbow bg-clip-text text-transparent text-2xl lg:text-5xl overflow-hidden',
|
||||||
FADE_OUT_STYLE
|
FADE_OUT_STYLE
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export const Card = ({
|
|||||||
loading = false,
|
loading = false,
|
||||||
highlight = false,
|
highlight = false,
|
||||||
testId,
|
testId,
|
||||||
|
noBackgroundOnMobile = false,
|
||||||
}: {
|
}: {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
title: string;
|
title: string;
|
||||||
@@ -16,20 +17,33 @@ export const Card = ({
|
|||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
highlight?: boolean;
|
highlight?: boolean;
|
||||||
testId?: string;
|
testId?: string;
|
||||||
|
noBackgroundOnMobile?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-testid={testId}
|
data-testid={testId}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'bg-vega-clight-800 dark:bg-vega-cdark-800 col-span-full p-0.5 lg:col-auto',
|
'col-span-full lg:col-auto',
|
||||||
'rounded-lg',
|
{
|
||||||
|
'rounded-lg bg-vega-clight-800 dark:bg-vega-cdark-800 p-0.5':
|
||||||
|
!noBackgroundOnMobile,
|
||||||
|
'mt-3 md:mt-0 md:rounded-lg md:bg-vega-clight-800 md:dark:bg-vega-cdark-800 md:p-0.5':
|
||||||
|
noBackgroundOnMobile,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'bg-rainbow': highlight,
|
'bg-rainbow': highlight,
|
||||||
},
|
},
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="bg-vega-clight-800 dark:bg-vega-cdark-800 h-full w-full rounded p-4">
|
<div
|
||||||
|
className={classNames('h-full w-full', {
|
||||||
|
'bg-vega-clight-800 dark:bg-vega-cdark-800 rounded p-4':
|
||||||
|
!noBackgroundOnMobile,
|
||||||
|
'md:bg-vega-clight-800 md:dark:bg-vega-cdark-800 md:rounded md:p-4':
|
||||||
|
noBackgroundOnMobile,
|
||||||
|
})}
|
||||||
|
>
|
||||||
<h2 className="mb-3">{title}</h2>
|
<h2 className="mb-3">{title}</h2>
|
||||||
{loading ? <CardLoader /> : children}
|
{loading ? <CardLoader /> : children}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { MarketFees } from './market-fees';
|
|||||||
import { useVolumeStats } from './use-volume-stats';
|
import { useVolumeStats } from './use-volume-stats';
|
||||||
import { useReferralStats } from './use-referral-stats';
|
import { useReferralStats } from './use-referral-stats';
|
||||||
import { formatPercentage, getAdjustedFee } from './utils';
|
import { formatPercentage, getAdjustedFee } from './utils';
|
||||||
import { Table, Td, Th, THead, Tr } from './table';
|
import { Table as SimpleTable } from '../../components/table';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { Links } from '../../lib/links';
|
import { Links } from '../../lib/links';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
@@ -24,6 +24,8 @@ import {
|
|||||||
truncateMiddle,
|
truncateMiddle,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { getTierGradient } from '../helpers/tiers';
|
||||||
|
|
||||||
export const FeesContainer = () => {
|
export const FeesContainer = () => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
@@ -166,6 +168,7 @@ export const FeesContainer = () => {
|
|||||||
className="lg:col-span-full xl:col-span-2"
|
className="lg:col-span-full xl:col-span-2"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
data-testid="volume-discount-card"
|
data-testid="volume-discount-card"
|
||||||
|
noBackgroundOnMobile={true}
|
||||||
>
|
>
|
||||||
<VolumeTiers
|
<VolumeTiers
|
||||||
tiers={volumeTiers}
|
tiers={volumeTiers}
|
||||||
@@ -179,12 +182,14 @@ export const FeesContainer = () => {
|
|||||||
className="lg:col-span-full xl:col-span-2"
|
className="lg:col-span-full xl:col-span-2"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
data-testid="referral-discount-card"
|
data-testid="referral-discount-card"
|
||||||
|
noBackgroundOnMobile={true}
|
||||||
>
|
>
|
||||||
<ReferralTiers
|
<ReferralTiers
|
||||||
tiers={referralTiers}
|
tiers={referralTiers}
|
||||||
tierIndex={referralTierIndex}
|
tierIndex={referralTierIndex}
|
||||||
epochsInSet={epochsInSet}
|
epochsInSet={epochsInSet}
|
||||||
referralVolumeInWindow={referralVolumeInWindow}
|
referralVolumeInWindow={referralVolumeInWindow}
|
||||||
|
referralDiscountWindowLength={referralDiscountWindowLength}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
<Card
|
<Card
|
||||||
@@ -192,6 +197,7 @@ export const FeesContainer = () => {
|
|||||||
className="lg:col-span-full"
|
className="lg:col-span-full"
|
||||||
loading={marketsLoading}
|
loading={marketsLoading}
|
||||||
data-testid="fees-by-market-card"
|
data-testid="fees-by-market-card"
|
||||||
|
noBackgroundOnMobile={true}
|
||||||
>
|
>
|
||||||
<MarketFees
|
<MarketFees
|
||||||
markets={markets}
|
markets={markets}
|
||||||
@@ -477,44 +483,65 @@ const VolumeTiers = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table>
|
<SimpleTable
|
||||||
<THead>
|
className="bg-white dark:bg-vega-cdark-900"
|
||||||
<Tr>
|
columns={[
|
||||||
<Th data-testid="tier-header">{t('Tier')}</Th>
|
{ name: 'tier', displayName: t('Tier'), testId: 'col-tier-value' },
|
||||||
<Th data-testid="discount-header">{t('Discount')}</Th>
|
{
|
||||||
<Th data-testid="min-volume-header">{t('Min. trading volume')}</Th>
|
name: 'discount',
|
||||||
<Th data-testid="my-volume-header">
|
displayName: t('Discount'),
|
||||||
{t('myVolume', 'My volume (last {{count}} epochs)', {
|
testId: 'discount-value',
|
||||||
count: windowLength,
|
},
|
||||||
})}
|
{
|
||||||
</Th>
|
name: 'minTradingVolume',
|
||||||
<Th data-testid="actions-header" />
|
displayName: t('Min. trading volume'),
|
||||||
</Tr>
|
testId: 'min-volume-value',
|
||||||
</THead>
|
},
|
||||||
<tbody>
|
{
|
||||||
{Array.from(tiers).map((tier, i) => {
|
name: 'myVolume',
|
||||||
const isUserTier = tierIndex === i;
|
displayName: t('myVolume', 'My volume (last {{count}} epochs)', {
|
||||||
|
count: windowLength,
|
||||||
return (
|
}),
|
||||||
<Tr key={i} data-testid={`tier-row-${i}`}>
|
testId: 'my-volume-value',
|
||||||
<Td data-testid={`tier-value-${i}`}>{i + 1}</Td>
|
},
|
||||||
<Td data-testid={`discount-value-${i}`}>
|
{
|
||||||
{formatPercentage(Number(tier.volumeDiscountFactor))}%
|
name: 'indicator',
|
||||||
</Td>
|
className: 'max-md:hidden',
|
||||||
<Td data-testid={`min-volume-value-${i}`}>
|
testId: 'your-tier',
|
||||||
{formatNumber(tier.minimumRunningNotionalTakerVolume)}
|
},
|
||||||
</Td>
|
]}
|
||||||
<Td data-testid={`my-volume-value-${i}`}>
|
data={Array.from(tiers).map((tier, i) => {
|
||||||
{isUserTier ? formatNumber(lastEpochVolume) : ''}
|
const isUserTier = tierIndex === i;
|
||||||
</Td>
|
const indicator = isUserTier ? (
|
||||||
<Td data-testid={`your-tier-${i}`}>
|
<YourTier testId={`your-volume-tier-${i}`} />
|
||||||
{isUserTier ? <YourTier /> : null}
|
) : null;
|
||||||
</Td>
|
const tierIndicator = (
|
||||||
</Tr>
|
<div className="flex justify-between">
|
||||||
);
|
<span data-testid={`tier-value-${i}`}>{i + 1}</span>
|
||||||
})}
|
<span className="md:hidden">{indicator}</span>
|
||||||
</tbody>
|
</div>
|
||||||
</Table>
|
);
|
||||||
|
return {
|
||||||
|
tier: tierIndicator,
|
||||||
|
discount: (
|
||||||
|
<>{formatPercentage(Number(tier.volumeDiscountFactor))}%</>
|
||||||
|
),
|
||||||
|
minTradingVolume: (
|
||||||
|
<>{formatNumber(tier.minimumRunningNotionalTakerVolume)}</>
|
||||||
|
),
|
||||||
|
myVolume: isUserTier ? (
|
||||||
|
formatNumber(lastEpochVolume)
|
||||||
|
) : (
|
||||||
|
<span className="md:hidden">-</span>
|
||||||
|
),
|
||||||
|
indicator: indicator,
|
||||||
|
className: classNames(
|
||||||
|
getTierGradient(i + 1, tiers.length),
|
||||||
|
'text-xs'
|
||||||
|
),
|
||||||
|
};
|
||||||
|
})}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -524,6 +551,7 @@ const ReferralTiers = ({
|
|||||||
tierIndex,
|
tierIndex,
|
||||||
epochsInSet,
|
epochsInSet,
|
||||||
referralVolumeInWindow,
|
referralVolumeInWindow,
|
||||||
|
referralDiscountWindowLength,
|
||||||
}: {
|
}: {
|
||||||
tiers: Array<{
|
tiers: Array<{
|
||||||
referralDiscountFactor: string;
|
referralDiscountFactor: string;
|
||||||
@@ -533,6 +561,7 @@ const ReferralTiers = ({
|
|||||||
tierIndex: number;
|
tierIndex: number;
|
||||||
epochsInSet: number;
|
epochsInSet: number;
|
||||||
referralVolumeInWindow: number;
|
referralVolumeInWindow: number;
|
||||||
|
referralDiscountWindowLength: number;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
|
|
||||||
@@ -544,60 +573,81 @@ const ReferralTiers = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table>
|
<SimpleTable
|
||||||
<THead>
|
className="bg-white dark:bg-vega-cdark-900"
|
||||||
<Tr>
|
columns={[
|
||||||
<Th data-testid="tier-header">{t('Tier')}</Th>
|
{ name: 'tier', displayName: t('Tier'), testId: 'col-tier-value' },
|
||||||
<Th data-testid="discount-header">{t('Discount')}</Th>
|
{
|
||||||
<Th data-testid="min-volume-header">{t('Min. trading volume')}</Th>
|
name: 'discount',
|
||||||
<Th data-testid="required-epochs-header">{t('Required epochs')}</Th>
|
displayName: t('Discount'),
|
||||||
<Th data-testid="extra-header" />
|
tooltip: t(
|
||||||
</Tr>
|
"The proportion of the referee's taker fees to be discounted"
|
||||||
</THead>
|
),
|
||||||
<tbody>
|
testId: 'discount-value',
|
||||||
{Array.from(tiers).map((tier, i) => {
|
},
|
||||||
const isUserTier = tierIndex === i;
|
{
|
||||||
|
name: 'volume',
|
||||||
|
displayName: t(
|
||||||
|
'minTradingVolume',
|
||||||
|
'Min. trading volume (last {{count}} epochs)',
|
||||||
|
{
|
||||||
|
count: referralDiscountWindowLength,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
tooltip: t(
|
||||||
|
'The minimum running notional for the given benefit tier'
|
||||||
|
),
|
||||||
|
testId: 'min-volume-value',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'epochs',
|
||||||
|
displayName: t('Min. epochs'),
|
||||||
|
tooltip: t(
|
||||||
|
'The minimum number of epochs the party needs to be in the referral set to be eligible for the benefit'
|
||||||
|
),
|
||||||
|
testId: 'required-epochs-value',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'indicator',
|
||||||
|
className: 'max-md:hidden',
|
||||||
|
testId: 'user-tier-or-unlocks',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
data={Array.from(tiers).map((tier, i) => {
|
||||||
|
const isUserTier = tierIndex === i;
|
||||||
|
const requiredVolume = Number(tier.minimumRunningNotionalTakerVolume);
|
||||||
|
|
||||||
const requiredVolume = Number(
|
const indicator = isUserTier ? (
|
||||||
tier.minimumRunningNotionalTakerVolume
|
<YourTier testId={`your-referral-tier-${i}`} />
|
||||||
);
|
) : referralVolumeInWindow >= requiredVolume &&
|
||||||
let unlocksIn = null;
|
epochsInSet < tier.minimumEpochs ? (
|
||||||
|
<span className="text-muted text-xs">
|
||||||
|
Unlocks in {tier.minimumEpochs - epochsInSet} epochs
|
||||||
|
</span>
|
||||||
|
) : null;
|
||||||
|
|
||||||
if (
|
const tierIndicator = (
|
||||||
referralVolumeInWindow >= requiredVolume &&
|
<div className="flex justify-between">
|
||||||
epochsInSet < tier.minimumEpochs
|
<span data-testid={`tier-value-${i}`}>{i + 1}</span>
|
||||||
) {
|
<span className="md:hidden">{indicator}</span>
|
||||||
unlocksIn = (
|
</div>
|
||||||
<span className="text-muted">
|
);
|
||||||
Unlocks in {tier.minimumEpochs - epochsInSet} epochs
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return {
|
||||||
<Tr key={i} data-testid={`tier-row-${i}`}>
|
tier: tierIndicator,
|
||||||
<Td data-testid={`tier-value-${i}`}>{i + 1}</Td>
|
discount: (
|
||||||
<Td data-testid={`discount-value-${i}`}>
|
<>{formatPercentage(Number(tier.referralDiscountFactor))}%</>
|
||||||
{formatPercentage(Number(tier.referralDiscountFactor))}%
|
),
|
||||||
</Td>
|
volume: formatNumber(tier.minimumRunningNotionalTakerVolume),
|
||||||
<Td data-testid={`min-volume-value-${i}`}>
|
epochs: tier.minimumEpochs,
|
||||||
{formatNumber(tier.minimumRunningNotionalTakerVolume)}
|
indicator,
|
||||||
</Td>
|
className: classNames(
|
||||||
<Td data-testid={`required-epochs-value-${i}`}>
|
getTierGradient(i + 1, tiers.length),
|
||||||
{tier.minimumEpochs}
|
'text-xs'
|
||||||
</Td>
|
),
|
||||||
<Td data-testid={`user-tier-or-unlocks-${i}`}>
|
};
|
||||||
{isUserTier ? (
|
})}
|
||||||
<YourTier testId={`your-tier-${i}`} />
|
/>
|
||||||
) : (
|
|
||||||
unlocksIn
|
|
||||||
)}
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</tbody>
|
|
||||||
</Table>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -611,7 +661,7 @@ const YourTier = ({ testId }: YourTierProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className="bg-rainbow whitespace-nowrap rounded-xl px-4 py-1.5 text-white"
|
className="bg-rainbow whitespace-nowrap rounded-xl px-4 py-1.5 text-white text-xs"
|
||||||
data-testid={testId}
|
data-testid={testId}
|
||||||
>
|
>
|
||||||
{t('Your tier')}
|
{t('Your tier')}
|
||||||
|
|||||||
@@ -8,43 +8,53 @@ import { useNavigateWithMeta } from '../../lib/hooks/use-market-click-handler';
|
|||||||
import { Links } from '../../lib/links';
|
import { Links } from '../../lib/links';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
import { type ColDef } from 'ag-grid-community/dist/lib/entities/colDef';
|
||||||
|
|
||||||
const useFeesTableColumnDefs = () => {
|
const useFeesTableColumnDefs = (): ColDef[] => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() => [
|
() =>
|
||||||
{ field: 'code', cellRenderer: 'MarketCodeCell' },
|
[
|
||||||
{
|
{
|
||||||
field: 'feeAfterDiscount',
|
field: 'code',
|
||||||
headerName: t('Total fee after discount'),
|
cellRenderer: 'MarketCodeCell',
|
||||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
pinned: 'left',
|
||||||
},
|
width: 150,
|
||||||
{
|
},
|
||||||
field: 'infraFee',
|
{
|
||||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
field: 'liquidityFee',
|
||||||
},
|
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||||
{
|
},
|
||||||
field: 'makerFee',
|
{
|
||||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
field: 'feeAfterDiscount',
|
||||||
},
|
headerName: t('Total fee after discount'),
|
||||||
{
|
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||||
field: 'liquidityFee',
|
},
|
||||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
{
|
||||||
},
|
field: 'totalFee',
|
||||||
{
|
headerName: t('Total fee before discount'),
|
||||||
field: 'totalFee',
|
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||||
headerName: t('Total fee before discount'),
|
},
|
||||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
{
|
||||||
},
|
field: 'infraFee',
|
||||||
],
|
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'makerFee',
|
||||||
|
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||||
|
},
|
||||||
|
] as ColDef[],
|
||||||
[t]
|
[t]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const feesTableDefaultColDef = {
|
const feesTableDefaultColDef = {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
minWidth: 62,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
suppressMovable: true,
|
||||||
|
pinned: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const components = {
|
const components = {
|
||||||
@@ -62,6 +72,8 @@ export const MarketFees = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const navigateWithMeta = useNavigateWithMeta();
|
const navigateWithMeta = useNavigateWithMeta();
|
||||||
|
|
||||||
|
const colDef = useFeesTableColumnDefs();
|
||||||
|
|
||||||
const rows = compact(markets || []).map((m) => {
|
const rows = compact(markets || []).map((m) => {
|
||||||
const infraFee = new BigNumber(m.fees.factors.infrastructureFee);
|
const infraFee = new BigNumber(m.fees.factors.infrastructureFee);
|
||||||
const makerFee = new BigNumber(m.fees.factors.makerFee);
|
const makerFee = new BigNumber(m.fees.factors.makerFee);
|
||||||
@@ -88,9 +100,9 @@ export const MarketFees = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border rounded-sm border-default">
|
<div className="border rounded-lg md:rounded-sm overflow-hidden border-default">
|
||||||
<AgGrid
|
<AgGrid
|
||||||
columnDefs={useFeesTableColumnDefs()}
|
columnDefs={colDef}
|
||||||
rowData={rows}
|
rowData={rows}
|
||||||
getRowId={({ data }) => data.id}
|
getRowId={({ data }) => data.id}
|
||||||
defaultColDef={feesTableDefaultColDef}
|
defaultColDef={feesTableDefaultColDef}
|
||||||
|
|||||||
+9
-1
@@ -2,7 +2,15 @@ import type { HTMLAttributes } from 'react';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
type TagProps = {
|
type TagProps = {
|
||||||
color?: 'yellow' | 'green' | 'blue' | 'purple' | 'pink' | 'orange' | 'none';
|
color?:
|
||||||
|
| 'yellow'
|
||||||
|
| 'green'
|
||||||
|
| 'blue'
|
||||||
|
| 'purple'
|
||||||
|
| 'pink'
|
||||||
|
| 'orange'
|
||||||
|
| 'red'
|
||||||
|
| 'none';
|
||||||
};
|
};
|
||||||
export const Tag = ({
|
export const Tag = ({
|
||||||
color = 'none',
|
color = 'none',
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import type { ComponentProps } from 'react';
|
||||||
|
import type { Tag } from './tag';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
// rainbow-ish order
|
||||||
|
export const TIER_COLORS: Array<ComponentProps<typeof Tag>['color']> = [
|
||||||
|
'none', // worst tier if 8 tiers, otherwise relative to the best tier
|
||||||
|
'red',
|
||||||
|
'pink',
|
||||||
|
'orange',
|
||||||
|
'yellow',
|
||||||
|
'green',
|
||||||
|
'blue',
|
||||||
|
'purple', // best tier
|
||||||
|
];
|
||||||
|
|
||||||
|
export const getTierColor = (tier: number, max = TIER_COLORS.length) => {
|
||||||
|
const available =
|
||||||
|
max < TIER_COLORS.length
|
||||||
|
? TIER_COLORS.slice(TIER_COLORS.length - max)
|
||||||
|
: TIER_COLORS;
|
||||||
|
const tiers = Object.keys(available).length;
|
||||||
|
let index = Math.abs(tier - 1);
|
||||||
|
if (tier >= tiers) {
|
||||||
|
index = index % tiers;
|
||||||
|
}
|
||||||
|
return available[index];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTierGradient = (tier: number, max = TIER_COLORS.length) =>
|
||||||
|
classNames({
|
||||||
|
'from-vega-yellow-400 dark:from-vega-yellow-600 to-20% bg-highlight':
|
||||||
|
'yellow' === getTierColor(tier, max),
|
||||||
|
'from-vega-green-400 dark:from-vega-green-600 to-20% bg-highlight':
|
||||||
|
'green' === getTierColor(tier, max),
|
||||||
|
'from-vega-blue-400 dark:from-vega-blue-600 to-20% bg-highlight':
|
||||||
|
'blue' === getTierColor(tier, max),
|
||||||
|
'from-vega-purple-400 dark:from-vega-purple-600 to-20% bg-highlight':
|
||||||
|
'purple' === getTierColor(tier, max),
|
||||||
|
'from-vega-pink-400 dark:from-vega-pink-600 to-20% bg-highlight':
|
||||||
|
'pink' === getTierColor(tier, max),
|
||||||
|
'from-vega-orange-400 dark:from-vega-orange-600 to-20% bg-highlight':
|
||||||
|
'orange' === getTierColor(tier, max),
|
||||||
|
'from-vega-red-400 dark:from-vega-red-600 to-20% bg-highlight':
|
||||||
|
'red' === getTierColor(tier, max),
|
||||||
|
'from-vega-clight-600 dark:from-vega-cdark-600 to-20% bg-highlight':
|
||||||
|
'none' === getTierColor(tier, max),
|
||||||
|
});
|
||||||
@@ -231,6 +231,7 @@ export const RewardsContainer = () => {
|
|||||||
title={t('Rewards history')}
|
title={t('Rewards history')}
|
||||||
className="lg:col-span-full"
|
className="lg:col-span-full"
|
||||||
loading={rewardsLoading}
|
loading={rewardsLoading}
|
||||||
|
noBackgroundOnMobile={true}
|
||||||
>
|
>
|
||||||
<RewardsHistoryContainer
|
<RewardsHistoryContainer
|
||||||
epoch={Number(epochData?.epoch.id)}
|
epoch={Number(epochData?.epoch.id)}
|
||||||
|
|||||||
@@ -99,16 +99,25 @@ describe('RewardsHistoryTable', () => {
|
|||||||
it('renders table with accounts summed up by asset', () => {
|
it('renders table with accounts summed up by asset', () => {
|
||||||
render(<RewardHistoryTable {...props} />);
|
render(<RewardHistoryTable {...props} />);
|
||||||
|
|
||||||
const container = within(
|
const containerLeft = within(
|
||||||
|
document.querySelector('.ag-pinned-left-cols-container') as HTMLElement
|
||||||
|
);
|
||||||
|
const pinnedRows = containerLeft.getAllByRole('row');
|
||||||
|
|
||||||
|
const containerCenter = within(
|
||||||
document.querySelector('.ag-center-cols-container') as HTMLElement
|
document.querySelector('.ag-center-cols-container') as HTMLElement
|
||||||
);
|
);
|
||||||
const rows = container.getAllByRole('row');
|
const rows = containerCenter.getAllByRole('row');
|
||||||
expect(rows).toHaveLength(
|
expect(rows).toHaveLength(
|
||||||
Object.keys(groupBy(rewardSummaries, 'node.assetId')).length
|
Object.keys(groupBy(rewardSummaries, 'node.assetId')).length
|
||||||
);
|
);
|
||||||
|
|
||||||
let row = within(rows[0]);
|
let row = within(rows[0]);
|
||||||
let cells = row.getAllByRole('gridcell');
|
let pinnedRow = within(pinnedRows[0]);
|
||||||
|
let cells = [
|
||||||
|
...pinnedRow.getAllByRole('gridcell'),
|
||||||
|
...row.getAllByRole('gridcell'),
|
||||||
|
];
|
||||||
|
|
||||||
let assetCell = getCell(cells, 'asset.symbol');
|
let assetCell = getCell(cells, 'asset.symbol');
|
||||||
expect(assetCell.getByTestId('stack-cell-primary')).toHaveTextContent(
|
expect(assetCell.getByTestId('stack-cell-primary')).toHaveTextContent(
|
||||||
@@ -140,7 +149,11 @@ describe('RewardsHistoryTable', () => {
|
|||||||
|
|
||||||
// Second row
|
// Second row
|
||||||
row = within(rows[1]);
|
row = within(rows[1]);
|
||||||
cells = row.getAllByRole('gridcell');
|
pinnedRow = within(pinnedRows[1]);
|
||||||
|
cells = [
|
||||||
|
...pinnedRow.getAllByRole('gridcell'),
|
||||||
|
...row.getAllByRole('gridcell'),
|
||||||
|
];
|
||||||
|
|
||||||
assetCell = getCell(cells, 'asset.symbol');
|
assetCell = getCell(cells, 'asset.symbol');
|
||||||
expect(assetCell.getByTestId('stack-cell-primary')).toHaveTextContent(
|
expect(assetCell.getByTestId('stack-cell-primary')).toHaveTextContent(
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ export const RewardsHistoryContainer = ({
|
|||||||
|
|
||||||
const defaultColDef = {
|
const defaultColDef = {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
minWidth: 62,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
};
|
};
|
||||||
@@ -195,6 +196,8 @@ export const RewardHistoryTable = ({
|
|||||||
return <StackedCell primary={value} secondary={data.asset.name} />;
|
return <StackedCell primary={value} secondary={data.asset.name} />;
|
||||||
},
|
},
|
||||||
sort: 'desc',
|
sort: 'desc',
|
||||||
|
pinned: 'left',
|
||||||
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'infrastructureFees',
|
field: 'infrastructureFees',
|
||||||
@@ -257,7 +260,7 @@ export const RewardHistoryTable = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-2 flex items-center justify-between gap-2">
|
<div className="mb-2 flex flex-wrap items-center justify-between gap-2">
|
||||||
<h4 className="text-muted flex items-center gap-2 text-sm">
|
<h4 className="text-muted flex items-center gap-2 text-sm">
|
||||||
<label htmlFor="fromEpoch">{t('From epoch')}</label>
|
<label htmlFor="fromEpoch">{t('From epoch')}</label>
|
||||||
<EpochInput
|
<EpochInput
|
||||||
@@ -329,15 +332,17 @@ export const RewardHistoryTable = ({
|
|||||||
</TradingButton>
|
</TradingButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<AgGrid
|
<div className="border rounded-lg md:rounded-sm overflow-hidden border-default">
|
||||||
columnDefs={columnDefs}
|
<AgGrid
|
||||||
defaultColDef={defaultColDef}
|
columnDefs={columnDefs}
|
||||||
rowData={rowData}
|
defaultColDef={defaultColDef}
|
||||||
rowHeight={45}
|
rowData={rowData}
|
||||||
domLayout="autoHeight"
|
rowHeight={45}
|
||||||
// Show loading message without wiping out the current rows
|
domLayout="autoHeight"
|
||||||
overlayNoRowsTemplate={loading ? t('Loading...') : t('No rows')}
|
// Show loading message without wiping out the current rows
|
||||||
/>
|
overlayNoRowsTemplate={loading ? t('Loading...') : t('No rows')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './table';
|
||||||
+10
-6
@@ -1,13 +1,17 @@
|
|||||||
import { Tooltip, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
import { Tooltip, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { forwardRef, type ReactNode, type HTMLAttributes } from 'react';
|
import { forwardRef, type ReactNode, type HTMLAttributes } from 'react';
|
||||||
import { BORDER_COLOR, GRADIENT } from './constants';
|
|
||||||
|
export const BORDER_COLOR = 'border-vega-clight-500 dark:border-vega-cdark-500';
|
||||||
|
export const GRADIENT =
|
||||||
|
'bg-gradient-to-b from-vega-clight-800 dark:from-vega-cdark-800 to-transparent';
|
||||||
|
|
||||||
type TableColumnDefinition = {
|
type TableColumnDefinition = {
|
||||||
displayName?: ReactNode;
|
displayName?: ReactNode;
|
||||||
name: string;
|
name: string;
|
||||||
tooltip?: string;
|
tooltip?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
testId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type TableProps = {
|
type TableProps = {
|
||||||
@@ -42,7 +46,7 @@ export const Table = forwardRef<
|
|||||||
key={name}
|
key={name}
|
||||||
col-id={name}
|
col-id={name}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'px-5 py-3 text-sm text-vega-clight-100 dark:text-vega-cdark-100 font-normal',
|
'px-5 py-3 text-xs text-vega-clight-100 dark:text-vega-cdark-100 font-normal',
|
||||||
INNER_BORDER_STYLE
|
INNER_BORDER_STYLE
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -66,7 +70,7 @@ export const Table = forwardRef<
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'w-full',
|
'w-full',
|
||||||
'border-separate border rounded-md border-spacing-0',
|
'border-separate border rounded-md border-spacing-0 overflow-hidden',
|
||||||
BORDER_COLOR,
|
BORDER_COLOR,
|
||||||
GRADIENT,
|
GRADIENT,
|
||||||
className
|
className
|
||||||
@@ -82,10 +86,10 @@ export const Table = forwardRef<
|
|||||||
'max-md:flex flex-col w-full': !noCollapse,
|
'max-md:flex flex-col w-full': !noCollapse,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{columns.map(({ name, displayName, className }, j) => (
|
{columns.map(({ name, displayName, className, testId }, j) => (
|
||||||
<td
|
<td
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'px-5 py-3 text-base',
|
'px-5 py-3',
|
||||||
{
|
{
|
||||||
'max-md:flex max-md:flex-col max-md:justify-between':
|
'max-md:flex max-md:flex-col max-md:justify-between':
|
||||||
!noCollapse,
|
!noCollapse,
|
||||||
@@ -110,7 +114,7 @@ export const Table = forwardRef<
|
|||||||
{displayName}
|
{displayName}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<span>{d[name]}</span>
|
<span data-testid={`${testId || name}-${i}`}>{d[name]}</span>
|
||||||
</td>
|
</td>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
@@ -27,8 +27,6 @@ MIN_VOLUME_VALUE_0 = "min-volume-value-0"
|
|||||||
MIN_VOLUME_VALUE_1 = "min-volume-value-1"
|
MIN_VOLUME_VALUE_1 = "min-volume-value-1"
|
||||||
MY_VOLUME_VALUE_0 = "my-volume-value-0"
|
MY_VOLUME_VALUE_0 = "my-volume-value-0"
|
||||||
MY_VOLUME_VALUE_1 = "my-volume-value-1"
|
MY_VOLUME_VALUE_1 = "my-volume-value-1"
|
||||||
YOUR_TIER_0 = "your-tier-0"
|
|
||||||
YOUR_TIER_1 = "your-tier-1"
|
|
||||||
ORDER_SIZE = "order-size"
|
ORDER_SIZE = "order-size"
|
||||||
ORDER_PRICE = "order-price"
|
ORDER_PRICE = "order-price"
|
||||||
DISCOUNT_PILL = "discount-pill"
|
DISCOUNT_PILL = "discount-pill"
|
||||||
@@ -52,6 +50,7 @@ REQUIRED_EPOCHS_VALUE_1 = "required-epochs-value-1"
|
|||||||
FILLS = "Fills"
|
FILLS = "Fills"
|
||||||
TAB_FILLS = "tab-fills"
|
TAB_FILLS = "tab-fills"
|
||||||
FEE_BREAKDOWN_TOOLTIP = "fee-breakdown-tooltip"
|
FEE_BREAKDOWN_TOOLTIP = "fee-breakdown-tooltip"
|
||||||
|
PINNED_ROW_LOCATOR = ".ag-pinned-left-cols-container .ag-row"
|
||||||
ROW_LOCATOR = ".ag-center-cols-container .ag-row"
|
ROW_LOCATOR = ".ag-center-cols-container .ag-row"
|
||||||
# Col-Ids:
|
# Col-Ids:
|
||||||
COL_INSTRUMENT_CODE = '[col-id="market.tradableInstrument.instrument.code"]'
|
COL_INSTRUMENT_CODE = '[col-id="market.tradableInstrument.instrument.code"]'
|
||||||
@@ -405,10 +404,10 @@ def test_fees_page_referral_discount_program_referral_benefits(
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"tier, discount_program, my_volume_test_id, my_volume_value, your_tier",
|
"tier, discount_program, my_volume_test_id, my_volume_value, your_tier",
|
||||||
[
|
[
|
||||||
(1, "volume", "my-volume-value-0", "103", "your-tier-0"),
|
(1, "volume", "my-volume-value-0", "103", "your-volume-tier-0"),
|
||||||
(2, "volume", "my-volume-value-1", "206", "your-tier-1"),
|
(2, "volume", "my-volume-value-1", "206", "your-volume-tier-1"),
|
||||||
(1, "referral", "my-volume-value-0", "103", "your-tier-0"),
|
(1, "referral", "my-volume-value-0", "103", "your-referral-tier-0"),
|
||||||
(2, "referral", "my-volume-value-1", "206", "your-tier-1"),
|
(2, "referral", "my-volume-value-1", "206", "your-referral-tier-1"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||||
@@ -439,8 +438,8 @@ def test_fees_page_discount_program_discount(
|
|||||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_0)).to_have_text("1")
|
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_0)).to_have_text("1")
|
||||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_1)).to_have_text("2")
|
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_1)).to_have_text("2")
|
||||||
|
|
||||||
expect(page.get_by_test_id(your_tier)).to_be_visible()
|
expect(page.get_by_test_id(your_tier).nth(1)).to_be_visible()
|
||||||
expect(page.get_by_test_id(your_tier)).to_have_text("Your tier")
|
expect(page.get_by_test_id(your_tier).nth(1)).to_have_text("Your tier")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@@ -461,8 +460,9 @@ def test_fees_page_discount_program_fees_by_market(
|
|||||||
vega_instance, tier, discount_program, market_ids
|
vega_instance, tier, discount_program, market_ids
|
||||||
)
|
)
|
||||||
page.goto("/#/fees")
|
page.goto("/#/fees")
|
||||||
|
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||||
row = page.locator(ROW_LOCATOR)
|
row = page.locator(ROW_LOCATOR)
|
||||||
expect(row.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text(fees_after_discount)
|
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text(fees_after_discount)
|
||||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ def test_market_selector(continuous_market, page: Page):
|
|||||||
page.get_by_test_id("header-title").click()
|
page.get_by_test_id("header-title").click()
|
||||||
# 6001-MARK-066
|
# 6001-MARK-066
|
||||||
expect(page.get_by_test_id("market-selector")).to_be_visible()
|
expect(page.get_by_test_id("market-selector")).to_be_visible()
|
||||||
|
|
||||||
# 6001-MARK-021
|
# 6001-MARK-021
|
||||||
# 6001-MARK-022
|
# 6001-MARK-022
|
||||||
# 6001-MARK-024
|
# 6001-MARK-024
|
||||||
@@ -43,7 +42,6 @@ def test_market_selector_filter(continuous_market, page: Page):
|
|||||||
page.goto(f"/#/markets/{continuous_market}")
|
page.goto(f"/#/markets/{continuous_market}")
|
||||||
page.get_by_test_id("header-title").click()
|
page.get_by_test_id("header-title").click()
|
||||||
# 6001-MARK-027
|
# 6001-MARK-027
|
||||||
|
|
||||||
page.get_by_test_id("product-Spot").click()
|
page.get_by_test_id("product-Spot").click()
|
||||||
expect(page.get_by_test_id("market-selector-list")).to_contain_text(
|
expect(page.get_by_test_id("market-selector-list")).to_contain_text(
|
||||||
"Spot markets coming soon."
|
"Spot markets coming soon."
|
||||||
|
|||||||
@@ -8,9 +8,17 @@ export const StackedCell = ({
|
|||||||
secondary: ReactNode;
|
secondary: ReactNode;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="leading-4 text-ellipsis whitespace-nowrap overflow-hidden">
|
<div className="leading-4">
|
||||||
<div data-testid="stack-cell-primary">{primary}</div>
|
<div
|
||||||
<div data-testid="stack-cell-secondary" className="text-muted">
|
className="text-ellipsis whitespace-nowrap overflow-hidden"
|
||||||
|
data-testid="stack-cell-primary"
|
||||||
|
>
|
||||||
|
{primary}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="stack-cell-secondary"
|
||||||
|
className="text-ellipsis whitespace-nowrap overflow-hidden text-muted"
|
||||||
|
>
|
||||||
{secondary}
|
{secondary}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user