2023-09-21 13:25:19 +00:00
|
|
|
import {
|
|
|
|
useVegaWallet,
|
|
|
|
useVegaWalletDialogStore,
|
|
|
|
determineId,
|
|
|
|
} from '@vegaprotocol/wallet';
|
|
|
|
import { RainbowButton } from './buttons';
|
|
|
|
import { useState } from 'react';
|
|
|
|
import {
|
|
|
|
CopyWithTooltip,
|
|
|
|
Dialog,
|
|
|
|
ExternalLink,
|
|
|
|
InputError,
|
|
|
|
Intent,
|
|
|
|
TradingAnchorButton,
|
|
|
|
TradingButton,
|
|
|
|
VegaIcon,
|
|
|
|
VegaIconNames,
|
|
|
|
} from '@vegaprotocol/ui-toolkit';
|
|
|
|
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
|
|
|
import { DApp, TokenStaticLinks, useLinks } from '@vegaprotocol/environment';
|
|
|
|
import { useStakeAvailable } from './hooks/use-stake-available';
|
2023-12-06 17:51:39 +00:00
|
|
|
import { ABOUT_REFERRAL_DOCS_LINK } from './constants';
|
|
|
|
import { useIsInReferralSet, useReferral } from './hooks/use-referral';
|
2023-11-16 03:10:39 +00:00
|
|
|
import { useT } from '../../lib/use-t';
|
2023-12-06 17:51:39 +00:00
|
|
|
import { Navigate } from 'react-router-dom';
|
|
|
|
import { Routes } from '../../lib/links';
|
|
|
|
import { useReferralProgram } from './hooks/use-referral-program';
|
2023-09-21 13:25:19 +00:00
|
|
|
|
|
|
|
export const CreateCodeContainer = () => {
|
2023-12-06 17:51:39 +00:00
|
|
|
const { pubKey } = useVegaWallet();
|
|
|
|
const isInReferralSet = useIsInReferralSet(pubKey);
|
|
|
|
|
|
|
|
// Navigate to the index page when already in the referral set.
|
|
|
|
if (isInReferralSet) {
|
|
|
|
return <Navigate to={Routes.REFERRALS} />;
|
|
|
|
}
|
|
|
|
|
2023-10-23 14:57:18 +00:00
|
|
|
return <CreateCodeForm />;
|
2023-09-21 13:25:19 +00:00
|
|
|
};
|
|
|
|
|
2023-10-23 14:57:18 +00:00
|
|
|
export const CreateCodeForm = () => {
|
2023-11-16 03:10:39 +00:00
|
|
|
const t = useT();
|
2023-09-21 13:25:19 +00:00
|
|
|
const [dialogOpen, setDialogOpen] = useState(false);
|
|
|
|
const openWalletDialog = useVegaWalletDialogStore(
|
|
|
|
(store) => store.openVegaWalletDialog
|
|
|
|
);
|
2023-10-23 14:57:18 +00:00
|
|
|
const { pubKey, isReadOnly } = useVegaWallet();
|
2023-09-21 13:25:19 +00:00
|
|
|
|
|
|
|
return (
|
2023-11-28 15:08:21 +00:00
|
|
|
<div
|
|
|
|
data-testid="referral-create-code-form"
|
2024-01-02 15:50:04 +00:00
|
|
|
className="md:w-2/3 max-w-md mx-auto bg-vega-clight-800 dark:bg-vega-cdark-800 p-8 rounded-lg"
|
2023-11-28 15:08:21 +00:00
|
|
|
>
|
2023-10-24 15:43:33 +00:00
|
|
|
<h3 className="mb-4 text-2xl text-center calt">
|
|
|
|
{t('Create a referral code')}
|
|
|
|
</h3>
|
2023-10-23 14:57:18 +00:00
|
|
|
<p className="mb-4 text-center text-base">
|
2023-10-24 15:43:33 +00:00
|
|
|
{t(
|
2023-12-06 17:51:39 +00:00
|
|
|
'Generate a referral code to share with your friends and access the commission benefits of the current program.'
|
2023-10-24 15:43:33 +00:00
|
|
|
)}
|
2023-09-21 13:25:19 +00:00
|
|
|
</p>
|
2023-10-23 14:57:18 +00:00
|
|
|
|
|
|
|
<div className="w-full flex flex-col">
|
|
|
|
<RainbowButton
|
|
|
|
variant="border"
|
|
|
|
disabled={isReadOnly}
|
|
|
|
onClick={() => {
|
|
|
|
if (pubKey) {
|
|
|
|
setDialogOpen(true);
|
|
|
|
} else {
|
|
|
|
openWalletDialog();
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
>
|
2023-10-24 15:43:33 +00:00
|
|
|
{pubKey ? t('Create a referral code') : t('Connect wallet')}
|
2023-10-23 14:57:18 +00:00
|
|
|
</RainbowButton>
|
2023-09-21 13:25:19 +00:00
|
|
|
</div>
|
2023-10-23 14:57:18 +00:00
|
|
|
|
2023-09-21 13:25:19 +00:00
|
|
|
<Dialog
|
2023-10-24 15:43:33 +00:00
|
|
|
title={t('Create a referral code')}
|
2023-09-21 13:25:19 +00:00
|
|
|
open={dialogOpen}
|
|
|
|
onChange={() => setDialogOpen(false)}
|
|
|
|
size="small"
|
|
|
|
>
|
2023-10-23 14:57:18 +00:00
|
|
|
<CreateCodeDialog setDialogOpen={setDialogOpen} />
|
2023-09-21 13:25:19 +00:00
|
|
|
</Dialog>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const CreateCodeDialog = ({
|
|
|
|
setDialogOpen,
|
|
|
|
}: {
|
|
|
|
setDialogOpen: (open: boolean) => void;
|
|
|
|
}) => {
|
2023-11-16 03:10:39 +00:00
|
|
|
const t = useT();
|
2023-09-21 13:25:19 +00:00
|
|
|
const createLink = useLinks(DApp.Governance);
|
|
|
|
const { isReadOnly, pubKey, sendTx } = useVegaWallet();
|
2023-10-23 14:57:18 +00:00
|
|
|
const { refetch } = useReferral({ pubKey, role: 'referrer' });
|
2023-09-21 13:25:19 +00:00
|
|
|
const [err, setErr] = useState<string | null>(null);
|
|
|
|
const [code, setCode] = useState<string | null>(null);
|
|
|
|
const [status, setStatus] = useState<
|
|
|
|
'idle' | 'loading' | 'success' | 'error'
|
|
|
|
>('idle');
|
|
|
|
|
2023-10-23 14:57:18 +00:00
|
|
|
const { stakeAvailable: currentStakeAvailable, requiredStake } =
|
|
|
|
useStakeAvailable();
|
|
|
|
|
2023-12-06 17:51:39 +00:00
|
|
|
const { details: programDetails } = useReferralProgram();
|
2023-11-23 17:08:26 +00:00
|
|
|
|
2023-09-21 13:25:19 +00:00
|
|
|
const onSubmit = () => {
|
|
|
|
if (isReadOnly || !pubKey) {
|
|
|
|
setErr('Not connected');
|
|
|
|
} else {
|
|
|
|
setErr(null);
|
|
|
|
setStatus('loading');
|
|
|
|
setCode(null);
|
|
|
|
sendTx(pubKey, {
|
|
|
|
createReferralSet: {
|
|
|
|
isTeam: false,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
if (!res) {
|
|
|
|
setErr(`Invalid response: ${JSON.stringify(res)}`);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const code = determineId(res.signature);
|
|
|
|
setCode(code);
|
|
|
|
setStatus('success');
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
if (err.message.includes('user rejected')) {
|
|
|
|
setStatus('idle');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setStatus('error');
|
|
|
|
setErr(err.message);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const getButtonProps = () => {
|
|
|
|
if (status === 'idle' || status === 'error') {
|
|
|
|
return {
|
2023-10-24 15:43:33 +00:00
|
|
|
children: t('Generate code'),
|
2023-09-21 13:25:19 +00:00
|
|
|
onClick: () => onSubmit(),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status === 'loading') {
|
|
|
|
return {
|
2023-10-24 15:43:33 +00:00
|
|
|
children: t('Confirm in wallet...'),
|
2023-09-21 13:25:19 +00:00
|
|
|
disabled: true,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status === 'success') {
|
|
|
|
return {
|
2023-10-24 15:43:33 +00:00
|
|
|
children: t('Close'),
|
2023-09-21 13:25:19 +00:00
|
|
|
intent: Intent.Success,
|
2023-10-23 14:57:18 +00:00
|
|
|
onClick: () => {
|
|
|
|
refetch();
|
|
|
|
setDialogOpen(false);
|
|
|
|
},
|
2023-09-21 13:25:19 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-10-23 14:57:18 +00:00
|
|
|
if (!pubKey || currentStakeAvailable == null || requiredStake == null) {
|
|
|
|
return (
|
|
|
|
<div className="flex flex-col gap-4">
|
2023-10-24 15:43:33 +00:00
|
|
|
<p>{t('You must be connected to the Vega wallet.')}</p>
|
2023-10-23 14:57:18 +00:00
|
|
|
<TradingButton
|
|
|
|
intent={Intent.Primary}
|
|
|
|
onClick={() => setDialogOpen(false)}
|
|
|
|
>
|
2023-10-24 15:43:33 +00:00
|
|
|
{t('Close')}
|
2023-10-23 14:57:18 +00:00
|
|
|
</TradingButton>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentStakeAvailable < requiredStake) {
|
2023-09-21 13:25:19 +00:00
|
|
|
return (
|
|
|
|
<div className="flex flex-col gap-4">
|
|
|
|
<p>
|
2023-10-24 15:43:33 +00:00
|
|
|
{t(
|
2023-11-16 03:10:39 +00:00
|
|
|
'You need at least {{requiredStake}} VEGA staked to generate a referral code and participate in the referral program.',
|
|
|
|
{
|
|
|
|
requiredStake: addDecimalsFormatNumber(
|
|
|
|
requiredStake.toString(),
|
|
|
|
18
|
|
|
|
),
|
|
|
|
}
|
2023-10-24 15:43:33 +00:00
|
|
|
)}
|
2023-09-21 13:25:19 +00:00
|
|
|
</p>
|
|
|
|
<TradingAnchorButton
|
|
|
|
href={createLink(TokenStaticLinks.ASSOCIATE)}
|
|
|
|
intent={Intent.Primary}
|
|
|
|
target="_blank"
|
|
|
|
>
|
2023-10-24 15:43:33 +00:00
|
|
|
{t('Stake some $VEGA now')}
|
2023-09-21 13:25:19 +00:00
|
|
|
</TradingAnchorButton>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-12-06 17:51:39 +00:00
|
|
|
if (!programDetails) {
|
2023-11-23 17:08:26 +00:00
|
|
|
return (
|
|
|
|
<div className="flex flex-col gap-4">
|
|
|
|
{(status === 'idle' || status === 'loading' || status === 'error') && (
|
|
|
|
<>
|
|
|
|
{
|
|
|
|
<p>
|
|
|
|
{t(
|
|
|
|
'There is currently no referral program active, are you sure you want to create a code?'
|
|
|
|
)}
|
|
|
|
</p>
|
|
|
|
}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
{status === 'success' && code && (
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
<div className="flex-1 min-w-0 p-2 text-sm rounded bg-vega-clight-700 dark:bg-vega-cdark-700">
|
|
|
|
<p className="overflow-hidden whitespace-nowrap text-ellipsis">
|
|
|
|
{code}
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<CopyWithTooltip text={code}>
|
|
|
|
<TradingButton
|
|
|
|
className="text-sm no-underline"
|
|
|
|
icon={<VegaIcon name={VegaIconNames.COPY} />}
|
|
|
|
>
|
|
|
|
<span>{t('Copy')}</span>
|
|
|
|
</TradingButton>
|
|
|
|
</CopyWithTooltip>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
<TradingButton
|
|
|
|
fill={true}
|
|
|
|
intent={Intent.Primary}
|
|
|
|
onClick={() => onSubmit()}
|
|
|
|
{...getButtonProps()}
|
2023-12-06 17:51:39 +00:00
|
|
|
>
|
|
|
|
{t('Yes')}
|
|
|
|
</TradingButton>
|
2023-11-23 17:08:26 +00:00
|
|
|
{status === 'idle' && (
|
|
|
|
<TradingButton
|
|
|
|
fill={true}
|
|
|
|
intent={Intent.Primary}
|
|
|
|
onClick={() => {
|
|
|
|
refetch();
|
|
|
|
setDialogOpen(false);
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{t('No')}
|
|
|
|
</TradingButton>
|
|
|
|
)}
|
|
|
|
{err && <InputError>{err}</InputError>}
|
|
|
|
<div className="flex justify-center pt-5 mt-2 text-sm border-t gap-4 text-default border-default">
|
|
|
|
<ExternalLink href={ABOUT_REFERRAL_DOCS_LINK}>
|
|
|
|
{t('About the referral program')}
|
|
|
|
</ExternalLink>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-09-21 13:25:19 +00:00
|
|
|
return (
|
|
|
|
<div className="flex flex-col gap-4">
|
|
|
|
{(status === 'idle' || status === 'loading' || status === 'error') && (
|
|
|
|
<p>
|
2023-10-24 15:43:33 +00:00
|
|
|
{t(
|
2023-12-06 17:51:39 +00:00
|
|
|
'Generate a referral code to share with your friends and access the commission benefits of the current program.'
|
2023-10-24 15:43:33 +00:00
|
|
|
)}
|
2023-09-21 13:25:19 +00:00
|
|
|
</p>
|
|
|
|
)}
|
|
|
|
{status === 'success' && code && (
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
<div className="flex-1 min-w-0 p-2 text-sm rounded bg-vega-clight-700 dark:bg-vega-cdark-700">
|
|
|
|
<p className="overflow-hidden whitespace-nowrap text-ellipsis">
|
|
|
|
{code}
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<CopyWithTooltip text={code}>
|
|
|
|
<TradingButton
|
|
|
|
className="text-sm no-underline"
|
|
|
|
icon={<VegaIcon name={VegaIconNames.COPY} />}
|
|
|
|
>
|
2023-10-24 15:43:33 +00:00
|
|
|
<span>{t('Copy')}</span>
|
2023-09-21 13:25:19 +00:00
|
|
|
</TradingButton>
|
|
|
|
</CopyWithTooltip>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
<TradingButton
|
|
|
|
fill={true}
|
|
|
|
intent={Intent.Primary}
|
|
|
|
{...getButtonProps()}
|
|
|
|
/>
|
|
|
|
{err && <InputError>{err}</InputError>}
|
|
|
|
<div className="flex justify-center pt-5 mt-2 text-sm border-t gap-4 text-default border-default">
|
2023-10-23 14:57:18 +00:00
|
|
|
<ExternalLink href={ABOUT_REFERRAL_DOCS_LINK}>
|
2023-10-24 15:43:33 +00:00
|
|
|
{t('About the referral program')}
|
2023-10-23 14:57:18 +00:00
|
|
|
</ExternalLink>
|
2023-09-21 13:25:19 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|