chore(trading): disable apply code when applied (#4855)

This commit is contained in:
Art 2023-09-22 13:06:02 +02:00 committed by GitHub
parent 3d2b171de7
commit 41760f2956
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 142 additions and 27 deletions

View File

@ -7,13 +7,21 @@ import {
import type { FieldValues } from 'react-hook-form';
import { useForm } from 'react-hook-form';
import classNames from 'classnames';
import { useSearchParams } from 'react-router-dom';
import { useEffect, useState } from 'react';
import { Navigate, useSearchParams } from 'react-router-dom';
import { useEffect, useRef, useState } from 'react';
import { Button } from './buttons';
import { useVegaWallet } from '@vegaprotocol/wallet';
import {
useTransactionEventSubscription,
useVegaWallet,
} from '@vegaprotocol/wallet';
import { useReferral } from './hooks/use-referral';
import { Routes } from '../../lib/links';
export const ApplyCodeForm = () => {
const [finalized, setFinalized] = useState<boolean>(false);
const [status, setStatus] = useState<
'requested' | 'failed' | 'successful' | null
>(null);
const txHash = useRef<string | null>(null);
const { isReadOnly, pubKey, sendTx } = useVegaWallet();
const {
register,
@ -24,6 +32,9 @@ export const ApplyCodeForm = () => {
} = useForm();
const [params] = useSearchParams();
const { data: referee } = useReferral(pubKey, 'referee');
const { data: referrer } = useReferral(pubKey, 'referrer');
useEffect(() => {
const code = params.get('code');
if (code) setValue('code', code);
@ -34,23 +45,67 @@ export const ApplyCodeForm = () => {
return;
}
setStatus('requested');
sendTx(pubKey, {
applyReferralCode: {
id: code as string,
},
})
.then((res) => {
setFinalized(true);
if (!res) {
setError('code', {
type: 'required',
message: 'The transaction could not be sent',
});
}
if (res) {
txHash.current = res.transactionHash.toLowerCase();
}
})
.catch((err) => {
if (err.message.includes('user rejected')) {
setStatus(null);
} else {
setError('code', {
type: 'required',
message: 'Your code has been rejected',
});
}
});
};
if (finalized) {
useTransactionEventSubscription({
variables: { partyId: pubKey || '' },
skip: !pubKey,
fetchPolicy: 'no-cache',
onData: ({ data: result }) =>
result.data?.busEvents?.forEach((event) => {
if (event.event.__typename === 'TransactionResult') {
const hash = event.event.hash.toLowerCase();
if (txHash.current && txHash.current === hash) {
const err = event.event.error;
const status = event.event.status;
if (err) {
setStatus(null);
setError('code', {
type: 'required',
message: err,
});
}
if (status && !err) {
setStatus('successful');
}
}
}
}),
});
if (referee || referrer) {
return <Navigate to={Routes.REFERRALS} />;
}
if (status === 'successful') {
return (
<div className="w-1/2 mx-auto">
<h3 className="mb-5 text-xl text-center uppercase calt flex flex-row gap-2 justify-center items-center">
@ -63,6 +118,27 @@ export const ApplyCodeForm = () => {
);
}
const getButtonProps = () => {
if (isReadOnly || !pubKey) {
return {
disabled: true,
children: 'Apply',
};
}
if (status === 'requested') {
return {
disabled: true,
children: 'Confirm in wallet...',
};
}
return {
disabled: false,
children: 'Apply',
};
};
return (
<div className="w-1/2 mx-auto">
<h3 className="mb-5 text-xl text-center uppercase calt">
@ -86,13 +162,7 @@ export const ApplyCodeForm = () => {
})}
/>
</label>
<Button
disabled={isReadOnly || !pubKey}
className="w-full"
type="submit"
>
Apply
</Button>
<Button className="w-full" type="submit" {...getButtonProps()} />
</form>
{errors.code && (
<InputError>{errors.code.message?.toString()}</InputError>

View File

@ -38,18 +38,36 @@ export const RainbowButton = ({
const RAINBOW_TAB_STYLE = classNames(
'inline-block',
'bg-vega-clight-500 dark:bg-vega-cdark-500 hover:bg-vega-clight-400 dark:hover:bg-vega-cdark-400',
'data-[state="active"]:text-white data-[state="active"]:bg-rainbow data-[state="active"]:hover:bg-none data-[state="active"]:hover:bg-vega-pink-500 dark:data-[state="active"]:hover:bg-vega-pink-500',
'[&.active]:text-white [&.active]:bg-rainbow [&.active]:hover:bg-none [&.active]:hover:bg-vega-pink-500 dark:[&.active]:hover:bg-vega-pink-500',
'bg-vega-clight-500 dark:bg-vega-cdark-500',
'hover:bg-vega-clight-400 dark:hover:bg-vega-cdark-400',
'data-[state="active"]:text-white data-[state="active"]:bg-rainbow',
'data-[state="active"]:hover:bg-none data-[state="active"]:hover:bg-vega-pink-500 dark:data-[state="active"]:hover:bg-vega-pink-500',
'[&.active]:text-white [&.active]:bg-rainbow',
'[&.active]:hover:bg-none [&.active]:hover:bg-vega-pink-500 dark:[&.active]:hover:bg-vega-pink-500',
'px-5 py-3',
'first:rounded-tl-lg last:rounded-tr-lg'
);
const DISABLED_RAINBOW_TAB_STYLE = classNames(
'pointer-events-none',
'text-vega-clight-100 dark:text-vega-cdark-100',
'data-[state="active"]:text-white',
'[&.active]:text-white'
);
export const RainbowTabButton = forwardRef<
HTMLButtonElement,
ButtonHTMLAttributes<HTMLButtonElement>
>(({ children, ...props }, ref) => (
<button ref={ref} className={RAINBOW_TAB_STYLE} {...props}>
{ disabled?: boolean } & ButtonHTMLAttributes<HTMLButtonElement>
>(({ children, className, disabled = false, ...props }, ref) => (
<button
ref={ref}
className={classNames(
RAINBOW_TAB_STYLE,
{ 'pointer-events-none': disabled },
className
)}
{...props}
>
{children}
</button>
));
@ -58,9 +76,19 @@ RainbowTabButton.displayName = 'RainbowTabButton';
export const RainbowTabLink = ({
to,
children,
className,
disabled = false,
...props
}: ComponentProps<typeof NavLink>) => (
<NavLink to={to} className={RAINBOW_TAB_STYLE} {...props}>
}: { disabled?: boolean } & ComponentProps<typeof NavLink>) => (
<NavLink
to={to}
className={classNames(
RAINBOW_TAB_STYLE,
disabled && DISABLED_RAINBOW_TAB_STYLE,
typeof className === 'string' ? className : undefined
)}
{...props}
>
{children}
</NavLink>
);

View File

@ -9,8 +9,14 @@ import { TiersContainer } from './tiers';
import { RainbowTabLink } from './buttons';
import { Outlet } from 'react-router-dom';
import { Routes } from '../../lib/links';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useReferral } from './hooks/use-referral';
export const Referrals = () => {
const { pubKey } = useVegaWallet();
const { data: referee } = useReferral(pubKey, 'referee');
const { data: referrer } = useReferral(pubKey, 'referrer');
return (
<>
<LandingBanner />
@ -19,7 +25,10 @@ export const Referrals = () => {
<RainbowTabLink end to={Routes.REFERRALS}>
Your referrals
</RainbowTabLink>
<RainbowTabLink to={Routes.REFERRALS_APPLY_CODE}>
<RainbowTabLink
disabled={Boolean(referee || referrer)}
to={Routes.REFERRALS_APPLY_CODE}
>
Apply a code
</RainbowTabLink>
</div>

View File

@ -465,6 +465,11 @@ export const isTransferTransaction = (
transaction: Transaction
): transaction is TransferBody => 'transfer' in transaction;
export const isReferralRelatedTransaction = (
transaction: Transaction
): transaction is CreateReferralSet | ApplyReferralCode =>
'createReferralSet' in transaction || 'applyReferralCode' in transaction;
export interface TransactionResponse {
transactionHash: string;
signature: string; // still to be added by core

View File

@ -25,6 +25,7 @@ import {
VegaTxStatus,
isStopOrdersSubmissionTransaction,
isStopOrdersCancellationTransaction,
isReferralRelatedTransaction,
} from '@vegaprotocol/wallet';
import type { Toast, ToastContent } from '@vegaprotocol/ui-toolkit';
import { ToastHeading } from '@vegaprotocol/ui-toolkit';
@ -97,6 +98,7 @@ const isTransactionTypeSupported = (tx: VegaStoredTxState) => {
const editOrder = isOrderAmendmentTransaction(tx.body);
const batchMarketInstructions = isBatchMarketInstructionsTransaction(tx.body);
const transfer = isTransferTransaction(tx.body);
const referral = isReferralRelatedTransaction(tx.body);
return (
withdraw ||
submitOrder ||
@ -105,7 +107,8 @@ const isTransactionTypeSupported = (tx: VegaStoredTxState) => {
cancelStopOrder ||
editOrder ||
batchMarketInstructions ||
transfer
transfer ||
referral
);
};