14.05.2026 rip

This commit is contained in:
2026-05-14 23:39:47 +03:00
parent 0d114e12c2
commit 7c8e812d4b
6 changed files with 306 additions and 14 deletions

View File

@@ -1,12 +1,18 @@
import { useState, useEffect } from 'react'
import { PrimaryButton } from '@shared/ui'
import { useWalletBalance, useWalletAddresses, useTokensList, useRelayQuote, useExecuteRelaySwap, useSignSwap, type Chain, type RelaySwapResponse } from '@features/wallet'
import {
useWalletBalance, useWalletAddresses, useTokensList,
useRelayQuote, useExecuteRelaySwap, useSignSwap,
useTrxSwapQuote, useFetchTrxQuote, useExecuteTrxSwap,
type Chain, type RelaySwapResponse, type TrxSwapQuoteData,
} from '@features/wallet'
import { useDebounce } from '@shared/lib/hooks/useDebounce'
import { TOKENS_LIST, buildTokensFromBalance, useSwapForm } from '../model/useSwapForm'
import { SwapCard } from './SwapCard'
import { SwapDirectionButton } from './SwapDirectionButton'
import { SwapInfoPanel } from './SwapInfoPanel'
import { SwapConfirmModal } from './SwapConfirmModal'
import { TrxConfirmModal } from './TrxConfirmModal'
import styles from './SwapForm.module.css'
@@ -29,6 +35,9 @@ export function SwapForm() {
const [fromNetwork, setFromNetwork] = useState('ETH')
const [modalData, setModalData] = useState<RelaySwapResponse | null>(null)
const [trxModalQuote, setTrxModalQuote] = useState<TrxSwapQuoteData | null>(null)
const isTrxNetwork = fromNetwork === 'TRX'
const { data: walletData } = useWalletBalance(fromNetwork as Chain)
const tokenOptions = walletData ? buildTokensFromBalance(walletData) : TOKENS_LIST
@@ -43,13 +52,15 @@ export function SwapForm() {
const { data: addresses } = useWalletAddresses()
const { data: tokensList } = useTokensList()
const parsedAmount = parseFloat(debouncedAmount)
// ── Relay (ETH / BSC / SOL) ─────────────────────────────────────────────
const chainId = CHAIN_ID[fromNetwork]
const walletAddress = addresses?.find(a => a.chain === fromNetwork)?.address
const fromContract = tokensList?.find(t => t.chain === fromNetwork && t.symbol === fromToken.symbol)?.contract ?? nativeAddr(fromNetwork)
const toContract = tokensList?.find(t => t.chain === fromNetwork && t.symbol === toToken.symbol)?.contract ?? nativeAddr(fromNetwork)
const parsedAmount = parseFloat(debouncedAmount)
const quotePayload = chainId && walletAddress && parsedAmount > 0
const quotePayload = !isTrxNetwork && chainId && walletAddress && parsedAmount > 0
? {
user: walletAddress,
recipient: walletAddress,
@@ -66,15 +77,44 @@ export function SwapForm() {
const { mutate: executeSwap, isPending: isSwapping } = useExecuteRelaySwap()
const { mutate: signSwap } = useSignSwap()
const displayToAmount = quoteData?.details.currencyOut.amountFormatted ?? '0'
const displayToUsd = quoteData?.details.currencyOut.amountUsd
const gasFee = quoteData?.fees.gas.amountUsd
// ── TRX ─────────────────────────────────────────────────────────────────
const trxQuotePayload = isTrxNetwork && parsedAmount > 0
? { from: fromToken.symbol, to: toToken.symbol, amountHuman: debouncedAmount }
: null
const { data: trxQuoteData } = useTrxSwapQuote(trxQuotePayload)
const { mutate: fetchTrxQuote, isPending: isFetchingTrxQuote } = useFetchTrxQuote()
const { mutate: executeTrxSwap } = useExecuteTrxSwap()
// ── Display values ───────────────────────────────────────────────────────
const displayToAmount = isTrxNetwork
? (trxQuoteData?.expectedOutFormatted ?? '0')
: (quoteData?.details.currencyOut.amountFormatted ?? '0')
const displayToUsd = isTrxNetwork
? undefined
: quoteData?.details.currencyOut.amountUsd
const gasFee = isTrxNetwork
? trxQuoteData?.fees.network.amountUsd?.toString()
: quoteData?.fees.gas.amountUsd
const isButtonDisabled = isTrxNetwork
? parsedAmount <= 0 || isFetchingTrxQuote
: !quotePayload || isSwapping
function handleSwap() {
if (!quotePayload) return
executeSwap(quotePayload, {
onSuccess: (data) => setModalData(data),
})
if (isTrxNetwork) {
if (!trxQuotePayload) return
fetchTrxQuote(trxQuotePayload, {
onSuccess: (quote) => setTrxModalQuote(quote),
})
} else {
if (!quotePayload) return
executeSwap(quotePayload, {
onSuccess: (data) => setModalData(data),
})
}
}
return (
@@ -105,7 +145,7 @@ export function SwapForm() {
<SwapInfoPanel gasFee={gasFee} />
<PrimaryButton onClick={handleSwap} disabled={!quotePayload || isSwapping} />
<PrimaryButton onClick={handleSwap} disabled={isButtonDisabled} />
{modalData && (
<SwapConfirmModal
@@ -118,6 +158,20 @@ export function SwapForm() {
}}
/>
)}
{trxModalQuote && (
<TrxConfirmModal
quote={trxModalQuote}
fromSymbol={fromToken.symbol}
toSymbol={toToken.symbol}
amountHuman={fromAmount}
onClose={() => setTrxModalQuote(null)}
onConfirm={() => {
executeTrxSwap(trxModalQuote.quoteId)
setTrxModalQuote(null)
}}
/>
)}
</div>
)
}