This commit is contained in:
2026-06-18 16:03:06 +03:00
parent 7236bab31b
commit 5c74b54c82
6 changed files with 32 additions and 23 deletions

View File

@@ -1,9 +1,16 @@
import { COIN_ICONS } from '@shared/assets/coins'
/** Wrapper-токены → их нативные аналоги (WETH→ETH, WBTC→BTC). */
const NATIVE_SYMBOL: Record<string, string> = { WETH: 'ETH', WBTC: 'BTC' }
/** Отображаемый символ: wrapper-токены показываем как нативные (WETH→ETH, WBTC→BTC). */
export function displaySymbol(symbol: string): string {
return NATIVE_SYMBOL[symbol] ?? symbol
}
/** Иконка по символу токена: WETH→ETH, WBTC→BTC, иначе по тикеру (может вернуть undefined). */
export function coinIcon(symbol: string): string | undefined {
const map: Record<string, string> = { WETH: 'ETH', WBTC: 'BTC' }
return COIN_ICONS[map[symbol] ?? symbol]
return COIN_ICONS[displaySymbol(symbol)]
}
/** feeTier (сотые доли процента) → человекочитаемые проценты: 3000 → «0.3%». */

View File

@@ -2,7 +2,7 @@ import { PrimaryButton } from '@shared/ui'
import { truncateDecimals } from '@shared/lib/utils/truncateDecimals'
import type { Pool, LpQuote } from '@features/pools'
import { useWalletBalance, type WalletBalanceData } from '@features/wallet'
import { formatFeeTier } from '../model/meta'
import { formatFeeTier, displaySymbol } from '../model/meta'
import styles from './LpDepositCard.module.css'
interface Props {
@@ -26,10 +26,11 @@ interface Props {
const DASH = '—'
const decimalRe = /^(\d+\.?\d*|\.?\d*)$/
// Баланс ноги по символу: нативный токен (chain === символ) берём из native, остальное — из tokens.
// Баланс ноги по символу. Wrapper-токен нативной монеты (WETH на ETH) показываем как баланс
// нативной монеты; остальные токены берём из tokens по исходному символу.
function legBalance(wb: WalletBalanceData | undefined, symbol: string): string {
if (!wb) return '0'
if (symbol === wb.chain) return wb.native.formatted
if (displaySymbol(symbol) === wb.chain) return wb.native.formatted
return wb.tokens[symbol]?.formatted ?? '0'
}
@@ -141,7 +142,7 @@ export function LpDepositCard({
<div className={styles.card}>
<div className={styles.top}>
<span className={styles.pair}>
{pool.symbol0}/{pool.symbol1}
{displaySymbol(pool.symbol0)}/{displaySymbol(pool.symbol1)}
</span>
<span className={styles.fee}>{formatFeeTier(pool.feeTier)}</span>
</div>
@@ -149,20 +150,20 @@ export function LpDepositCard({
<span className={styles.tag}>Суммы взноса</span>
<div className={styles.amounts}>
<AmountInput
symbol={pool.symbol0}
symbol={displaySymbol(pool.symbol0)}
value={amount0}
onChange={onAmount0Change}
balance={legBalance(walletBalance, pool.symbol0)}
/>
<AmountInput
symbol={pool.symbol1}
symbol={displaySymbol(pool.symbol1)}
value={amount1}
onChange={onAmount1Change}
balance={legBalance(walletBalance, pool.symbol1)}
/>
</div>
<span className={styles.tag}>Диапазон цен ({pool.symbol1} за {pool.symbol0})</span>
<span className={styles.tag}>Диапазон цен ({displaySymbol(pool.symbol1)} за {displaySymbol(pool.symbol0)})</span>
<div className={styles.range}>
<PriceInput label="Мин." value={priceLower} onChange={onPriceLowerChange} />
<PriceInput label="Макс." value={priceUpper} onChange={onPriceUpperChange} />
@@ -184,11 +185,11 @@ export function LpDepositCard({
<div className={styles.quote} data-loading={quoteFetching ? 'true' : undefined}>
<div className={styles.quoteRow}>
<span className={styles.quoteLabel}>Взнос {pool.symbol0}</span>
<span className={styles.quoteLabel}>Взнос {displaySymbol(pool.symbol0)}</span>
<span className={styles.quoteValue}>{amount0Out}</span>
</div>
<div className={styles.quoteRow}>
<span className={styles.quoteLabel}>Взнос {pool.symbol1}</span>
<span className={styles.quoteLabel}>Взнос {displaySymbol(pool.symbol1)}</span>
<span className={styles.quoteValue}>{amount1Out}</span>
</div>
<div className={styles.quoteRow}>
@@ -203,7 +204,7 @@ export function LpDepositCard({
{insufficient && (
<p className={styles.warning}>
Недостаточно средств{shortLeg ? `: не хватает ${shortLeg.symbol}` : ''}. Пополните баланс.
Недостаточно средств{shortLeg ? `: не хватает ${displaySymbol(shortLeg.symbol)}` : ''}. Пополните баланс.
</p>
)}

View File

@@ -1,7 +1,7 @@
import { Spinner } from '@shared/ui'
import { truncateDecimals } from '@shared/lib/utils/truncateDecimals'
import type { LpPosition } from '@features/pools'
import { formatFeeTier } from '../model/meta'
import { formatFeeTier, displaySymbol } from '../model/meta'
import styles from './LpPositionsPanel.module.css'
interface Props {
@@ -43,7 +43,7 @@ export function LpPositionsPanel({ positions, onRemove, removePending, isLoading
<div key={p.tokenId} className={styles.pos}>
<div className={styles.posTop}>
<span className={styles.coin}>
{p.symbol0}/{p.symbol1}
{displaySymbol(p.symbol0)}/{displaySymbol(p.symbol1)}
<span className={styles.fee}>{formatFeeTier(p.feeTier)}</span>
</span>
<span className={`${styles.badge} ${p.inRange ? styles.badgeActive : styles.badgeWarn}`}>
@@ -59,17 +59,17 @@ export function LpPositionsPanel({ positions, onRemove, removePending, isLoading
</span>
</div>
<div className={styles.row}>
<span className={styles.label}>{p.symbol0}</span>
<span className={styles.label}>{displaySymbol(p.symbol0)}</span>
<span className={styles.value}>{truncateDecimals(p.currentAmount0Human, 8)}</span>
</div>
<div className={styles.row}>
<span className={styles.label}>{p.symbol1}</span>
<span className={styles.label}>{displaySymbol(p.symbol1)}</span>
<span className={styles.value}>{truncateDecimals(p.currentAmount1Human, 8)}</span>
</div>
<div className={styles.row}>
<span className={styles.label}>Комиссии к выводу</span>
<span className={`${styles.value} ${styles.success}`}>
{truncateDecimals(p.feesOwed0Human, 8)} {p.symbol0} · {truncateDecimals(p.feesOwed1Human, 8)} {p.symbol1}
{truncateDecimals(p.feesOwed0Human, 8)} {displaySymbol(p.symbol0)} · {truncateDecimals(p.feesOwed1Human, 8)} {displaySymbol(p.symbol1)}
</span>
</div>
</div>

View File

@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react'
import type { LpPosition } from '@features/pools'
import { formatFeeTier } from '../model/meta'
import { formatFeeTier, displaySymbol } from '../model/meta'
import styles from './LpRemoveModal.module.css'
interface Props {
@@ -36,7 +36,7 @@ export function LpRemoveModal({ position, pending, onConfirm, onClose }: Props)
<div className={styles.token}>
<span className={styles.tokenLabel}>Позиция</span>
<span className={styles.tokenAmount}>
{position.symbol0}/{position.symbol1}
{displaySymbol(position.symbol0)}/{displaySymbol(position.symbol1)}
</span>
<span className={styles.tokenMeta}>
{formatFeeTier(position.feeTier)} · #{position.tokenId}

View File

@@ -1,7 +1,7 @@
import { useMemo, useState } from 'react'
import { Spinner } from '@shared/ui'
import type { Pool } from '@features/pools'
import { formatFeeTier } from '../model/meta'
import { formatFeeTier, displaySymbol } from '../model/meta'
import styles from './PoolsTable.module.css'
interface Props {
@@ -35,7 +35,7 @@ function formatApr(value: number | null): string {
}
function pairName(p: Pool): string {
return `${p.symbol0}/${p.symbol1}`
return `${displaySymbol(p.symbol0)}/${displaySymbol(p.symbol1)}`
}
// Числовые поля могут быть null — null уходит вниз независимо от направления.
@@ -140,7 +140,7 @@ export function PoolsTable({ pools, selected, onSelect, loading, error }: Props)
>
<td className={styles.tdLeft}>
<span className={styles.pairName}>
{p.symbol0}/{p.symbol1}
{displaySymbol(p.symbol0)}/{displaySymbol(p.symbol1)}
</span>
</td>
<td>

View File

@@ -11,6 +11,7 @@ import {
type LpDepositInput,
type LpPosition,
} from '@features/pools'
import { displaySymbol } from '../model/meta'
import { PoolsTable } from './PoolsTable'
import { LpDepositCard } from './LpDepositCard'
import { LpPositionsPanel } from './LpPositionsPanel'
@@ -103,7 +104,7 @@ export function PoolsWidget() {
setToast({ status: 'info', message: 'Внесение в пул может занять несколько минут…' })
addM.mutate(input, {
onSuccess: () => {
setToast({ status: 'success', message: `Депозит в пул ${pool.symbol0}/${pool.symbol1} выполнен` })
setToast({ status: 'success', message: `Депозит в пул ${displaySymbol(pool.symbol0)}/${displaySymbol(pool.symbol1)} выполнен` })
setAmount0('')
setAmount1('')
},