import { useState } from 'react' import { Notification } from '@shared/ui' import { truncateDecimals } from '@shared/lib/utils/truncateDecimals' import { ChainToggle } from './ChainToggle' import { StakeCard } from './StakeCard' import { PositionsPanel } from './PositionsPanel' import { UnstakeModal } from './UnstakeModal' import { useStake, useUnstake, useClaim, getStakingErrorMessage, type StakeChain, type SolPosition, } from '@features/staking' import { CHAIN_META } from '../model/meta' import styles from './StakingWidget.module.css' type ModalState = { kind: 'eth'; amount: string } | { kind: 'sol'; position: SolPosition } | null type Toast = { status: 'success' | 'error' | 'info'; message: string } | null export function StakingWidget() { const [chain, setChain] = useState('ETH') const [amount, setAmount] = useState('') const [modal, setModal] = useState(null) const [toast, setToast] = useState(null) const stakeM = useStake() const unstakeM = useUnstake() const claimM = useClaim() function handleChain(next: StakeChain) { setChain(next) setAmount('') } // stakeAmountHuman — это сумма стейка A (= введённое − газ), её и отправляем на бэкенд. function handleStake(stakeAmountHuman: string) { stakeM.mutate( { chain, amountHuman: stakeAmountHuman }, { onSuccess: () => { setToast({ status: 'success', message: `Стейкинг ${truncateDecimals(stakeAmountHuman, 6)} ${CHAIN_META[chain].symbol} выполнен`, }) setAmount('') }, onError: (e) => setToast({ status: 'error', message: getStakingErrorMessage(e) }), } ) } function handleConfirm(mode?: 'swap' | 'queue') { if (modal?.kind === 'eth') { const selected = mode ?? 'swap' unstakeM.mutate( { chain: 'ETH', amountHuman: modal.amount, mode: selected }, { onSuccess: () => { setModal(null) setToast({ status: 'success', message: selected === 'queue' ? 'Заявка на вывод добавлена в очередь Lido' : 'Вывод stETH → ETH выполнен', }) }, onError: (e) => setToast({ status: 'error', message: getStakingErrorMessage(e) }), } ) } else if (modal?.kind === 'sol') { unstakeM.mutate( { chain: 'SOL', stakeAccount: modal.position.stakeAccount }, { onSuccess: (res) => { setModal(null) const withdrawn = 'action' in res && res.action === 'withdraw' setToast({ status: 'success', message: withdrawn ? 'Средства выведены на кошелёк' : 'Деактивация запущена — вывод через 1–2 эпохи', }) }, onError: (e) => setToast({ status: 'error', message: getStakingErrorMessage(e) }), } ) } } function handleClaim(requestId: string) { claimM.mutate(requestId, { onSuccess: () => setToast({ status: 'success', message: 'ETH забран на кошелёк' }), onError: (e) => setToast({ status: 'error', message: getStakingErrorMessage(e) }), }) } return (
setModal({ kind: 'eth', amount: amountHuman })} onUnstakeSol={(position) => setModal({ kind: 'sol', position })} onClaim={handleClaim} unstakePending={unstakeM.isPending} claimPending={claimM.isPending} />
{modal?.kind === 'eth' && ( setModal(null)} /> )} {modal?.kind === 'sol' && ( setModal(null)} /> )} {toast && setToast(null)} duration={5000} />}
) }