diff --git a/package.json b/package.json
index 14e9b0e0..d01af7da 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
"dependencies": {
"@ar.io/sdk": "2.5.0-alpha.8",
"@fontsource/rubik": "^5.0.19",
- "@headlessui/react": "^1.7.19",
+ "@headlessui/react": "^2.2.0",
"@radix-ui/react-tooltip": "^1.0.7",
"@sentry/browser": "^7.101.1",
"@sentry/react": "^7.101.1",
diff --git a/src/components/AssessmentDetailsPanel.tsx b/src/components/AssessmentDetailsPanel.tsx
index 901c04a1..6b9c35f9 100644
--- a/src/components/AssessmentDetailsPanel.tsx
+++ b/src/components/AssessmentDetailsPanel.tsx
@@ -1,4 +1,4 @@
-import { Dialog } from '@headlessui/react';
+import { Dialog, DialogPanel } from '@headlessui/react';
import {
CaretDoubleRightIcon,
CheckSquareIcon,
@@ -177,7 +177,7 @@ const AssessmentDetailsPanel = ({
/>
-
)}
-
+
);
diff --git a/src/components/Profile.tsx b/src/components/Profile.tsx
index 69d31ce3..b42d11fe 100644
--- a/src/components/Profile.tsx
+++ b/src/components/Profile.tsx
@@ -1,5 +1,5 @@
/* eslint-disable tailwindcss/migration-from-tailwind-2 */
-import { Popover } from '@headlessui/react';
+import { Popover, PopoverButton, PopoverPanel } from '@headlessui/react';
import { useGlobalState } from '@src/store';
import { formatBalance, formatWalletAddress } from '@src/utils';
import { forwardRef, useState } from 'react';
@@ -45,9 +45,9 @@ const Profile = () => {
return walletAddress ? (
-
+
-
+
@@ -110,7 +110,7 @@ const Profile = () => {
Logout
-
+
) : walletStateInitialized ? (
diff --git a/src/components/forms/validation.ts b/src/components/forms/validation.ts
index 220ccc98..a2352d40 100644
--- a/src/components/forms/validation.ts
+++ b/src/components/forms/validation.ts
@@ -86,7 +86,7 @@ export const validateNumberRange = (
};
};
-export const validateUnstakeAmount = (
+export const validateWithdrawAmount = (
propertyName: string,
ticker: string,
currentStake: number,
diff --git a/src/components/icons/circle.svg b/src/components/icons/circle.svg
new file mode 100644
index 00000000..4d5133ef
--- /dev/null
+++ b/src/components/icons/circle.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/icons/circle_check.svg b/src/components/icons/circle_check.svg
new file mode 100644
index 00000000..f130c0d1
--- /dev/null
+++ b/src/components/icons/circle_check.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/icons/index.ts b/src/components/icons/index.ts
index 8db3fa1c..4c9af254 100644
--- a/src/components/icons/index.ts
+++ b/src/components/icons/index.ts
@@ -8,6 +8,8 @@ import CancelButtonXIcon from './cancel_button_x.svg?react';
import CaretDoubleRightIcon from './caret_double_right.svg?react';
import CheckSquareIcon from './check_square.svg?react';
import ChevronDownIcon from './chevron_down.svg?react';
+import CircleCheckIcon from './circle_check.svg?react';
+import CircleIcon from './circle.svg?react';
import ClockRewindIcon from './clock_rewind.svg?react';
import CloseIcon from './close.svg?react';
import CloseDrawerIcon from './close_drawer.svg?react';
@@ -60,6 +62,8 @@ export {
CancelButtonXIcon,
CheckSquareIcon,
ChevronDownIcon,
+ CircleCheckIcon,
+ CircleIcon,
ClockRewindIcon,
CloseDrawerIcon,
CloseIcon,
diff --git a/src/components/modals/BaseModal.tsx b/src/components/modals/BaseModal.tsx
index 1f56e0a8..55fe3389 100644
--- a/src/components/modals/BaseModal.tsx
+++ b/src/components/modals/BaseModal.tsx
@@ -1,4 +1,4 @@
-import { Dialog } from '@headlessui/react';
+import { Dialog, DialogPanel } from '@headlessui/react';
import { ReactElement } from 'react';
import { CloseIcon } from '../icons';
@@ -21,18 +21,18 @@ const BaseModal = ({
/>
-
{showCloseButton && (
)}
-
);
diff --git a/src/components/modals/CancelWithdrawalModal.tsx b/src/components/modals/CancelWithdrawalModal.tsx
index 79f6886f..7a6789f2 100644
--- a/src/components/modals/CancelWithdrawalModal.tsx
+++ b/src/components/modals/CancelWithdrawalModal.tsx
@@ -76,7 +76,7 @@ const CancelWithdrawalModal = ({
-
+
Please type "CONFIRM" in the text box to proceed.
@@ -85,7 +85,7 @@ const CancelWithdrawalModal = ({
type="text"
onChange={(e) => setConfirmText(e.target.value)}
className={
- 'h-7 w-full rounded-md border border-grey-700 bg-grey-1000 p-3 text-sm text-mid outline-none placeholder:text-grey-400 focus:text-high'
+ 'h-7 w-full rounded-md border border-grey-700 bg-grey-1000 p-4 text-sm text-mid outline-none placeholder:text-grey-400 focus:text-high'
}
value={confirmText}
/>
diff --git a/src/components/modals/InstantWithdrawalModal.tsx b/src/components/modals/InstantWithdrawalModal.tsx
index 4c1479fe..a104a25e 100644
--- a/src/components/modals/InstantWithdrawalModal.tsx
+++ b/src/components/modals/InstantWithdrawalModal.tsx
@@ -142,7 +142,7 @@ const InstantWithdrawalModal = ({
-
+
-
+
Please type "WITHDRAW" in the text box to proceed.
@@ -189,7 +189,7 @@ const InstantWithdrawalModal = ({
type="text"
onChange={(e) => setConfirmText(e.target.value)}
className={
- 'h-7 w-full rounded-md border border-grey-700 bg-grey-1000 p-3 text-sm text-mid outline-none placeholder:text-grey-400 focus:text-high'
+ 'h-7 w-full rounded-md border border-grey-700 bg-grey-1000 p-4 text-sm text-mid outline-none placeholder:text-grey-400 focus:text-high'
}
value={confirmText}
/>
diff --git a/src/components/modals/LeaveNetworkModal.tsx b/src/components/modals/LeaveNetworkModal.tsx
index 5605a9e1..557d07a2 100644
--- a/src/components/modals/LeaveNetworkModal.tsx
+++ b/src/components/modals/LeaveNetworkModal.tsx
@@ -94,14 +94,14 @@ const LeaveNetworkModal = ({ onClose }: { onClose: () => void }) => {
-
+
Please type "LEAVE NETWORK" in the text box to proceed.
setLeaveNetworkText(e.target.value)}
className={
- 'h-7 w-full rounded-md border border-grey-700 bg-grey-1000 p-3 text-sm text-mid outline-none placeholder:text-grey-400 focus:text-high'
+ 'h-7 w-full rounded-md border border-grey-700 bg-grey-1000 p-4 text-sm text-mid outline-none placeholder:text-grey-400 focus:text-high'
}
value={leaveNetworkText}
/>
diff --git a/src/components/modals/ReviewStakeModal.tsx b/src/components/modals/ReviewStakeModal.tsx
new file mode 100644
index 00000000..bdea002c
--- /dev/null
+++ b/src/components/modals/ReviewStakeModal.tsx
@@ -0,0 +1,176 @@
+import { AoGatewayWithAddress, IOToken } from '@ar.io/sdk/web';
+import { log, WRITE_OPTIONS } from '@src/constants';
+import { useGlobalState } from '@src/store';
+import { formatAddress, formatWithCommas } from '@src/utils';
+import { ArweaveTransactionID } from '@src/utils/ArweaveTransactionId';
+import { showErrorToast } from '@src/utils/toast';
+import { useQueryClient } from '@tanstack/react-query';
+import { useState } from 'react';
+import Button, { ButtonType } from '../Button';
+import { LinkArrowIcon } from '../icons';
+import LabelValueRow from '../LabelValueRow';
+import BaseModal from './BaseModal';
+import BlockingMessageModal from './BlockingMessageModal';
+import SuccessModal from './SuccessModal';
+import WithdrawWarning from './WithdrawWarning';
+
+const ReviewStakeModal = ({
+ gateway,
+ amountToStake,
+ onSuccess,
+ onClose,
+ walletAddress,
+ ticker,
+}: {
+ gateway: AoGatewayWithAddress;
+ amountToStake: number;
+ walletAddress: ArweaveTransactionID;
+ onClose: () => void;
+ onSuccess: () => void;
+ ticker: string;
+}) => {
+ const queryClient = useQueryClient();
+ const arIOWriteableSDK = useGlobalState((state) => state.arIOWriteableSDK);
+
+ const [txid, setTxid] = useState
();
+
+ const [showBlockingMessageModal, setShowBlockingMessageModal] =
+ useState(false);
+ const [showSuccessModal, setShowSuccessModal] = useState(false);
+
+ const submitForm = async () => {
+ if (arIOWriteableSDK) {
+ setShowBlockingMessageModal(true);
+
+ try {
+ const { id: txID } = await arIOWriteableSDK.delegateStake(
+ {
+ target: gateway.gatewayAddress,
+ stakeQty: new IOToken(amountToStake).toMIO(),
+ },
+ WRITE_OPTIONS,
+ );
+ setTxid(txID);
+
+ log.info(`Increase Delegate Stake txID: ${txID}`);
+
+ queryClient.invalidateQueries({
+ queryKey: ['gateway', walletAddress.toString()],
+ refetchType: 'all',
+ });
+ queryClient.invalidateQueries({
+ queryKey: ['gateways'],
+ refetchType: 'all',
+ });
+ queryClient.invalidateQueries({
+ queryKey: ['balances'],
+ refetchType: 'all',
+ });
+ queryClient.invalidateQueries({
+ queryKey: ['delegateStakes'],
+ refetchType: 'all',
+ });
+
+ setShowSuccessModal(true);
+ } catch (e: any) {
+ showErrorToast(`${e}`);
+ } finally {
+ setShowBlockingMessageModal(false);
+ }
+ }
+ };
+
+ return (
+ <>
+
+
+
+ Review
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {showBlockingMessageModal && (
+ setShowBlockingMessageModal(false)}
+ message="Sign the following data with your wallet to proceed."
+ >
+ )}
+ {showSuccessModal && (
+ {
+ setShowSuccessModal(false);
+ onClose();
+ onSuccess();
+ }}
+ title="Congratulations"
+ bodyText={
+
+
You have successfully updated your stake.
+
+
Transaction ID:
+
+
+
+ }
+ />
+ )}
+ >
+ );
+};
+
+export default ReviewStakeModal;
diff --git a/src/components/modals/ReviewWithdrawalModal.tsx b/src/components/modals/ReviewWithdrawalModal.tsx
new file mode 100644
index 00000000..62666754
--- /dev/null
+++ b/src/components/modals/ReviewWithdrawalModal.tsx
@@ -0,0 +1,239 @@
+import { AoGatewayWithAddress, IOToken } from '@ar.io/sdk/web';
+import { log, WRITE_OPTIONS } from '@src/constants';
+import { useGlobalState } from '@src/store';
+import { WithdrawalType } from '@src/types';
+import { formatAddress, formatDateTime, formatWithCommas } from '@src/utils';
+import { ArweaveTransactionID } from '@src/utils/ArweaveTransactionId';
+import { showErrorToast } from '@src/utils/toast';
+import { useQueryClient } from '@tanstack/react-query';
+import dayjs from 'dayjs';
+import { useEffect, useState } from 'react';
+import Button, { ButtonType } from '../Button';
+import { LinkArrowIcon } from '../icons';
+import LabelValueRow from '../LabelValueRow';
+import BaseModal from './BaseModal';
+import BlockingMessageModal from './BlockingMessageModal';
+import SuccessModal from './SuccessModal';
+
+const ReviewWithdrawalModal = ({
+ gateway,
+ amountToWithdraw,
+ withdrawalType,
+ onSuccess,
+ onClose,
+ walletAddress,
+ ticker,
+ withdrawalFee,
+ returningAmount,
+}: {
+ gateway: AoGatewayWithAddress;
+ amountToWithdraw: number;
+ withdrawalType: WithdrawalType;
+ walletAddress: ArweaveTransactionID;
+ onClose: () => void;
+ onSuccess: () => void;
+ ticker: string;
+ withdrawalFee: number;
+ returningAmount?: number | string;
+}) => {
+ const queryClient = useQueryClient();
+ const arIOWriteableSDK = useGlobalState((state) => state.arIOWriteableSDK);
+
+ const [txid, setTxid] = useState();
+
+ const [showBlockingMessageModal, setShowBlockingMessageModal] =
+ useState(false);
+ const [showSuccessModal, setShowSuccessModal] = useState(false);
+
+ const [dateOfReturn, setDateOfReturn] = useState('');
+
+ const [confirmText, setConfirmText] = useState('');
+
+ const termsAccepted = confirmText === 'WITHDRAW';
+
+ useEffect(() => {
+ setDateOfReturn(
+ withdrawalType === 'expedited'
+ ? 'Instant'
+ : formatDateTime(dayjs(new Date()).add(30, 'day').toDate()),
+ );
+ }, [withdrawalType]);
+
+ const submitForm = async () => {
+ if (arIOWriteableSDK) {
+ setShowBlockingMessageModal(true);
+
+ try {
+ const instant = withdrawalType === 'expedited';
+
+ const { id: txID } = await arIOWriteableSDK.decreaseDelegateStake(
+ {
+ target: gateway.gatewayAddress,
+ decreaseQty: new IOToken(amountToWithdraw).toMIO(),
+ instant,
+ },
+ WRITE_OPTIONS,
+ );
+ setTxid(txID);
+
+ log.info(`Decrease Delegate Stake txID: ${txID}`);
+
+ queryClient.invalidateQueries({
+ queryKey: ['gateway', walletAddress.toString()],
+ refetchType: 'all',
+ });
+ queryClient.invalidateQueries({
+ queryKey: ['gateways'],
+ refetchType: 'all',
+ });
+ queryClient.invalidateQueries({
+ queryKey: ['balances'],
+ refetchType: 'all',
+ });
+ queryClient.invalidateQueries({
+ queryKey: ['delegateStakes'],
+ refetchType: 'all',
+ });
+
+ setShowSuccessModal(true);
+ } catch (e: any) {
+ showErrorToast(`${e}`);
+ } finally {
+ setShowBlockingMessageModal(false);
+ }
+ }
+ };
+
+ return (
+ <>
+
+
+
+ Review
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {withdrawalType === 'expedited' && (
+ <>
+
+
+ >
+ )}
+
+
+
+
+
+ Please type "WITHDRAW" in the text box to proceed.
+
+
setConfirmText(e.target.value)}
+ className={
+ 'h-7 w-full rounded-md border border-grey-700 bg-grey-1000 p-4 text-sm text-mid outline-none placeholder:text-grey-400 focus:text-high'
+ }
+ value={confirmText}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+ {showBlockingMessageModal && (
+ setShowBlockingMessageModal(false)}
+ message="Sign the following data with your wallet to proceed."
+ >
+ )}
+ {showSuccessModal && (
+ {
+ setShowSuccessModal(false);
+ onClose();
+ onSuccess();
+ }}
+ title="Congratulations"
+ bodyText={
+
+
You have successfully updated your stake.
+
+
Transaction ID:
+
+
+
+ }
+ />
+ )}
+ >
+ );
+};
+
+export default ReviewWithdrawalModal;
diff --git a/src/components/modals/StakingModal.tsx b/src/components/modals/StakingModal.tsx
index 1df49dd0..87743517 100644
--- a/src/components/modals/StakingModal.tsx
+++ b/src/components/modals/StakingModal.tsx
@@ -1,18 +1,13 @@
-import { IOToken, mIOToken } from '@ar.io/sdk/web';
-import {
- EAY_TOOLTIP_FORMULA,
- EAY_TOOLTIP_TEXT,
- WRITE_OPTIONS,
- log,
-} from '@src/constants';
+import { mIOToken } from '@ar.io/sdk/web';
+import { Label, Radio, RadioGroup } from '@headlessui/react';
+import { EAY_TOOLTIP_FORMULA, EAY_TOOLTIP_TEXT } from '@src/constants';
import useBalances from '@src/hooks/useBalances';
import useDelegateStakes from '@src/hooks/useDelegateStakes';
import useGateway from '@src/hooks/useGateway';
import useRewardsInfo from '@src/hooks/useRewardsInfo';
import { useGlobalState } from '@src/store';
-import { formatWithCommas } from '@src/utils';
-import { showErrorToast } from '@src/utils/toast';
-import { useQueryClient } from '@tanstack/react-query';
+import { WithdrawalType } from '@src/types';
+import { formatAddress, formatWithCommas } from '@src/utils';
import { MathJax } from 'better-react-mathjax';
import { useEffect, useState } from 'react';
import Button, { ButtonType } from '../Button';
@@ -21,14 +16,13 @@ import Tooltip from '../Tooltip';
import ErrorMessageIcon from '../forms/ErrorMessageIcon';
import {
validateIOAmount,
- validateUnstakeAmount,
validateWalletAddress,
+ validateWithdrawAmount,
} from '../forms/validation';
-import { InfoIcon } from '../icons';
+import { CircleCheckIcon, CircleIcon, InfoIcon } from '../icons';
import BaseModal from './BaseModal';
-import BlockingMessageModal from './BlockingMessageModal';
-import SuccessModal from './SuccessModal';
-import UnstakeWarning from './UnstakeWarning';
+import ReviewStakeModal from './ReviewStakeModal';
+import ReviewWithdrawalModal from './ReviewWithdrawalModal';
const StakingModal = ({
onClose,
@@ -38,11 +32,8 @@ const StakingModal = ({
onClose: () => void;
ownerWallet?: string;
}) => {
- const queryClient = useQueryClient();
-
const walletAddress = useGlobalState((state) => state.walletAddress);
const { data: balances } = useBalances(walletAddress);
- const arIOWriteableSDK = useGlobalState((state) => state.arIOWriteableSDK);
const ticker = useGlobalState((state) => state.ticker);
const [tab, setTab] = useState(0);
@@ -51,11 +42,13 @@ const StakingModal = ({
const [currentStake, setCurrentStake] = useState(0);
const [amountToStake, setAmountToStake] = useState('');
- const [amountToUnstake, setAmountToUnstake] = useState('');
+ const [amountToWithdraw, setAmountToWithdraw] = useState('');
+ const [withdrawalType, setWithdrawalType] =
+ useState('standard');
- const [showBlockingMessageModal, setShowBlockingMessageModal] =
+ const [showReviewStakeModal, setShowReviewStakeModal] = useState(false);
+ const [showReviewWithdrawalModal, setShowReviewWithdrawalModal] =
useState(false);
- const [showSuccessModal, setShowSuccessModal] = useState(false);
const gatewayOwnerWallet =
ownerWallet?.toString() ?? userEnteredWalletAddress;
@@ -82,12 +75,12 @@ const StakingModal = ({
const newTotalStake =
tab == 0
? currentStake + parseFloat(amountToStake)
- : currentStake - parseFloat(amountToUnstake);
+ : currentStake - parseFloat(amountToWithdraw);
const newStake =
- tab == 0 ? parseFloat(amountToStake) : -parseFloat(amountToUnstake);
+ tab == 0 ? parseFloat(amountToStake) : -parseFloat(amountToWithdraw);
const rewardsInfo = useRewardsInfo(gateway, newStake);
const EAY =
- rewardsInfo && newTotalStake > 0
+ rewardsInfo && newTotalStake > 0 && !isNaN(rewardsInfo.EAY)
? (rewardsInfo.EAY * 100).toLocaleString('en-us', {
maximumFractionDigits: 2,
}) + '%'
@@ -98,6 +91,16 @@ const StakingModal = ({
: 500;
const minRequiredStakeToAdd = currentStake > 0 ? 1 : minDelegatedStake;
+ const withdrawalFee =
+ withdrawalType === 'expedited' ? 0.5 * parseFloat(amountToWithdraw) : 0;
+ const returningAmount = isNaN(parseFloat(amountToWithdraw))
+ ? '-'
+ : +(
+ isNaN(withdrawalFee)
+ ? parseFloat(amountToWithdraw)
+ : parseFloat(amountToWithdraw) - withdrawalFee
+ ).toFixed(4);
+
const validators = {
address: validateWalletAddress('Gateway Owner'),
stakeAmount: validateIOAmount(
@@ -106,8 +109,8 @@ const StakingModal = ({
minRequiredStakeToAdd,
balances?.io,
),
- unstakeAmount: validateUnstakeAmount(
- 'Unstake Amount',
+ withdrawAmount: validateWithdrawAmount(
+ 'Withdraw Amount',
ticker,
currentStake,
minDelegatedStake,
@@ -121,12 +124,18 @@ const StakingModal = ({
if (tab == 0) {
return validators.stakeAmount(amountToStake) == undefined;
} else {
- return validators.unstakeAmount(amountToUnstake) == undefined;
+ return validators.withdrawAmount(amountToWithdraw) == undefined;
}
};
+ const parsedStake = parseFloat(
+ amountToStake.length === 0 ? '0' : amountToStake,
+ );
const remainingBalance =
- isFormValid() && balances ? balances.io - parseFloat(amountToStake) : '-';
+ balances && parsedStake <= balances.io ? balances.io - parsedStake : -1;
+
+ const parsedWithdrawing = parseFloat(amountToWithdraw.length === 0 ? '0' : amountToWithdraw);
+ const remainingWithdrawalBalance = currentStake - parsedWithdrawing;
const baseTabClassName = 'text-center py-3';
const selectedTabClassNames = `${baseTabClassName} bg-grey-700 border-b border-red-400`;
@@ -136,7 +145,7 @@ const StakingModal = ({
if (tab == 0) {
setAmountToStake((balances?.io || 0) + '');
} else {
- setAmountToUnstake(currentStake + '');
+ setAmountToWithdraw(currentStake + '');
}
};
@@ -147,63 +156,10 @@ const StakingModal = ({
!allowDelegatedStaking)) ||
(tab == 1 && currentStake <= 0);
- const submitForm = async () => {
- if (walletAddress && arIOWriteableSDK && gateway && isFormValid()) {
- setShowBlockingMessageModal(true);
-
- try {
- if (tab == 0) {
- const { id: txID } = await arIOWriteableSDK.delegateStake(
- {
- target: gatewayOwnerWallet,
- stakeQty: new IOToken(parseFloat(amountToStake)).toMIO(),
- },
- WRITE_OPTIONS,
- );
-
- log.info(`Increase Delegate Stake txID: ${txID}`);
- } else {
- const { id: txID } = await arIOWriteableSDK.decreaseDelegateStake(
- {
- target: gatewayOwnerWallet,
- decreaseQty: new IOToken(parseFloat(amountToUnstake)).toMIO(),
- },
- WRITE_OPTIONS,
- );
-
- log.info(`Decrease Delegate Stake txID: ${txID}`);
- }
-
- queryClient.invalidateQueries({
- queryKey: ['gateway', walletAddress.toString()],
- refetchType: 'all',
- });
- queryClient.invalidateQueries({
- queryKey: ['gateways'],
- refetchType: 'all',
- });
- queryClient.invalidateQueries({
- queryKey: ['balances'],
- refetchType: 'all',
- });
- queryClient.invalidateQueries({
- queryKey: ['delegateStakes'],
- refetchType: 'all',
- });
-
- setShowSuccessModal(true);
- } catch (e: any) {
- showErrorToast(`${e}`);
- } finally {
- setShowBlockingMessageModal(false);
- }
- }
- };
-
const errorMessages = {
gatewayOwner: validators.address(gatewayOwnerWallet),
stakeAmount: validators.stakeAmount(amountToStake),
- unstakeAmount: validators.unstakeAmount(amountToUnstake),
+ withdrawAmount: validators.withdrawAmount(amountToWithdraw),
cannotStake:
(balances?.io || 0) < minRequiredStakeToAdd
? `Insufficient balance, at least ${minRequiredStakeToAdd} IO required.`
@@ -215,46 +171,65 @@ const StakingModal = ({
return (
-
+
-
Gateway Owner:
- {ownerWallet ? (
-
{ownerWallet}
- ) : (
-
{
- setUserEnteredWalletAddress(e.target.value);
- }}
- maxLength={43}
+
+ {ownerWallet ? (
+
+ ) : (
+ <>
+
Gateway Owner:
+
{
+ setUserEnteredWalletAddress(e.target.value);
+ }}
+ maxLength={43}
+ />
+ >
+ )}
+
+
- )}
+
+
+
+
Amount:
{tab == 0
? balances &&
- `Available: ${formatWithCommas(balances.io)} ${ticker}`
- : `Available to Unstake: ${formatWithCommas(currentStake)} ${ticker}`}
+ `Available: ${remainingBalance >= 0 ? formatWithCommas(+remainingBalance) : '-'} ${ticker}`
+ : `Available to Withdraw: ${remainingWithdrawalBalance >= 0 ? formatWithCommas(remainingWithdrawalBalance) : '-'} ${ticker}`}
@@ -265,8 +240,8 @@ const StakingModal = ({
disabled={disableInput}
readOnly={disableInput}
type="text"
- placeholder={`Enter amount of ${ticker} to ${tab == 0 ? 'stake' : 'unstake'}`}
- value={tab == 0 ? amountToStake : amountToUnstake}
+ placeholder={`Enter amount of ${ticker} to ${tab == 0 ? 'stake' : 'withdraw'}`}
+ value={tab == 0 ? amountToStake : amountToWithdraw}
onChange={(e) => {
const textValue = e.target.value;
@@ -277,7 +252,7 @@ const StakingModal = ({
if (tab == 0) {
setAmountToStake(textValue);
} else {
- setAmountToUnstake(textValue);
+ setAmountToWithdraw(textValue);
}
}}
>
@@ -295,10 +270,10 @@ const StakingModal = ({
/>
)}
{tab == 1 &&
- amountToUnstake?.length > 0 &&
- errorMessages.unstakeAmount && (
+ amountToWithdraw?.length > 0 &&
+ errorMessages.withdrawAmount && (
)}
@@ -311,103 +286,147 @@ const StakingModal = ({
text="Max"
/>
-
+
+ {tab == 1 && (
+
setWithdrawalType(v)}
+ >
+
+
+
+
+
+
+
+
+ 30 day withdrawal period with no fees.
+
+
+
+
+
+
+
+
+
+
+
+
+ Instant withdrawal with 50% fee.
+
+
+
+
+ )}
+
+
+
+ {tab == 1 && withdrawalType == 'expedited' && (
+ <>
+
+
+ >
+ )}
+
+
{tab == 0 && (
)}
-
-
- {EAY_TOOLTIP_TEXT}
- {EAY_TOOLTIP_FORMULA}
-
- }
- >
-
-
- }
- />
-
-
-
-
+ {tab == 0 && (
+
+ {EAY_TOOLTIP_TEXT}
+
+ {EAY_TOOLTIP_FORMULA}
+
+
+ }
+ >
+
+
+ }
+ />
+ )}
-
-
-
-
- {tab == 0 && (
-
- )}
-
- {showBlockingMessageModal && (
-
setShowBlockingMessageModal(false)}
- message="Sign the following data with your wallet to proceed."
- >
+ {showReviewStakeModal && gateway && walletAddress && (
+
setShowReviewStakeModal(false)}
+ onSuccess={() => onClose()}
+ ticker={ticker}
+ walletAddress={walletAddress}
+ />
)}
- {showSuccessModal && (
- {
- setShowSuccessModal(false);
- onClose();
- }}
- title="Congratulations"
- bodyText="You have successfully updated stake."
+ {showReviewWithdrawalModal && gateway && walletAddress && (
+ setShowReviewWithdrawalModal(false)}
+ onSuccess={() => onClose()}
+ ticker={ticker}
+ walletAddress={walletAddress}
+ withdrawalFee={withdrawalFee}
+ returningAmount={returningAmount}
/>
)}
diff --git a/src/components/modals/UnstakeAllModal.tsx b/src/components/modals/WithdrawAllModal.tsx
similarity index 90%
rename from src/components/modals/UnstakeAllModal.tsx
rename to src/components/modals/WithdrawAllModal.tsx
index 873bc3c0..2933d112 100644
--- a/src/components/modals/UnstakeAllModal.tsx
+++ b/src/components/modals/WithdrawAllModal.tsx
@@ -5,12 +5,12 @@ import { showErrorToast } from '@src/utils/toast';
import { useState } from 'react';
import Button, { ButtonType } from '../Button';
import BaseModal from './BaseModal';
-import UnstakeWarning from './UnstakeWarning';
+import WithdrawWarning from './WithdrawWarning';
import BlockingMessageModal from './BlockingMessageModal';
import SuccessModal from './SuccessModal';
import { useQueryClient } from '@tanstack/react-query';
-const UnstakeAllModal = ({
+const WithdrawAllModal = ({
onClose,
activeStakes,
}: {
@@ -84,7 +84,7 @@ const UnstakeAllModal = ({
-
Unstake All
+
Withdraw All
Withdraw all delegated stakes.
@@ -115,14 +115,10 @@ const UnstakeAllModal = ({
))}
-
+
-
-
+
Total Withdrawal:
@@ -134,8 +130,8 @@ const UnstakeAllModal = ({
}
+ title="Withdraw"
+ text={
Withdraw
}
className="w-full"
/>
@@ -162,4 +158,4 @@ const UnstakeAllModal = ({
);
};
-export default UnstakeAllModal;
+export default WithdrawAllModal;
diff --git a/src/components/modals/UnstakeWarning.tsx b/src/components/modals/WithdrawWarning.tsx
similarity index 87%
rename from src/components/modals/UnstakeWarning.tsx
rename to src/components/modals/WithdrawWarning.tsx
index 09fe1ef6..fc2aecfd 100644
--- a/src/components/modals/UnstakeWarning.tsx
+++ b/src/components/modals/WithdrawWarning.tsx
@@ -1,6 +1,6 @@
import { WarningTriangleIcon } from '../icons';
-const UnstakeWarning = () => {
+const WithdrawWarning = () => {
return (
@@ -14,4 +14,4 @@ const UnstakeWarning = () => {
);
};
-export default UnstakeWarning;
+export default WithdrawWarning;
diff --git a/src/hooks/useDelegateStakes.ts b/src/hooks/useDelegateStakes.ts
index f97ad1e3..47c9b61a 100644
--- a/src/hooks/useDelegateStakes.ts
+++ b/src/hooks/useDelegateStakes.ts
@@ -11,7 +11,7 @@ const useDelegateStakes = (address?: string) => {
const arIOReadSDK = useGlobalState((state) => state.arIOReadSDK);
const res = useQuery
({
- queryKey: ['delegateStakes', address],
+ queryKey: ['delegateStakes', arIOReadSDK, address],
queryFn: async () => {
if (!address) {
throw new Error('Address is not set');
@@ -30,6 +30,7 @@ const useDelegateStakes = (address?: string) => {
cursor,
limit: 10,
});
+
pageResult.items.forEach((d) => {
if (d.type === 'stake') {
retVal.stakes.push(d);
diff --git a/src/hooks/useGateway.ts b/src/hooks/useGateway.ts
index b42e40b3..a04979f2 100644
--- a/src/hooks/useGateway.ts
+++ b/src/hooks/useGateway.ts
@@ -10,7 +10,7 @@ const useGateway = ({
const arIOReadSDK = useGlobalState((state) => state.arIOReadSDK);
const queryResults = useQuery({
- queryKey: ['gateway', ownerWalletAddress || ''],
+ queryKey: ['gateway', arIOReadSDK, ownerWalletAddress || ''],
queryFn: () => {
if (ownerWalletAddress === undefined) {
return Promise.reject(
diff --git a/src/pages/Staking/MyStakesTable.tsx b/src/pages/Staking/MyStakesTable.tsx
index 55b6d4f5..971a4e19 100644
--- a/src/pages/Staking/MyStakesTable.tsx
+++ b/src/pages/Staking/MyStakesTable.tsx
@@ -12,7 +12,7 @@ import {
import CancelWithdrawalModal from '@src/components/modals/CancelWithdrawalModal';
import InstantWithdrawalModal from '@src/components/modals/InstantWithdrawalModal';
import StakingModal from '@src/components/modals/StakingModal';
-import UnstakeAllModal from '@src/components/modals/UnstakeAllModal';
+import WithdrawAllModal from '@src/components/modals/WithdrawAllModal';
import useDelegateStakes from '@src/hooks/useDelegateStakes';
import useGateways from '@src/hooks/useGateways';
import { useGlobalState } from '@src/store';
@@ -54,7 +54,7 @@ const MyStakesTable = () => {
const [tableMode, setTableMode] = useState('activeStakes');
- const [showUnstakeAllModal, setShowUnstakeAllModal] = useState(false);
+ const [showWithdrawAllModal, setShowWithdrawAllModal] = useState(false);
const [stakingModalWalletAddress, setStakingModalWalletAddress] =
useState();
const [showQuickStake, setShowQuickStake] = useState(false);
@@ -317,7 +317,7 @@ const MyStakesTable = () => {
active={true}
title="Withdraw All"
text="Withdraw All"
- onClick={() => setShowUnstakeAllModal(true)}
+ onClick={() => setShowWithdrawAllModal(true)}
/>
)}