From 6629157d1de351ac2eee198bbf3f2ad7adb555af Mon Sep 17 00:00:00 2001 From: Isaac Onyemaechi Date: Wed, 25 Feb 2026 18:08:22 +0100 Subject: [PATCH] feat: integrate WalletMigrationModal into TransferForm and TransactionForm for improved migration handling * Added WalletMigrationModal to TransferForm and TransactionForm to prompt users for migration when necessary. * Enhanced migration logic to determine when migration is mandatory based on user status and deadline. * Updated button text and styles in WalletTransferApprovalModal for consistency and clarity. * Refactored useSwapButton to include isRemainingFundsMigration for better migration state management. --- app/components/TransferForm.tsx | 24 +++++++++++++++++-- app/components/WalletMigrationModal.tsx | 4 ++-- .../WalletTransferApprovalModal.tsx | 8 ++++--- app/hooks/useSwapButton.ts | 9 +++---- app/pages/TransactionForm.tsx | 17 +++++++++++-- 5 files changed, 49 insertions(+), 13 deletions(-) diff --git a/app/components/TransferForm.tsx b/app/components/TransferForm.tsx index e05ec1fb..02bf8b73 100644 --- a/app/components/TransferForm.tsx +++ b/app/components/TransferForm.tsx @@ -6,6 +6,7 @@ import { useSmartWallets } from "@privy-io/react-auth/smart-wallets"; import { useShouldUseEOA, useWalletMigrationStatus } from "../hooks/useEIP7702Account"; import { useNetwork } from "../context/NetworksContext"; import { useBalance, useTokens } from "../context"; +import WalletMigrationModal from "./WalletMigrationModal"; import { classNames, formatDecimalPrecision, @@ -47,12 +48,16 @@ export const TransferForm: React.FC<{ const { user, getAccessToken } = usePrivy(); const { wallets } = useWallets(); const shouldUseEOA = useShouldUseEOA(); - const { isChecking: isMigrationChecking } = useWalletMigrationStatus(); + const { isChecking: isMigrationChecking, needsMigration, isRemainingFundsMigration } = useWalletMigrationStatus(); const { refreshBalance } = useBalance(); const { allTokens } = useTokens(); const useInjectedWallet = shouldUseInjectedWallet(searchParams); const isDark = useActualTheme(); + const MIGRATION_DEADLINE = new Date("2026-03-01T00:00:00Z"); + const isMigrationMandatory = needsMigration && !isRemainingFundsMigration && new Date() >= MIGRATION_DEADLINE; + const [isMigrationModalOpen, setIsMigrationModalOpen] = useState(false); + // State for network dropdown const [isNetworkDropdownOpen, setIsNetworkDropdownOpen] = useState(false); const networkDropdownRef = useRef(null); @@ -323,9 +328,18 @@ export const TransferForm: React.FC<{ const networksMatch = selectedNetwork.chain.name === recipientNetwork; const showNetworkWarning = recipientNetwork && !networksMatch; + const onFormSubmit = (data: any) => { + if (isMigrationMandatory) { + setIsMigrationModalOpen(true); + return; + } + transfer({ ...data, resetForm: reset }); + }; + return ( + <>
transfer({ ...data, resetForm: reset }))} + onSubmit={handleSubmit(onFormSubmit)} className="z-50 w-full max-w-full space-y-4 overflow-x-hidden text-neutral-900 transition-all dark:text-white" noValidate > @@ -622,5 +636,11 @@ export const TransferForm: React.FC<{ {isConfirming ? "Confirming..." : "Continue"}
+ + setIsMigrationModalOpen(false)} + /> + ); }; diff --git a/app/components/WalletMigrationModal.tsx b/app/components/WalletMigrationModal.tsx index 1de78957..8450af1d 100644 --- a/app/components/WalletMigrationModal.tsx +++ b/app/components/WalletMigrationModal.tsx @@ -159,9 +159,9 @@ const WalletMigrationModal: React.FC = ({ {/* Approve Migration Button */} diff --git a/app/components/WalletTransferApprovalModal.tsx b/app/components/WalletTransferApprovalModal.tsx index 115c04cf..2b6d4ce3 100644 --- a/app/components/WalletTransferApprovalModal.tsx +++ b/app/components/WalletTransferApprovalModal.tsx @@ -284,7 +284,7 @@ const WalletTransferApprovalModal: React.FC = continue; } - setProgress(`Transferring ${calls.length} token(s) on ${chainName} (gasless)...`); + setProgress(`Transferring ${calls.length} token${calls.length === 1 ? '' : 's'} on ${chainName}.`); // ✅ Send batched transaction from SCW const txHash = (await smartWalletClient.sendTransaction({ @@ -537,9 +537,11 @@ const WalletTransferApprovalModal: React.FC = diff --git a/app/hooks/useSwapButton.ts b/app/hooks/useSwapButton.ts index 230714f1..312a23b8 100644 --- a/app/hooks/useSwapButton.ts +++ b/app/hooks/useSwapButton.ts @@ -14,6 +14,7 @@ interface UseSwapButtonProps { rate?: number | null; tokenDecimals?: number; needsMigration?: boolean; + isRemainingFundsMigration?: boolean; } export function useSwapButton({ @@ -25,6 +26,7 @@ export function useSwapButton({ rate, tokenDecimals = 18, needsMigration = false, + isRemainingFundsMigration = false, }: UseSwapButtonProps) { const { authenticated } = usePrivy(); const { isInjectedWallet } = useInjectedWallet(); @@ -34,7 +36,7 @@ export function useSwapButton({ const isCurrencySelected = Boolean(currency); const isMigrationMandatory = - needsMigration && new Date() >= MIGRATION_DEADLINE; + needsMigration && !isRemainingFundsMigration && new Date() >= MIGRATION_DEADLINE; // Calculate sender fee and include in balance check const { feeAmount: senderFeeAmount } = calculateSenderFee( @@ -47,7 +49,7 @@ export function useSwapButton({ const hasInsufficientBalance = totalRequired > balance; const isEnabled = (() => { - if (isMigrationMandatory) return false; + if (isMigrationMandatory) return true; if (!rate) return false; if (isInjectedWallet && hasInsufficientBalance) { return false; @@ -87,8 +89,6 @@ export function useSwapButton({ })(); const buttonText = (() => { - if (isMigrationMandatory) return "Migrate wallet"; - if (isInjectedWallet && hasInsufficientBalance) { return "Insufficient balance"; } @@ -132,5 +132,6 @@ export function useSwapButton({ buttonText, buttonAction, hasInsufficientBalance, + isMigrationMandatory, }; } diff --git a/app/pages/TransactionForm.tsx b/app/pages/TransactionForm.tsx index 855db63c..820e3766 100644 --- a/app/pages/TransactionForm.tsx +++ b/app/pages/TransactionForm.tsx @@ -46,6 +46,7 @@ import { useNetwork, useTokens, } from "../context"; +import WalletMigrationModal from "../components/WalletMigrationModal"; /** * TransactionForm component renders a form for submitting a transaction. @@ -74,7 +75,7 @@ export const TransactionForm = ({ const { selectedNetwork } = useNetwork(); const { smartWalletBalance, externalWalletBalance, injectedWalletBalance, isLoading } = useBalance(); const shouldUseEOA = useShouldUseEOA(); - const { needsMigration } = useWalletMigrationStatus(); + const { needsMigration, isRemainingFundsMigration } = useWalletMigrationStatus(); const { isInjectedWallet, injectedAddress } = useInjectedWallet(); const { allTokens } = useTokens(); @@ -470,7 +471,7 @@ export const TransactionForm = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [currencies]); - const { isEnabled, buttonText, buttonAction } = useSwapButton({ + const { isEnabled, buttonText, buttonAction, isMigrationMandatory } = useSwapButton({ watch, balance, isDirty, @@ -479,9 +480,16 @@ export const TransactionForm = ({ rate, tokenDecimals, needsMigration, + isRemainingFundsMigration, }); + const [isMigrationModalOpen, setIsMigrationModalOpen] = useState(false); + const handleSwap = () => { + if (isMigrationMandatory) { + setIsMigrationModalOpen(true); + return; + } setOrderId(""); handleSubmit(onSubmit)(); }; @@ -948,6 +956,11 @@ export const TransactionForm = ({ setIsFundModalOpen(false)} /> )} + + setIsMigrationModalOpen(false)} + /> ); };