This commit is contained in:
2026-06-18 15:27:03 +03:00
parent f17367658d
commit 594ba4fd07
4 changed files with 21 additions and 107 deletions

View File

@@ -60,10 +60,13 @@ export function useAddLp() {
const qc = useQueryClient()
return useMutation({
mutationFn: (input: LpDepositInput) => addLp(input),
// Депозит отражается в сети не мгновенно: баланс обновляем сразу, позиции — с задержкой,
// иначе ранний рефетч «мигнул» бы (позиции ещё нет). Паттерн из useStake.
// Депозит отражается в сети не мгновенно. Первый рефетч делаем не сразу, а спустя 1.5 с,
// и повторяем для позиций через 6 с — позиция может ещё не появиться на чейне. Паттерн из useStake.
onSettled: () => {
setTimeout(() => {
qc.invalidateQueries({ queryKey: ['wallet', 'balance', 'ETH'] })
qc.invalidateQueries({ queryKey: ['pools', 'positions'] })
}, 1500)
setTimeout(() => {
qc.invalidateQueries({ queryKey: ['pools', 'positions'] })
qc.invalidateQueries({ queryKey: ['wallet', 'balance', 'ETH'] })

View File

@@ -87,13 +87,12 @@
.range {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
gap: 12px;
margin-bottom: 20px;
}
.priceField,
.slippage {
.priceField {
display: flex;
flex-direction: column;
gap: 6px;
@@ -125,66 +124,6 @@
color: rgba(255, 255, 255, 0.3);
}
.options {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 20px;
}
.slippage {
width: 160px;
flex-shrink: 0;
}
/* Выбор способа оплаты: ETH / WETH — взаимоисключающие «таблетки». */
.payment {
display: flex;
flex-direction: column;
gap: 6px;
}
.segment {
display: flex;
gap: 8px;
}
.segItem,
.segActive {
padding: 7px 16px;
border-radius: 999px;
border: 1px solid var(--glass-border);
background: transparent;
color: var(--text-secondary);
font-family: var(--font-sans);
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: background 0.18s, border-color 0.18s, color 0.18s, opacity 0.18s;
}
/* Невыбранный вариант «гаснет». */
.segItem {
opacity: 0.45;
}
.segItem:hover {
opacity: 0.75;
border-color: rgba(255, 255, 255, 0.18);
}
.segActive {
background: rgba(74, 109, 255, 0.15);
border-color: var(--interactive);
color: var(--text-primary);
}
.segItem:focus-visible,
.segActive:focus-visible {
outline: 2px solid var(--highlight);
outline-offset: 2px;
}
.quote {
background: var(--glass-bg);
border: 1px solid var(--glass-border);
@@ -218,6 +157,11 @@
text-align: right;
}
.feeValue {
font-size: 20px;
font-weight: 700;
}
.success {
color: var(--success);
}
@@ -267,12 +211,7 @@
padding: 16px;
}
.options {
flex-direction: column;
align-items: stretch;
}
.slippage {
width: 100%;
.range {
grid-template-columns: 1fr;
}
}

View File

@@ -14,13 +14,11 @@ interface Props {
priceLower: string
priceUpper: string
slippage: string
useNativeEth: boolean
onAmount0Change: (v: string) => void
onAmount1Change: (v: string) => void
onPriceLowerChange: (v: string) => void
onPriceUpperChange: (v: string) => void
onSlippageChange: (v: string) => void
onUseNativeEthChange: (v: boolean) => void
onSubmit: () => void
}
@@ -94,13 +92,11 @@ export function LpDepositCard({
priceLower,
priceUpper,
slippage,
useNativeEth,
onAmount0Change,
onAmount1Change,
onPriceLowerChange,
onPriceUpperChange,
onSlippageChange,
onUseNativeEthChange,
onSubmit,
}: Props) {
if (!pool) {
@@ -145,10 +141,7 @@ export function LpDepositCard({
<div className={styles.range}>
<PriceInput label="Мин." value={priceLower} onChange={onPriceLowerChange} />
<PriceInput label="Макс." value={priceUpper} onChange={onPriceUpperChange} />
</div>
<div className={styles.options}>
<label className={styles.slippage}>
<label className={styles.priceField}>
<span className={styles.priceLabel}>Проскальзывание, %</span>
<input
className={styles.priceInput}
@@ -162,27 +155,6 @@ export function LpDepositCard({
placeholder="1"
/>
</label>
<div className={styles.payment}>
<span className={styles.priceLabel}>Оплата</span>
<div className={styles.segment} role="group" aria-label="Способ оплаты">
<button
type="button"
className={!useNativeEth ? styles.segActive : styles.segItem}
aria-pressed={!useNativeEth}
onClick={() => onUseNativeEthChange(false)}
>
WETH
</button>
<button
type="button"
className={useNativeEth ? styles.segActive : styles.segItem}
aria-pressed={useNativeEth}
onClick={() => onUseNativeEthChange(true)}
>
ETH
</button>
</div>
</div>
</div>
<div className={styles.quote} data-loading={quoteFetching ? 'true' : undefined}>
@@ -196,7 +168,7 @@ export function LpDepositCard({
</div>
<div className={styles.quoteRow}>
<span className={styles.quoteLabel}>Комиссия сервиса (0.7%)</span>
<span className={styles.quoteValue}>{feeUsd}</span>
<span className={`${styles.quoteValue} ${styles.feeValue}`}>{feeUsd}</span>
</div>
<div className={styles.quoteRow}>
<span className={styles.quoteLabel}>Годовая доходность (APR)</span>

View File

@@ -37,8 +37,8 @@ export function PoolsWidget() {
const [priceLower, setPriceLower] = useState('')
const [priceUpper, setPriceUpper] = useState('')
const [slippage, setSlippage] = useState('1')
// По умолчанию оплата идёт в WETH (ERC-20); юзер может переключить на нативный ETH.
const [useNativeEth, setUseNativeEth] = useState(false)
// Оплата всегда идёт в WETH (ERC-20).
const useNativeEth = false
const [removeTarget, setRemoveTarget] = useState<LpPosition | null>(null)
const [toast, setToast] = useState<Toast>(null)
@@ -99,6 +99,8 @@ export function PoolsWidget() {
slippageBps: Number.isFinite(slippageNum) ? Math.round(slippageNum * 100) : undefined,
useNativeEth,
}
// Транзакция подтверждается в сети не мгновенно — предупреждаем юзера о возможном ожидании.
setToast({ status: 'info', message: 'Внесение в пул может занять несколько минут…' })
addM.mutate(input, {
onSuccess: () => {
setToast({ status: 'success', message: `Депозит в пул ${pool.symbol0}/${pool.symbol1} выполнен` })
@@ -144,13 +146,11 @@ export function PoolsWidget() {
priceLower={priceLower}
priceUpper={priceUpper}
slippage={slippage}
useNativeEth={useNativeEth}
onAmount0Change={setAmount0}
onAmount1Change={setAmount1}
onPriceLowerChange={setPriceLower}
onPriceUpperChange={setPriceUpper}
onSlippageChange={setSlippage}
onUseNativeEthChange={setUseNativeEth}
onSubmit={handleSubmit}
/>
<LpPositionsPanel