226 lines
5.9 KiB
TypeScript
226 lines
5.9 KiB
TypeScript
|
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';
|
||
|
|
||
|
export const CreateCodeContainer = () => {
|
||
|
const { stakeAvailable, requiredStake } = useStakeAvailable();
|
||
|
if (stakeAvailable == null || requiredStake == null) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
<CreateCodeForm
|
||
|
currentStakeAvailable={stakeAvailable}
|
||
|
requiredStake={requiredStake}
|
||
|
/>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
export const CreateCodeForm = ({
|
||
|
currentStakeAvailable,
|
||
|
requiredStake,
|
||
|
}: {
|
||
|
currentStakeAvailable: bigint;
|
||
|
requiredStake: bigint;
|
||
|
}) => {
|
||
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||
|
const openWalletDialog = useVegaWalletDialogStore(
|
||
|
(store) => store.openVegaWalletDialog
|
||
|
);
|
||
|
const { pubKey } = useVegaWallet();
|
||
|
|
||
|
return (
|
||
|
<div className="w-1/2 mx-auto">
|
||
|
<h3 className="mb-5 text-xl text-center uppercase calt">
|
||
|
Create a referral code
|
||
|
</h3>
|
||
|
<p className="mb-6 text-center">
|
||
|
Generate a referral code to share with your friends and start earning
|
||
|
commission.
|
||
|
</p>
|
||
|
<div className="mb-5">
|
||
|
<div className="text-center">
|
||
|
<RainbowButton
|
||
|
variant="border"
|
||
|
onClick={() => {
|
||
|
if (pubKey) {
|
||
|
setDialogOpen(true);
|
||
|
} else {
|
||
|
openWalletDialog();
|
||
|
}
|
||
|
}}
|
||
|
>
|
||
|
{pubKey ? 'Create a referral code' : 'Connect wallet'}
|
||
|
</RainbowButton>
|
||
|
</div>
|
||
|
</div>
|
||
|
<Dialog
|
||
|
title="Create a referral code"
|
||
|
open={dialogOpen}
|
||
|
onChange={() => setDialogOpen(false)}
|
||
|
size="small"
|
||
|
>
|
||
|
<CreateCodeDialog
|
||
|
currentStakeAvailable={currentStakeAvailable}
|
||
|
setDialogOpen={setDialogOpen}
|
||
|
requiredStake={requiredStake}
|
||
|
/>
|
||
|
</Dialog>
|
||
|
</div>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
const CreateCodeDialog = ({
|
||
|
setDialogOpen,
|
||
|
currentStakeAvailable,
|
||
|
requiredStake,
|
||
|
}: {
|
||
|
setDialogOpen: (open: boolean) => void;
|
||
|
currentStakeAvailable: bigint;
|
||
|
requiredStake: bigint;
|
||
|
}) => {
|
||
|
const createLink = useLinks(DApp.Governance);
|
||
|
const { isReadOnly, pubKey, sendTx } = useVegaWallet();
|
||
|
const [err, setErr] = useState<string | null>(null);
|
||
|
const [code, setCode] = useState<string | null>(null);
|
||
|
const [status, setStatus] = useState<
|
||
|
'idle' | 'loading' | 'success' | 'error'
|
||
|
>('idle');
|
||
|
|
||
|
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 {
|
||
|
children: 'Generate code',
|
||
|
onClick: () => onSubmit(),
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (status === 'loading') {
|
||
|
return {
|
||
|
children: 'Confirm in wallet...',
|
||
|
disabled: true,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (status === 'success') {
|
||
|
return {
|
||
|
children: 'Close',
|
||
|
intent: Intent.Success,
|
||
|
onClick: () => setDialogOpen(false),
|
||
|
};
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// TODO: Add when network parameters are updated
|
||
|
if (
|
||
|
currentStakeAvailable === BigInt(0) ||
|
||
|
currentStakeAvailable < requiredStake
|
||
|
) {
|
||
|
return (
|
||
|
<div className="flex flex-col gap-4">
|
||
|
<p>
|
||
|
You need at least{' '}
|
||
|
{addDecimalsFormatNumber(requiredStake.toString(), 18)} VEGA staked to
|
||
|
generate a referral code and participate in the referral program.
|
||
|
</p>
|
||
|
<TradingAnchorButton
|
||
|
href={createLink(TokenStaticLinks.ASSOCIATE)}
|
||
|
intent={Intent.Primary}
|
||
|
target="_blank"
|
||
|
>
|
||
|
Stake some $VEGA now
|
||
|
</TradingAnchorButton>
|
||
|
</div>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
<div className="flex flex-col gap-4">
|
||
|
{(status === 'idle' || status === 'loading' || status === 'error') && (
|
||
|
<p>
|
||
|
Generate a referral code to share with your friends and start earning
|
||
|
commission.
|
||
|
</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>Copy</span>
|
||
|
</TradingButton>
|
||
|
</CopyWithTooltip>
|
||
|
</div>
|
||
|
)}
|
||
|
<TradingButton
|
||
|
fill={true}
|
||
|
intent={Intent.Primary}
|
||
|
{...getButtonProps()}
|
||
|
/>
|
||
|
{err && <InputError>{err}</InputError>}
|
||
|
{/* TODO: Add links */}
|
||
|
<div className="flex justify-center pt-5 mt-2 text-sm border-t gap-4 text-default border-default">
|
||
|
<ExternalLink>About the referral program</ExternalLink>
|
||
|
<ExternalLink>Disclaimer</ExternalLink>
|
||
|
</div>
|
||
|
</div>
|
||
|
);
|
||
|
};
|