chore(trading): disable apply code when applied (#4855)
This commit is contained in:
parent
3d2b171de7
commit
41760f2956
@ -7,13 +7,21 @@ import {
|
|||||||
import type { FieldValues } from 'react-hook-form';
|
import type { FieldValues } from 'react-hook-form';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { Navigate, useSearchParams } from 'react-router-dom';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { Button } from './buttons';
|
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 = () => {
|
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 { isReadOnly, pubKey, sendTx } = useVegaWallet();
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
@ -24,6 +32,9 @@ export const ApplyCodeForm = () => {
|
|||||||
} = useForm();
|
} = useForm();
|
||||||
const [params] = useSearchParams();
|
const [params] = useSearchParams();
|
||||||
|
|
||||||
|
const { data: referee } = useReferral(pubKey, 'referee');
|
||||||
|
const { data: referrer } = useReferral(pubKey, 'referrer');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const code = params.get('code');
|
const code = params.get('code');
|
||||||
if (code) setValue('code', code);
|
if (code) setValue('code', code);
|
||||||
@ -34,23 +45,67 @@ export const ApplyCodeForm = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setStatus('requested');
|
||||||
|
|
||||||
sendTx(pubKey, {
|
sendTx(pubKey, {
|
||||||
applyReferralCode: {
|
applyReferralCode: {
|
||||||
id: code as string,
|
id: code as string,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.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) => {
|
.catch((err) => {
|
||||||
|
if (err.message.includes('user rejected')) {
|
||||||
|
setStatus(null);
|
||||||
|
} else {
|
||||||
setError('code', {
|
setError('code', {
|
||||||
type: 'required',
|
type: 'required',
|
||||||
message: 'Your code has been rejected',
|
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 (
|
return (
|
||||||
<div className="w-1/2 mx-auto">
|
<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">
|
<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 (
|
return (
|
||||||
<div className="w-1/2 mx-auto">
|
<div className="w-1/2 mx-auto">
|
||||||
<h3 className="mb-5 text-xl text-center uppercase calt">
|
<h3 className="mb-5 text-xl text-center uppercase calt">
|
||||||
@ -86,13 +162,7 @@ export const ApplyCodeForm = () => {
|
|||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<Button
|
<Button className="w-full" type="submit" {...getButtonProps()} />
|
||||||
disabled={isReadOnly || !pubKey}
|
|
||||||
className="w-full"
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
Apply
|
|
||||||
</Button>
|
|
||||||
</form>
|
</form>
|
||||||
{errors.code && (
|
{errors.code && (
|
||||||
<InputError>{errors.code.message?.toString()}</InputError>
|
<InputError>{errors.code.message?.toString()}</InputError>
|
||||||
|
@ -38,18 +38,36 @@ export const RainbowButton = ({
|
|||||||
|
|
||||||
const RAINBOW_TAB_STYLE = classNames(
|
const RAINBOW_TAB_STYLE = classNames(
|
||||||
'inline-block',
|
'inline-block',
|
||||||
'bg-vega-clight-500 dark:bg-vega-cdark-500 hover:bg-vega-clight-400 dark:hover:bg-vega-cdark-400',
|
'bg-vega-clight-500 dark:bg-vega-cdark-500',
|
||||||
'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',
|
'hover:bg-vega-clight-400 dark:hover:bg-vega-cdark-400',
|
||||||
'[&.active]:text-white [&.active]:bg-rainbow [&.active]:hover:bg-none [&.active]:hover:bg-vega-pink-500 dark:[&.active]:hover:bg-vega-pink-500',
|
'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',
|
'px-5 py-3',
|
||||||
'first:rounded-tl-lg last:rounded-tr-lg'
|
'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<
|
export const RainbowTabButton = forwardRef<
|
||||||
HTMLButtonElement,
|
HTMLButtonElement,
|
||||||
ButtonHTMLAttributes<HTMLButtonElement>
|
{ disabled?: boolean } & ButtonHTMLAttributes<HTMLButtonElement>
|
||||||
>(({ children, ...props }, ref) => (
|
>(({ children, className, disabled = false, ...props }, ref) => (
|
||||||
<button ref={ref} className={RAINBOW_TAB_STYLE} {...props}>
|
<button
|
||||||
|
ref={ref}
|
||||||
|
className={classNames(
|
||||||
|
RAINBOW_TAB_STYLE,
|
||||||
|
{ 'pointer-events-none': disabled },
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</button>
|
</button>
|
||||||
));
|
));
|
||||||
@ -58,9 +76,19 @@ RainbowTabButton.displayName = 'RainbowTabButton';
|
|||||||
export const RainbowTabLink = ({
|
export const RainbowTabLink = ({
|
||||||
to,
|
to,
|
||||||
children,
|
children,
|
||||||
|
className,
|
||||||
|
disabled = false,
|
||||||
...props
|
...props
|
||||||
}: ComponentProps<typeof NavLink>) => (
|
}: { disabled?: boolean } & ComponentProps<typeof NavLink>) => (
|
||||||
<NavLink to={to} className={RAINBOW_TAB_STYLE} {...props}>
|
<NavLink
|
||||||
|
to={to}
|
||||||
|
className={classNames(
|
||||||
|
RAINBOW_TAB_STYLE,
|
||||||
|
disabled && DISABLED_RAINBOW_TAB_STYLE,
|
||||||
|
typeof className === 'string' ? className : undefined
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
);
|
);
|
||||||
|
@ -9,8 +9,14 @@ import { TiersContainer } from './tiers';
|
|||||||
import { RainbowTabLink } from './buttons';
|
import { RainbowTabLink } from './buttons';
|
||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet } from 'react-router-dom';
|
||||||
import { Routes } from '../../lib/links';
|
import { Routes } from '../../lib/links';
|
||||||
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
|
import { useReferral } from './hooks/use-referral';
|
||||||
|
|
||||||
export const Referrals = () => {
|
export const Referrals = () => {
|
||||||
|
const { pubKey } = useVegaWallet();
|
||||||
|
const { data: referee } = useReferral(pubKey, 'referee');
|
||||||
|
const { data: referrer } = useReferral(pubKey, 'referrer');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<LandingBanner />
|
<LandingBanner />
|
||||||
@ -19,7 +25,10 @@ export const Referrals = () => {
|
|||||||
<RainbowTabLink end to={Routes.REFERRALS}>
|
<RainbowTabLink end to={Routes.REFERRALS}>
|
||||||
Your referrals
|
Your referrals
|
||||||
</RainbowTabLink>
|
</RainbowTabLink>
|
||||||
<RainbowTabLink to={Routes.REFERRALS_APPLY_CODE}>
|
<RainbowTabLink
|
||||||
|
disabled={Boolean(referee || referrer)}
|
||||||
|
to={Routes.REFERRALS_APPLY_CODE}
|
||||||
|
>
|
||||||
Apply a code
|
Apply a code
|
||||||
</RainbowTabLink>
|
</RainbowTabLink>
|
||||||
</div>
|
</div>
|
||||||
|
@ -465,6 +465,11 @@ export const isTransferTransaction = (
|
|||||||
transaction: Transaction
|
transaction: Transaction
|
||||||
): transaction is TransferBody => 'transfer' in 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 {
|
export interface TransactionResponse {
|
||||||
transactionHash: string;
|
transactionHash: string;
|
||||||
signature: string; // still to be added by core
|
signature: string; // still to be added by core
|
||||||
|
@ -25,6 +25,7 @@ import {
|
|||||||
VegaTxStatus,
|
VegaTxStatus,
|
||||||
isStopOrdersSubmissionTransaction,
|
isStopOrdersSubmissionTransaction,
|
||||||
isStopOrdersCancellationTransaction,
|
isStopOrdersCancellationTransaction,
|
||||||
|
isReferralRelatedTransaction,
|
||||||
} from '@vegaprotocol/wallet';
|
} from '@vegaprotocol/wallet';
|
||||||
import type { Toast, ToastContent } from '@vegaprotocol/ui-toolkit';
|
import type { Toast, ToastContent } from '@vegaprotocol/ui-toolkit';
|
||||||
import { ToastHeading } from '@vegaprotocol/ui-toolkit';
|
import { ToastHeading } from '@vegaprotocol/ui-toolkit';
|
||||||
@ -97,6 +98,7 @@ const isTransactionTypeSupported = (tx: VegaStoredTxState) => {
|
|||||||
const editOrder = isOrderAmendmentTransaction(tx.body);
|
const editOrder = isOrderAmendmentTransaction(tx.body);
|
||||||
const batchMarketInstructions = isBatchMarketInstructionsTransaction(tx.body);
|
const batchMarketInstructions = isBatchMarketInstructionsTransaction(tx.body);
|
||||||
const transfer = isTransferTransaction(tx.body);
|
const transfer = isTransferTransaction(tx.body);
|
||||||
|
const referral = isReferralRelatedTransaction(tx.body);
|
||||||
return (
|
return (
|
||||||
withdraw ||
|
withdraw ||
|
||||||
submitOrder ||
|
submitOrder ||
|
||||||
@ -105,7 +107,8 @@ const isTransactionTypeSupported = (tx: VegaStoredTxState) => {
|
|||||||
cancelStopOrder ||
|
cancelStopOrder ||
|
||||||
editOrder ||
|
editOrder ||
|
||||||
batchMarketInstructions ||
|
batchMarketInstructions ||
|
||||||
transfer
|
transfer ||
|
||||||
|
referral
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user