UNPKG

@bluvo/react

Version:

React hooks for Bluvo SDK - Framework-agnostic state machine for crypto withdrawals

132 lines (131 loc) 6.01 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useBluvoFlow = useBluvoFlow; const react_1 = require("react"); const useFlowMachine_1 = require("./useFlowMachine"); function useBluvoFlow(options) { const [flowClient] = (0, react_1.useState)(() => { // Lazy import to avoid SSR issues const { BluvoFlowClient } = require('@bluvo/sdk-ts'); return new BluvoFlowClient(options); }); const [flowMachine, setFlowMachine] = (0, react_1.useState)(null); const [exchanges, setExchanges] = (0, react_1.useState)([]); const [exchangesLoading, setExchangesLoading] = (0, react_1.useState)(false); const [exchangesError, setExchangesError] = (0, react_1.useState)(null); const closeOAuthWindowRef = (0, react_1.useRef)(null); const flow = (0, useFlowMachine_1.useFlowMachine)(flowMachine); const startWithdrawalFlow = (0, react_1.useCallback)(async (flowOptions) => { const result = await flowClient.startWithdrawalFlow(flowOptions); setFlowMachine(result.machine); closeOAuthWindowRef.current = result.closeOAuthWindow; return result; }, [flowClient]); const resumeWithdrawalFlow = (0, react_1.useCallback)(async (flowOptions) => { const result = await flowClient.resumeWithdrawalFlow(flowOptions); setFlowMachine(result.machine); return result; }, [flowClient]); const requestQuote = (0, react_1.useCallback)(async (options) => { await flowClient.requestQuote(options); }, [flowClient]); const executeWithdrawal = (0, react_1.useCallback)(async (quoteId) => { await flowClient.executeWithdrawal(quoteId); }, [flowClient]); const submit2FA = (0, react_1.useCallback)(async (code) => { await flowClient.submit2FA(code); }, [flowClient]); const submitSMS = (0, react_1.useCallback)(async (code) => { await flowClient.submitSMS(code); }, [flowClient]); const retryWithdrawal = (0, react_1.useCallback)(async () => { await flowClient.retryWithdrawal(); }, [flowClient]); const listExchanges = (0, react_1.useCallback)(async (status) => { setExchangesLoading(true); setExchangesError(null); try { const result = await flowClient.loadExchanges(status); setExchanges(result); return result; } catch (error) { const errorObj = error instanceof Error ? error : new Error('Failed to load exchanges'); setExchangesError(errorObj); throw errorObj; } finally { setExchangesLoading(false); } }, [flowClient]); const cancel = (0, react_1.useCallback)(() => { flowClient.cancel(); setFlowMachine(null); if (closeOAuthWindowRef.current) { closeOAuthWindowRef.current(); closeOAuthWindowRef.current = null; } }, [flowClient]); // TEST METHOD - For testing withdrawal completion without real transactions const testWithdrawalComplete = (0, react_1.useCallback)((transactionId) => { flowClient.testWithdrawalComplete(transactionId); }, [flowClient]); // Cleanup on unmount (0, react_1.useEffect)(() => { return () => { flowClient.dispose(); if (closeOAuthWindowRef.current) { closeOAuthWindowRef.current(); } }; }, [flowClient]); return { // State ...flow, // Actions listExchanges, startWithdrawalFlow, resumeWithdrawalFlow, requestQuote, executeWithdrawal, submit2FA, submitSMS, retryWithdrawal, cancel, testWithdrawalComplete, // TEST METHOD // Computed state helpers isExchangesLoading: exchangesLoading || flow.state?.type === 'exchanges:loading', isExchangesReady: flow.state?.type === 'exchanges:ready' || exchanges.length > 0, exchangesError: exchangesError || (flow.state?.type === 'exchanges:error' ? flow.error || null : null), isOAuthPending: flow.state?.type === 'oauth:waiting' || flow.state?.type === 'oauth:processing', isOAuthComplete: flow.state?.type === 'oauth:completed', isOAuthWindowBeenClosedByTheUser: flow.state?.type === 'oauth:window_closed_by_user', isWalletLoading: flow.state?.type === 'wallet:loading', isWalletReady: flow.state?.type === 'wallet:ready', isQuoteLoading: flow.state?.type === 'quote:requesting', isQuoteReady: flow.state?.type === 'quote:ready', isQuoteExpired: flow.state?.type === 'quote:expired', isWithdrawing: flow.state?.type?.startsWith('withdraw:') && flow.state?.type !== 'withdraw:completed' && flow.state?.type !== 'withdraw:fatal' && !flow.state?.type?.startsWith('withdraw:error') || false, isWithdrawalComplete: flow.state?.type === 'withdraw:completed', hasFatalError: flow.state?.type === 'withdraw:fatal', requires2FA: flow.state?.type === 'withdraw:error2FA', requiresValid2FAMethod: (flow.state?.type === 'withdraw:fatal' && flow.error?.message?.includes('Two-factor authentication method not supported')) || false, requiresSMS: flow.state?.type === 'withdraw:errorSMS', requiresKYC: flow.state?.type === 'withdraw:errorKYC', hasInsufficientBalance: flow.state?.type === 'withdraw:errorBalance', canRetry: flow.state?.type === 'withdraw:retrying', invalid2FAAttempts: flow.context?.invalid2FAAttempts || 0, // Data exchanges: flow.context?.exchanges || exchanges, walletBalances: flow.context?.walletBalances || [], quote: flow.context?.quote, withdrawal: flow.context?.withdrawal, valid2FAMethods: flow.context?.errorDetails?.valid2FAMethods, // Client instance (for advanced use) client: flowClient }; }