/** * Copyright (c) TonTech. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ import { createContext, useCallback, useContext, useMemo, useState } from 'react'; import type { FC, PropsWithChildren } from 'react'; import type { SendTransactionReturnType } from '@ton/appkit'; import { useSendTransaction } from '../../hooks/use-send-transaction'; import type { SendRequest } from '../transaction/send'; export interface SendContextType { /** Function to submit the transaction */ onSubmit: () => void; /** Whether the transaction is currently loading */ isLoading: boolean; /** The error object if the transaction failed */ error?: Error | null; /** The receipt of the successful transaction */ receipt?: SendTransactionReturnType | null; /** Disable the button/interaction */ disabled?: boolean; } export const SendContext = createContext({ onSubmit: () => { throw new Error('onSubmit is not defined'); }, isLoading: false, }); export function useSendContext() { const context = useContext(SendContext); return context; } export interface SendProviderProps extends PropsWithChildren { /** The transaction request parameters */ request: SendRequest; /** Callback when an error occurs */ onError?: (error: Error) => void; /** Callback when the transaction is successful */ onSuccess?: (response: SendTransactionReturnType) => void; /** Disable the button/interaction */ disabled?: boolean; } export const SendProvider: FC = ({ children, request, onError, onSuccess, disabled = false }) => { const [receipt, setReceipt] = useState(null); const [isPreparing, setIsPreparing] = useState(false); const { mutateAsync: sendTransaction, isPending, error: mutationError, } = useSendTransaction({ mutation: { onSuccess: (data) => { setReceipt(data); onSuccess?.(data); }, onError: (err) => { onError?.(err); }, }, }); const handleSubmit = useCallback(async () => { if (disabled || isPreparing || isPending) { return; } setIsPreparing(true); try { const transactionRequest = typeof request === 'function' ? await request() : await request; if (!transactionRequest) { return; } await sendTransaction(transactionRequest); } catch (e) { const error = e instanceof Error ? e : new Error(String(e)); onError?.(error); } finally { setIsPreparing(false); } }, [sendTransaction, request, disabled, isPreparing, isPending, onError]); const value = useMemo( () => ({ error: mutationError, isLoading: isPreparing || isPending, onSubmit: handleSubmit, receipt, disabled, }), [mutationError, isPreparing, isPending, handleSubmit, receipt, disabled], ); return {children}; };