2023-09-21 13:25:19 +00:00
|
|
|
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
|
|
|
import { useReferralProgram } from './hooks/use-referral-program';
|
|
|
|
import { Table } from './table';
|
|
|
|
import classNames from 'classnames';
|
|
|
|
import { BORDER_COLOR, GRADIENT } from './constants';
|
|
|
|
import { Tag } from './tag';
|
2023-10-23 14:57:18 +00:00
|
|
|
import type { ComponentProps, ReactNode } from 'react';
|
|
|
|
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
|
|
|
import { DApp, TOKEN_PROPOSALS, useLinks } from '@vegaprotocol/environment';
|
2023-09-21 13:25:19 +00:00
|
|
|
|
|
|
|
const Loading = ({ variant }: { variant: 'large' | 'inline' }) => (
|
|
|
|
<div
|
|
|
|
className={classNames(
|
|
|
|
'bg-vega-clight-800 dark:bg-vega-cdark-800 rounded-lg animate-pulse',
|
|
|
|
{
|
|
|
|
'w-full h-20': variant === 'large',
|
|
|
|
}
|
|
|
|
)}
|
|
|
|
></div>
|
|
|
|
);
|
|
|
|
|
|
|
|
const StakingTier = ({
|
|
|
|
tier,
|
|
|
|
label,
|
|
|
|
referralRewardMultiplier,
|
|
|
|
minimumStakedTokens,
|
|
|
|
}: {
|
|
|
|
tier: number;
|
|
|
|
label: string;
|
|
|
|
referralRewardMultiplier: string;
|
|
|
|
minimumStakedTokens: string;
|
|
|
|
}) => {
|
|
|
|
const color: Record<number, ComponentProps<typeof Tag>['color']> = {
|
|
|
|
1: 'green',
|
|
|
|
2: 'blue',
|
|
|
|
3: 'pink',
|
|
|
|
};
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className={classNames(
|
|
|
|
'overflow-hidden',
|
|
|
|
'border rounded-md w-full',
|
2023-10-23 14:57:18 +00:00
|
|
|
'flex flex-row',
|
|
|
|
GRADIENT,
|
2023-09-21 13:25:19 +00:00
|
|
|
BORDER_COLOR
|
|
|
|
)}
|
|
|
|
>
|
2023-10-23 14:57:18 +00:00
|
|
|
<div aria-hidden className="max-w-[120px]">
|
2023-09-21 13:25:19 +00:00
|
|
|
{tier < 4 && (
|
|
|
|
// eslint-disable-next-line @next/next/no-img-element
|
|
|
|
<img
|
|
|
|
src={`/${tier}x.png`}
|
|
|
|
alt={`${referralRewardMultiplier}x multiplier`}
|
2023-10-23 14:57:18 +00:00
|
|
|
width={240}
|
|
|
|
height={240}
|
|
|
|
className="w-full h-full"
|
2023-09-21 13:25:19 +00:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</div>
|
2023-10-23 14:57:18 +00:00
|
|
|
<div className={classNames('p-3')}>
|
|
|
|
<Tag color={color[tier]}>Multiplier {referralRewardMultiplier}x</Tag>
|
|
|
|
<h3 className="mt-1 mb-1 text-base">{label}</h3>
|
|
|
|
<p className="text-sm text-vega-clight-100 dark:text-vega-cdark-100">
|
2023-09-21 13:25:19 +00:00
|
|
|
Stake a minimum of {minimumStakedTokens} $VEGA tokens
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const TiersContainer = () => {
|
2023-10-23 14:57:18 +00:00
|
|
|
const { benefitTiers, stakingTiers, details, loading, error } =
|
|
|
|
useReferralProgram();
|
2023-09-21 13:25:19 +00:00
|
|
|
|
|
|
|
const ends = details?.endOfProgramTimestamp
|
|
|
|
? getDateTimeFormat().format(new Date(details.endOfProgramTimestamp))
|
|
|
|
: undefined;
|
|
|
|
|
2023-10-23 14:57:18 +00:00
|
|
|
const governanceLink = useLinks(DApp.Governance);
|
|
|
|
|
|
|
|
if ((!loading && !details) || error) {
|
|
|
|
return (
|
|
|
|
<div className="text-base px-5 py-10 text-center">
|
|
|
|
We're sorry but we don't have an active referral programme
|
|
|
|
currently running. You can propose a new programme{' '}
|
|
|
|
<ExternalLink href={governanceLink(TOKEN_PROPOSALS)}>here</ExternalLink>
|
|
|
|
.
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-09-21 13:25:19 +00:00
|
|
|
return (
|
|
|
|
<>
|
2023-10-23 14:57:18 +00:00
|
|
|
{/* Benefit tiers */}
|
|
|
|
<div className="flex flex-col items-baseline justify-between mt-10 mb-5">
|
2023-09-21 13:25:19 +00:00
|
|
|
<h2 className="text-2xl">Referral tiers</h2>
|
|
|
|
{ends && (
|
2023-10-23 14:57:18 +00:00
|
|
|
<span className="text-sm text-vega-clight-200 dark:text-vega-cdark-200">
|
|
|
|
Program ends: {ends}
|
2023-09-21 13:25:19 +00:00
|
|
|
</span>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
<div className="mb-20">
|
|
|
|
{loading || !benefitTiers || benefitTiers.length === 0 ? (
|
|
|
|
<Loading variant="large" />
|
|
|
|
) : (
|
2023-10-23 14:57:18 +00:00
|
|
|
<TiersTable
|
|
|
|
data={benefitTiers.map((bt) => ({
|
|
|
|
...bt,
|
|
|
|
tierElement: (
|
|
|
|
<div className="rounded-full bg-vega-clight-900 dark:bg-vega-cdark-900 p-1 w-8 h-8 text-center">
|
|
|
|
{bt.tier}
|
|
|
|
</div>
|
|
|
|
),
|
|
|
|
}))}
|
|
|
|
/>
|
2023-09-21 13:25:19 +00:00
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
|
2023-10-23 14:57:18 +00:00
|
|
|
{/* Staking tiers */}
|
2023-09-21 13:25:19 +00:00
|
|
|
<div className="flex flex-row items-baseline justify-between mb-5">
|
|
|
|
<h2 className="text-2xl">Staking multipliers</h2>
|
|
|
|
</div>
|
2023-10-23 14:57:18 +00:00
|
|
|
<div className="mb-20 flex flex-col justify-items-stretch lg:flex-row gap-5">
|
2023-09-21 13:25:19 +00:00
|
|
|
{loading || !stakingTiers || stakingTiers.length === 0 ? (
|
|
|
|
<>
|
|
|
|
<Loading variant="large" />
|
|
|
|
<Loading variant="large" />
|
|
|
|
<Loading variant="large" />
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<StakingTiers data={stakingTiers} />
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const StakingTiers = ({
|
|
|
|
data,
|
|
|
|
}: {
|
|
|
|
data: ReturnType<typeof useReferralProgram>['stakingTiers'];
|
|
|
|
}) => (
|
|
|
|
<>
|
|
|
|
{data.map(
|
|
|
|
({ tier, label, referralRewardMultiplier, minimumStakedTokens }, i) => (
|
|
|
|
<StakingTier
|
|
|
|
key={i}
|
|
|
|
tier={tier}
|
|
|
|
label={label}
|
|
|
|
referralRewardMultiplier={referralRewardMultiplier}
|
|
|
|
minimumStakedTokens={minimumStakedTokens}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
|
|
|
|
const TiersTable = ({
|
|
|
|
data,
|
|
|
|
}: {
|
|
|
|
data: Array<{
|
|
|
|
tier: number;
|
2023-10-23 14:57:18 +00:00
|
|
|
tierElement: ReactNode;
|
2023-09-21 13:25:19 +00:00
|
|
|
commission: string;
|
|
|
|
discount: string;
|
|
|
|
volume: string;
|
|
|
|
}>;
|
|
|
|
}) => {
|
|
|
|
return (
|
|
|
|
<Table
|
|
|
|
columns={[
|
2023-10-23 14:57:18 +00:00
|
|
|
{ name: 'tierElement', displayName: 'Tier' },
|
2023-09-21 13:25:19 +00:00
|
|
|
{
|
|
|
|
name: 'commission',
|
|
|
|
displayName: 'Referrer commission',
|
|
|
|
tooltip: 'A percentage of commission earned by the referrer',
|
|
|
|
},
|
|
|
|
{ name: 'discount', displayName: 'Referrer trading discount' },
|
|
|
|
{ name: 'volume', displayName: 'Min. trading volume' },
|
2023-10-23 14:57:18 +00:00
|
|
|
{ name: 'epochs', displayName: 'Min. epochs' },
|
2023-09-21 13:25:19 +00:00
|
|
|
]}
|
|
|
|
data={data.map((d) => ({
|
|
|
|
...d,
|
|
|
|
className: classNames({
|
|
|
|
'from-vega-pink-400 dark:from-vega-pink-600 to-20% bg-highlight':
|
|
|
|
d.tier === 1,
|
|
|
|
'from-vega-purple-400 dark:from-vega-purple-600 to-20% bg-highlight':
|
|
|
|
d.tier === 2,
|
|
|
|
'from-vega-blue-400 dark:from-vega-blue-600 to-20% bg-highlight':
|
|
|
|
d.tier === 3,
|
|
|
|
'from-vega-orange-400 dark:from-vega-orange-600 to-20% bg-highlight':
|
|
|
|
d.tier > 3,
|
|
|
|
}),
|
|
|
|
}))}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
};
|