'use client'; import type { LifecycleStatusUpdate } from '@/internal/types'; import { createContext, useCallback, useContext, useEffect, useState, } from 'react'; import { useAnalytics } from '../../core/analytics/hooks/useAnalytics'; import { FundEvent } from '../../core/analytics/types'; import { useEmitLifecycleStatus } from '../hooks/useEmitLifecycleStatus'; import { useOnrampExchangeRate } from '../hooks/useOnrampExchangeRate'; import { usePaymentMethods } from '../hooks/usePaymentMethods'; import type { AmountInputType, FundButtonState, FundCardProviderProps, LifecycleStatus, OnrampError, PaymentMethod, PresetAmountInputs, } from '../types'; type FundCardContextType = { asset: string; currency: string; selectedPaymentMethod?: PaymentMethod; setSelectedPaymentMethod: (paymentMethod: PaymentMethod) => void; selectedInputType: AmountInputType; setSelectedInputType: (inputType: AmountInputType) => void; fundAmountFiat: string; setFundAmountFiat: (amount: string) => void; fundAmountCrypto: string; setFundAmountCrypto: (amount: string) => void; exchangeRate: number; setExchangeRate: (exchangeRate: number) => void; exchangeRateLoading: boolean; setExchangeRateLoading: (loading: boolean) => void; submitButtonState: FundButtonState; setSubmitButtonState: (state: FundButtonState) => void; paymentMethods: PaymentMethod[]; setPaymentMethods: (paymentMethods: PaymentMethod[]) => void; isPaymentMethodsLoading: boolean; setIsPaymentMethodsLoading: (loading: boolean) => void; headerText?: string; buttonText?: string; country: string; subdivision?: string; inputType?: 'fiat' | 'crypto'; sessionToken?: string; lifecycleStatus: LifecycleStatus; presetAmountInputs?: PresetAmountInputs; updateLifecycleStatus: ( newStatus: LifecycleStatusUpdate, ) => void; onError?: (error: OnrampError) => void; }; const FundContext = createContext(undefined); export function FundCardProvider({ children, asset, currency = 'USD', headerText = `Buy ${asset.toUpperCase()}`, buttonText, country, subdivision, inputType, onError, onStatus, onSuccess, presetAmountInputs, sessionToken, }: FundCardProviderProps) { const [selectedPaymentMethod, setSelectedPaymentMethod] = useState< PaymentMethod | undefined >(); const [selectedInputType, setSelectedInputType] = useState( inputType || 'fiat', ); const [fundAmountFiat, setFundAmountFiat] = useState(''); const [fundAmountCrypto, setFundAmountCrypto] = useState(''); const [exchangeRate, setExchangeRate] = useState(0); const [exchangeRateLoading, setExchangeRateLoading] = useState(true); const [submitButtonState, setSubmitButtonState] = useState('default'); const [paymentMethods, setPaymentMethods] = useState([]); const [isPaymentMethodsLoading, setIsPaymentMethodsLoading] = useState(true); const { lifecycleStatus, updateLifecycleStatus } = useEmitLifecycleStatus({ onError, onSuccess, onStatus, }); const { fetchExchangeRate } = useOnrampExchangeRate({ asset, currency, country, subdivision, setExchangeRate, onError, }); const { sendAnalytics } = useAnalytics(); const handleAnalyticsAmountChanged = useCallback( (amount: number, currency: string) => { sendAnalytics(FundEvent.FundAmountChanged, { amount, currency, }); }, [sendAnalytics], ); const handleAnalyticsOptionSelected = useCallback( (option: string) => { sendAnalytics(FundEvent.FundOptionSelected, { option, }); }, [sendAnalytics], ); const handleSetFundAmountFiat = useCallback( (amount: string) => { const newAmount = Number.parseFloat(amount); if (!Number.isNaN(newAmount)) { handleAnalyticsAmountChanged(newAmount, currency); } setFundAmountFiat(amount); }, [currency, handleAnalyticsAmountChanged], ); const handleSetSelectedPaymentMethod = useCallback( (paymentMethod: PaymentMethod) => { handleAnalyticsOptionSelected(paymentMethod.id); setSelectedPaymentMethod(paymentMethod); }, [handleAnalyticsOptionSelected], ); const handleFetchExchangeRate = useCallback(async () => { setExchangeRateLoading(true); await fetchExchangeRate(); setExchangeRateLoading(false); }, [fetchExchangeRate]); useEffect(() => { handleFetchExchangeRate(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // Fetches and sets the payment methods to the context usePaymentMethods({ country, subdivision, currency, setPaymentMethods, setIsPaymentMethodsLoading, onError, }); return ( {children} ); } export function useFundContext() { const context = useContext(FundContext); if (!context) { throw new Error('useFundContext must be used within a FundCardProvider'); } return context; }