fix
This commit is contained in:
@@ -60,10 +60,13 @@ export function useAddLp() {
|
|||||||
const qc = useQueryClient()
|
const qc = useQueryClient()
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (input: LpDepositInput) => addLp(input),
|
mutationFn: (input: LpDepositInput) => addLp(input),
|
||||||
// Депозит отражается в сети не мгновенно: баланс обновляем сразу, позиции — с задержкой,
|
// Депозит отражается в сети не мгновенно. Первый рефетч делаем не сразу, а спустя 1.5 с,
|
||||||
// иначе ранний рефетч «мигнул» бы (позиции ещё нет). Паттерн из useStake.
|
// и повторяем для позиций через 6 с — позиция может ещё не появиться на чейне. Паттерн из useStake.
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
|
setTimeout(() => {
|
||||||
qc.invalidateQueries({ queryKey: ['wallet', 'balance', 'ETH'] })
|
qc.invalidateQueries({ queryKey: ['wallet', 'balance', 'ETH'] })
|
||||||
|
qc.invalidateQueries({ queryKey: ['pools', 'positions'] })
|
||||||
|
}, 1500)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
qc.invalidateQueries({ queryKey: ['pools', 'positions'] })
|
qc.invalidateQueries({ queryKey: ['pools', 'positions'] })
|
||||||
qc.invalidateQueries({ queryKey: ['wallet', 'balance', 'ETH'] })
|
qc.invalidateQueries({ queryKey: ['wallet', 'balance', 'ETH'] })
|
||||||
|
|||||||
@@ -87,13 +87,12 @@
|
|||||||
|
|
||||||
.range {
|
.range {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.priceField,
|
.priceField {
|
||||||
.slippage {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
@@ -125,66 +124,6 @@
|
|||||||
color: rgba(255, 255, 255, 0.3);
|
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 {
|
.quote {
|
||||||
background: var(--glass-bg);
|
background: var(--glass-bg);
|
||||||
border: 1px solid var(--glass-border);
|
border: 1px solid var(--glass-border);
|
||||||
@@ -218,6 +157,11 @@
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.feeValue {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
.success {
|
.success {
|
||||||
color: var(--success);
|
color: var(--success);
|
||||||
}
|
}
|
||||||
@@ -267,12 +211,7 @@
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.options {
|
.range {
|
||||||
flex-direction: column;
|
grid-template-columns: 1fr;
|
||||||
align-items: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slippage {
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,13 +14,11 @@ interface Props {
|
|||||||
priceLower: string
|
priceLower: string
|
||||||
priceUpper: string
|
priceUpper: string
|
||||||
slippage: string
|
slippage: string
|
||||||
useNativeEth: boolean
|
|
||||||
onAmount0Change: (v: string) => void
|
onAmount0Change: (v: string) => void
|
||||||
onAmount1Change: (v: string) => void
|
onAmount1Change: (v: string) => void
|
||||||
onPriceLowerChange: (v: string) => void
|
onPriceLowerChange: (v: string) => void
|
||||||
onPriceUpperChange: (v: string) => void
|
onPriceUpperChange: (v: string) => void
|
||||||
onSlippageChange: (v: string) => void
|
onSlippageChange: (v: string) => void
|
||||||
onUseNativeEthChange: (v: boolean) => void
|
|
||||||
onSubmit: () => void
|
onSubmit: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,13 +92,11 @@ export function LpDepositCard({
|
|||||||
priceLower,
|
priceLower,
|
||||||
priceUpper,
|
priceUpper,
|
||||||
slippage,
|
slippage,
|
||||||
useNativeEth,
|
|
||||||
onAmount0Change,
|
onAmount0Change,
|
||||||
onAmount1Change,
|
onAmount1Change,
|
||||||
onPriceLowerChange,
|
onPriceLowerChange,
|
||||||
onPriceUpperChange,
|
onPriceUpperChange,
|
||||||
onSlippageChange,
|
onSlippageChange,
|
||||||
onUseNativeEthChange,
|
|
||||||
onSubmit,
|
onSubmit,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
if (!pool) {
|
if (!pool) {
|
||||||
@@ -145,10 +141,7 @@ export function LpDepositCard({
|
|||||||
<div className={styles.range}>
|
<div className={styles.range}>
|
||||||
<PriceInput label="Мин." value={priceLower} onChange={onPriceLowerChange} />
|
<PriceInput label="Мин." value={priceLower} onChange={onPriceLowerChange} />
|
||||||
<PriceInput label="Макс." value={priceUpper} onChange={onPriceUpperChange} />
|
<PriceInput label="Макс." value={priceUpper} onChange={onPriceUpperChange} />
|
||||||
</div>
|
<label className={styles.priceField}>
|
||||||
|
|
||||||
<div className={styles.options}>
|
|
||||||
<label className={styles.slippage}>
|
|
||||||
<span className={styles.priceLabel}>Проскальзывание, %</span>
|
<span className={styles.priceLabel}>Проскальзывание, %</span>
|
||||||
<input
|
<input
|
||||||
className={styles.priceInput}
|
className={styles.priceInput}
|
||||||
@@ -162,27 +155,6 @@ export function LpDepositCard({
|
|||||||
placeholder="1"
|
placeholder="1"
|
||||||
/>
|
/>
|
||||||
</label>
|
</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>
|
||||||
|
|
||||||
<div className={styles.quote} data-loading={quoteFetching ? 'true' : undefined}>
|
<div className={styles.quote} data-loading={quoteFetching ? 'true' : undefined}>
|
||||||
@@ -196,7 +168,7 @@ export function LpDepositCard({
|
|||||||
</div>
|
</div>
|
||||||
<div className={styles.quoteRow}>
|
<div className={styles.quoteRow}>
|
||||||
<span className={styles.quoteLabel}>Комиссия сервиса (0.7%)</span>
|
<span className={styles.quoteLabel}>Комиссия сервиса (0.7%)</span>
|
||||||
<span className={styles.quoteValue}>{feeUsd}</span>
|
<span className={`${styles.quoteValue} ${styles.feeValue}`}>{feeUsd}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.quoteRow}>
|
<div className={styles.quoteRow}>
|
||||||
<span className={styles.quoteLabel}>Годовая доходность (APR)</span>
|
<span className={styles.quoteLabel}>Годовая доходность (APR)</span>
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ export function PoolsWidget() {
|
|||||||
const [priceLower, setPriceLower] = useState('')
|
const [priceLower, setPriceLower] = useState('')
|
||||||
const [priceUpper, setPriceUpper] = useState('')
|
const [priceUpper, setPriceUpper] = useState('')
|
||||||
const [slippage, setSlippage] = useState('1')
|
const [slippage, setSlippage] = useState('1')
|
||||||
// По умолчанию оплата идёт в WETH (ERC-20); юзер может переключить на нативный ETH.
|
// Оплата всегда идёт в WETH (ERC-20).
|
||||||
const [useNativeEth, setUseNativeEth] = useState(false)
|
const useNativeEth = false
|
||||||
const [removeTarget, setRemoveTarget] = useState<LpPosition | null>(null)
|
const [removeTarget, setRemoveTarget] = useState<LpPosition | null>(null)
|
||||||
const [toast, setToast] = useState<Toast>(null)
|
const [toast, setToast] = useState<Toast>(null)
|
||||||
|
|
||||||
@@ -99,6 +99,8 @@ export function PoolsWidget() {
|
|||||||
slippageBps: Number.isFinite(slippageNum) ? Math.round(slippageNum * 100) : undefined,
|
slippageBps: Number.isFinite(slippageNum) ? Math.round(slippageNum * 100) : undefined,
|
||||||
useNativeEth,
|
useNativeEth,
|
||||||
}
|
}
|
||||||
|
// Транзакция подтверждается в сети не мгновенно — предупреждаем юзера о возможном ожидании.
|
||||||
|
setToast({ status: 'info', message: 'Внесение в пул может занять несколько минут…' })
|
||||||
addM.mutate(input, {
|
addM.mutate(input, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setToast({ status: 'success', message: `Депозит в пул ${pool.symbol0}/${pool.symbol1} выполнен` })
|
setToast({ status: 'success', message: `Депозит в пул ${pool.symbol0}/${pool.symbol1} выполнен` })
|
||||||
@@ -144,13 +146,11 @@ export function PoolsWidget() {
|
|||||||
priceLower={priceLower}
|
priceLower={priceLower}
|
||||||
priceUpper={priceUpper}
|
priceUpper={priceUpper}
|
||||||
slippage={slippage}
|
slippage={slippage}
|
||||||
useNativeEth={useNativeEth}
|
|
||||||
onAmount0Change={setAmount0}
|
onAmount0Change={setAmount0}
|
||||||
onAmount1Change={setAmount1}
|
onAmount1Change={setAmount1}
|
||||||
onPriceLowerChange={setPriceLower}
|
onPriceLowerChange={setPriceLower}
|
||||||
onPriceUpperChange={setPriceUpper}
|
onPriceUpperChange={setPriceUpper}
|
||||||
onSlippageChange={setSlippage}
|
onSlippageChange={setSlippage}
|
||||||
onUseNativeEthChange={setUseNativeEth}
|
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
/>
|
/>
|
||||||
<LpPositionsPanel
|
<LpPositionsPanel
|
||||||
|
|||||||
Reference in New Issue
Block a user