11import { PEANUT_WALLET_CHAIN , PEANUT_WALLET_TOKEN } from '@/constants'
2- import { BALANCE_DECREASE , INITIATE_PAYMENT } from '@/constants/query.consts'
32import { tokenSelectorContext } from '@/context'
43import { useWallet } from '@/hooks/wallet/useWallet'
54import { type ParsedURL } from '@/lib/url-parser/types/payment'
@@ -27,7 +26,6 @@ import { getRoute, type PeanutCrossChainRoute } from '@/services/swap'
2726import { estimateTransactionCostUsd } from '@/app/actions/tokens'
2827import { captureException } from '@sentry/nextjs'
2928import { useRouter } from 'next/navigation'
30- import { useQueryClient } from '@tanstack/react-query'
3129
3230enum ELoadingStep {
3331 IDLE = 'Idle' ,
@@ -84,7 +82,6 @@ export const usePaymentInitiator = () => {
8482 const router = useRouter ( )
8583 const config = useConfig ( )
8684 const { chain : connectedWalletChain } = useWagmiAccount ( )
87- const queryClient = useQueryClient ( )
8885
8986 const [ slippagePercentage , setSlippagePercentage ] = useState < number | undefined > ( undefined )
9087 const [ unsignedTx , setUnsignedTx ] = useState < peanutInterfaces . IPeanutUnsignedTransaction | null > ( null )
@@ -605,22 +602,12 @@ export const usePaymentInitiator = () => {
605602 ]
606603 )
607604
608- // @dev Architecture Note: initiatePayment flow and mutation tracking
609- //
610- // Current: This async function uses state-based lifecycle (isProcessing, loadingStep)
611- // rather than TanStack Query mutations. This is INTENTIONAL because:
612- // 1. It has two phases: charge preparation (no balance change) + payment execution (balance decrease)
613- // 2. Only the payment execution phase triggers balance-decreasing mutations (via sendMoney/sendTransactions)
614- // 3. sendMoney already properly wraps mutations with mutationKey: [BALANCE_DECREASE, SEND_MONEY]
615- // 4. usePendingTransactions tracks ALL balance-decreasing operations globally
616- //
617- // Bug fix (2025-10): Added guard at line 648 to prevent premature payment execution when
618- // fetching existing charges. Previously, fetching an existing charge (chargeCreated=false)
619- // without skipChargeCreation=true would fall through and trigger sendMoney() prematurely,
620- // causing optimistic balance updates before user confirmed payment.
621- //
622- // Future consideration: Could wrap entire initiatePayment in useMutation, but complexity is HIGH
623- // due to two-phase flow, Redux integration, and multiple return points. Current architecture works.
605+ // @dev TODO: Refactor to TanStack Query mutation for architectural consistency
606+ // Current: This async function works correctly (protected by isProcessing state)
607+ // but is NOT tracked by usePendingTransactions mutation system.
608+ // Future improvement: Wrap in useMutation for consistency with other balance-decreasing ops.
609+ // mutationKey: [BALANCE_DECREASE, INITIATE_PAYMENT]
610+ // Complexity: HIGH - complex state/Redux integration. Low priority.
624611 //
625612 // initiate and process payments
626613 const initiatePayment = useCallback (
@@ -641,25 +628,19 @@ export const usePaymentInitiator = () => {
641628 console . log ( 'Proceeding with charge details:' , determinedChargeDetails . uuid )
642629
643630 // 2. handle charge state
644- // Return early if:
645- // a) Explicitly told to return after charge creation (request pot initial view)
646- // b) Charge was just created AND needs special handling (external wallet/cross-chain)
647- // c) Fetching existing charge WITHOUT explicit skipChargeCreation (not from CONFIRM view)
648- const shouldReturnAfterCharge =
649- payload . returnAfterChargeCreation ||
631+ if (
632+ payload . returnAfterChargeCreation || // For request pot payment, return after charge creation
650633 ( chargeCreated &&
651634 ( payload . isExternalWalletFlow ||
652635 ! isPeanutWallet ||
653636 ( isPeanutWallet &&
654637 ( ! areEvmAddressesEqual ( determinedChargeDetails . tokenAddress , PEANUT_WALLET_TOKEN ) ||
655- determinedChargeDetails . chainId !== PEANUT_WALLET_CHAIN . id . toString ( ) ) ) ) ) ||
656- // NEW: If charge exists (not created) and we're NOT explicitly skipping charge creation,
657- // then we're in "prepare" mode and shouldn't execute payment yet
658- ( ! chargeCreated && payload . chargeId && ! payload . skipChargeCreation )
659-
660- if ( shouldReturnAfterCharge ) {
638+ determinedChargeDetails . chainId !== PEANUT_WALLET_CHAIN . id . toString ( ) ) ) ) )
639+ ) {
661640 console . log (
662- `Charge ready. Returning without payment execution. (chargeCreated: ${ chargeCreated } , skipChargeCreation: ${ payload . skipChargeCreation } )`
641+ `Charge created. Transitioning to Confirm view for: ${
642+ payload . isExternalWalletFlow ? 'Add Money Flow' : 'External Wallet'
643+ } .`
663644 )
664645 setLoadingStep ( 'Charge Created' )
665646 return { status : 'Charge Created' , charge : determinedChargeDetails , success : false }
0 commit comments