/** * 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 { useCallback, useMemo, useState } from 'react'; import type { ComponentProps, FC, ReactNode } from 'react'; import type { StakingQuoteDirection } from '@ton/appkit'; import clsx from 'clsx'; import { CenteredAmountInput } from '../../../../components/ui/centered-amount-input'; import { Tabs, TabsList, TabsTrigger, TabsContent } from '../../../../components/ui/tabs'; import { useI18n } from '../../../settings/hooks/use-i18n'; import { StakingBalanceBlock } from '../staking-balance-block'; import { StakingConfirmModal } from '../staking-confirm-modal'; import { StakingInfo } from '../staking-info'; import { SelectUnstakeMode } from '../select-unstake-mode'; import { StakingSettingsModal } from '../staking-settings-modal'; import styles from './staking-widget-ui.module.css'; import type { StakingContextType } from '../staking-widget-provider'; import { ButtonWithConnect } from '../../../../components/shared/button-with-connect'; import { AmountReversed } from '../../../../components/ui/amount-reversed'; import { LowBalanceModal } from '../../../../components/shared/low-balance-modal'; import { SettingsButton } from '../../../../components/shared/settings-button'; export type StakingWidgetRenderProps = StakingContextType & ComponentProps<'div'>; export const StakingWidgetUI: FC = ({ amount, canSubmit, isQuoteLoading, error, providerInfo, providerMetadata, stakingProvider, stakingProviders, setStakingProviderId, network, isProviderInfoLoading, setAmount, direction, quote, sendTransaction, isSendingTransaction, unstakeMode, setUnstakeMode, stakedBalance, isStakedBalanceLoading, onChangeDirection, isReversed, toggleReversed, reversedAmount, onMaxClick, balance, isBalanceLoading, isLowBalanceWarningOpen, lowBalanceMode, lowBalanceRequiredTon, onLowBalanceChange, onLowBalanceCancel, className, ...props }) => { const { t } = useI18n(); const [isSettingsOpen, setIsSettingsOpen] = useState(false); const [isConfirmOpen, setIsConfirmOpen] = useState(false); const receiveToken = providerMetadata?.receiveToken; const stakeToken = providerMetadata?.stakeToken; const buttonText = useMemo(() => { if (isSendingTransaction || isQuoteLoading) return t('staking.loading'); if (error) return t(error); return direction === 'stake' ? t('staking.continue') : t('staking.unstake'); }, [isSendingTransaction, isQuoteLoading, error, direction, t]); // Close the modal immediately; the build/send result (including errors) is surfaced // back in the widget's main button via the `error` from the provider. const handleConfirm = useCallback(() => { setIsConfirmOpen(false); sendTransaction().catch(() => { // Error is captured by the mutation and shown through the validator's `error` output. }); }, [sendTransaction]); const submitActions: ReactNode = (
setIsConfirmOpen(true)} > {buttonText} setIsSettingsOpen(true)} />
); return (
onChangeDirection(value as StakingQuoteDirection)}> {t('staking.stake')} {t('staking.unstake')} {/* ── STAKE TAB ── */}
{receiveToken && ( )}
{submitActions}
{/* ── UNSTAKE TAB ── */}
{receiveToken && ( )}
{submitActions}
setIsSettingsOpen(false)} provider={stakingProvider} providers={stakingProviders} onProviderChange={setStakingProviderId} network={network} /> setIsConfirmOpen(false)} onConfirm={handleConfirm} direction={direction} network={network} quote={quote} providerInfo={providerInfo} providerMetadata={providerMetadata} isProviderInfoLoading={isProviderInfoLoading} isQuoteLoading={isQuoteLoading} />
); };