14.05.2026 rip
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
export { useAllWalletBalances, usePrices, useSendWallet, useWalletAddresses } from './model/useWalletData'
|
||||
export { useAllWalletBalances, usePrices, useSendWallet, useWalletAddresses, useWalletBalance } from './model/useWalletData'
|
||||
export type { Chain, FormattedAmount, WalletBalanceData, PriceEntry, SendWalletPayload, SendWalletResponse, WalletAddress } from './api/walletApi'
|
||||
export { CHAINS } from './api/walletApi'
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import { useQuery, useQueries, useMutation } from '@tanstack/react-query'
|
||||
import { getWalletBalance, getPrices, sendWallet, getWalletAddresses, CHAINS, type Chain, type SendWalletPayload } from '../api/walletApi'
|
||||
|
||||
export function useWalletBalance(chain: Chain) {
|
||||
return useQuery({
|
||||
queryKey: ['wallet', 'balance', chain],
|
||||
queryFn: () => getWalletBalance(chain),
|
||||
staleTime: 30_000,
|
||||
})
|
||||
}
|
||||
|
||||
export function useAllWalletBalances() {
|
||||
return useQueries({
|
||||
queries: CHAINS.map(chain => ({
|
||||
|
||||
@@ -4,6 +4,7 @@ import eth from '@shared/assets/eth.svg'
|
||||
import sol from '@shared/assets/sol.svg'
|
||||
import trx from '@shared/assets/trx.svg'
|
||||
import arb from '@shared/assets/arb.svg'
|
||||
import type { WalletBalanceData } from '@features/wallet'
|
||||
|
||||
export interface Token {
|
||||
symbol: string
|
||||
@@ -27,6 +28,76 @@ const TOKENS: Record<string, Token> = {
|
||||
|
||||
export const TOKENS_LIST: Token[] = Object.values(TOKENS)
|
||||
|
||||
export const TOKEN_META: Record<string, { letter: string; color: string; logo?: string }> = {
|
||||
// Native / major
|
||||
BTC: { letter: '₿', logo: btc, color: '#F7931A' },
|
||||
ETH: { letter: 'E', logo: eth, color: '#627EEA' },
|
||||
BNB: { letter: 'B', color: '#F3BA2F' },
|
||||
SOL: { letter: 'S', logo: sol, color: '#9945FF' },
|
||||
TRX: { letter: 'T', logo: trx, color: '#FF060A' },
|
||||
ARB: { letter: 'A', logo: arb, color: '#4A6DFF' },
|
||||
// Stablecoins
|
||||
USDC: { letter: '$', color: '#2775CA' },
|
||||
USDT: { letter: '$', color: '#26A17B' },
|
||||
DAI: { letter: 'D', color: '#F5AC37' },
|
||||
BUSD: { letter: 'B', color: '#F0B90B' },
|
||||
// ETH tokens
|
||||
WBTC: { letter: 'W', color: '#F7931A' },
|
||||
LINK: { letter: 'L', color: '#2A5ADA' },
|
||||
UNI: { letter: 'U', color: '#FF007A' },
|
||||
// BSC tokens
|
||||
WBNB: { letter: 'W', color: '#F3BA2F' },
|
||||
DOGE: { letter: 'D', color: '#C2A633' },
|
||||
// SOL tokens
|
||||
JUP: { letter: 'J', color: '#C7A52D' },
|
||||
WIF: { letter: 'W', color: '#9333EA' },
|
||||
BONK: { letter: 'B', color: '#FF8C00' },
|
||||
RAY: { letter: 'R', color: '#5AC4BE' },
|
||||
ORCA: { letter: 'O', color: '#1B8EF2' },
|
||||
PYTH: { letter: 'P', color: '#8B5CF6' },
|
||||
JTO: { letter: 'J', color: '#06B6D4' },
|
||||
W: { letter: 'W', color: '#6B7280' },
|
||||
PUMP: { letter: 'P', color: '#00D4AA' },
|
||||
POPCAT: { letter: 'P', color: '#FF6B6B' },
|
||||
TRUMP: { letter: 'T', color: '#E63946' },
|
||||
PENGU: { letter: 'P', color: '#60A5FA' },
|
||||
}
|
||||
|
||||
const CHAIN_NATIVE: Record<string, string> = {
|
||||
ETH: 'ETH', BSC: 'BNB', BTC: 'BTC', TRX: 'TRX', SOL: 'SOL',
|
||||
}
|
||||
|
||||
export function buildTokensFromBalance(data: WalletBalanceData): Token[] {
|
||||
const result: Token[] = []
|
||||
|
||||
const nativeSym = CHAIN_NATIVE[data.chain] ?? data.chain
|
||||
const nativeMeta = TOKEN_META[nativeSym]
|
||||
result.push({
|
||||
symbol: nativeSym,
|
||||
letter: nativeMeta?.letter ?? nativeSym[0],
|
||||
color: nativeMeta?.color ?? '#888',
|
||||
logo: nativeMeta?.logo,
|
||||
network: data.chain,
|
||||
balance: parseFloat(data.native.formatted),
|
||||
usdRate: data.native.usdPrice,
|
||||
})
|
||||
|
||||
for (const [sym, info] of Object.entries(data.tokens)) {
|
||||
const meta = TOKEN_META[sym]
|
||||
result.push({
|
||||
symbol: sym,
|
||||
letter: meta?.letter ?? sym[0],
|
||||
color: meta?.color ?? '#888',
|
||||
logo: meta?.logo,
|
||||
network: data.chain,
|
||||
balance: parseFloat(info.formatted),
|
||||
usdRate: info.usdPrice,
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
const RATE = 82.2578
|
||||
|
||||
export function useSwapForm() {
|
||||
|
||||
@@ -50,6 +50,37 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* ── Network buttons ── */
|
||||
.networkPills {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.networkBtn {
|
||||
background: rgba(255, 255, 255, 0.07);
|
||||
color: var(--text-secondary);
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
padding: 4px 10px;
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-sans);
|
||||
font-weight: 600;
|
||||
transition: all 0.2s;
|
||||
letter-spacing: 0.4px;
|
||||
}
|
||||
|
||||
.networkBtn:hover {
|
||||
color: var(--text-primary);
|
||||
background: rgba(255, 255, 255, 0.13);
|
||||
}
|
||||
|
||||
.networkBtnActive {
|
||||
background: rgba(255, 255, 255, 0.18);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* ── Pills inside card (desktop only) ── */
|
||||
.pillsInner {
|
||||
display: flex;
|
||||
|
||||
@@ -12,13 +12,18 @@ interface Props {
|
||||
onTokenChange: (token: Token) => void
|
||||
onAmountChange?: (v: string) => void
|
||||
onSetPercent?: (p: number) => void
|
||||
selectedNetwork?: string
|
||||
onNetworkChange?: (network: string) => void
|
||||
}
|
||||
|
||||
const NETWORKS = ['BTC', 'ETH', 'BSC', 'TRX', 'SOL']
|
||||
|
||||
const PERCENTS = [25, 50, 100]
|
||||
|
||||
export function SwapCard({
|
||||
mode, token, tokenOptions, amount, usd, slippage,
|
||||
onTokenChange, onAmountChange, onSetPercent,
|
||||
selectedNetwork, onNetworkChange,
|
||||
}: Props) {
|
||||
const [intPart, decPart] = amount.split('.')
|
||||
|
||||
@@ -42,7 +47,21 @@ export function SwapCard({
|
||||
<div className={styles.card}>
|
||||
<div className={styles.top}>
|
||||
<div className={styles.label}>
|
||||
<span className={styles.tag}>{mode === 'from' ? 'ОТ' : 'К'}</span>
|
||||
{mode === 'from' ? (
|
||||
<div className={styles.networkPills}>
|
||||
{NETWORKS.map(n => (
|
||||
<button
|
||||
key={n}
|
||||
className={`${styles.networkBtn} ${n === selectedNetwork ? styles.networkBtnActive : ''}`}
|
||||
onClick={() => onNetworkChange?.(n)}
|
||||
>
|
||||
{n}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<span className={styles.tag}>К</span>
|
||||
)}
|
||||
<span className={styles.network}>{token.network}</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { PrimaryButton } from '@shared/ui'
|
||||
import { TOKENS_LIST, useSwapForm } from '../model/useSwapForm'
|
||||
import { useWalletBalance, type Chain } from '@features/wallet'
|
||||
import { TOKENS_LIST, buildTokensFromBalance, useSwapForm } from '../model/useSwapForm'
|
||||
import { RateRow } from './RateRow'
|
||||
import { SwapCard } from './SwapCard'
|
||||
import { SwapDirectionButton } from './SwapDirectionButton'
|
||||
@@ -17,17 +19,31 @@ export function SwapForm() {
|
||||
setFromToken, setToToken,
|
||||
} = useSwapForm()
|
||||
|
||||
const [fromNetwork, setFromNetwork] = useState('ETH')
|
||||
|
||||
const { data: walletData } = useWalletBalance(fromNetwork as Chain)
|
||||
const tokenOptions = walletData ? buildTokensFromBalance(walletData) : TOKENS_LIST
|
||||
|
||||
useEffect(() => {
|
||||
if (tokenOptions.length > 0) {
|
||||
setFromToken(tokenOptions[0])
|
||||
setToToken(tokenOptions[1] ?? tokenOptions[0])
|
||||
}
|
||||
}, [fromNetwork])
|
||||
|
||||
return (
|
||||
<div className={styles.form}>
|
||||
<SwapCard
|
||||
mode="from"
|
||||
token={fromToken}
|
||||
tokenOptions={TOKENS_LIST}
|
||||
tokenOptions={tokenOptions}
|
||||
amount={fromAmount}
|
||||
usd={fromUsd}
|
||||
onAmountChange={setFromAmount}
|
||||
onSetPercent={setPercent}
|
||||
onTokenChange={setFromToken}
|
||||
selectedNetwork={fromNetwork}
|
||||
onNetworkChange={setFromNetwork}
|
||||
/>
|
||||
|
||||
<SwapDirectionButton onClick={swapTokens} />
|
||||
@@ -35,7 +51,7 @@ export function SwapForm() {
|
||||
<SwapCard
|
||||
mode="to"
|
||||
token={toToken}
|
||||
tokenOptions={TOKENS_LIST}
|
||||
tokenOptions={tokenOptions}
|
||||
amount={toAmount}
|
||||
usd={toUsd}
|
||||
slippage="−0.16%"
|
||||
|
||||
Reference in New Issue
Block a user