add redirects
This commit is contained in:
1
dist/assets/index-BrS4UPZI.css
vendored
Normal file
1
dist/assets/index-BrS4UPZI.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/index-DianSEHM.css
vendored
1
dist/assets/index-DianSEHM.css
vendored
File diff suppressed because one or more lines are too long
153
dist/assets/index-H9RMF-3p.js
vendored
153
dist/assets/index-H9RMF-3p.js
vendored
File diff suppressed because one or more lines are too long
161
dist/assets/index-woqmDgbc.js
vendored
Normal file
161
dist/assets/index-woqmDgbc.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
dist/index.html
vendored
4
dist/index.html
vendored
@@ -5,8 +5,8 @@
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>ЭКСА — Ваш мост в мир цифровых активов</title>
|
||||
<script type="module" crossorigin src="/assets/index-H9RMF-3p.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DianSEHM.css">
|
||||
<script type="module" crossorigin src="/assets/index-woqmDgbc.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BrS4UPZI.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
10
package-lock.json
generated
10
package-lock.json
generated
@@ -11,6 +11,7 @@
|
||||
"@reduxjs/toolkit": "^2.5.1",
|
||||
"@tanstack/react-query": "^5.100.9",
|
||||
"axios": "^1.7.9",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-easy-crop": "^5.5.7",
|
||||
@@ -3223,6 +3224,15 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode.react": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.2.0.tgz",
|
||||
"integrity": "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "19.2.5",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz",
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"@reduxjs/toolkit": "^2.5.1",
|
||||
"@tanstack/react-query": "^5.100.9",
|
||||
"axios": "^1.7.9",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-easy-crop": "^5.5.7",
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { PrimaryButton } from '@shared/ui'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { Notification, PrimaryButton } from '@shared/ui'
|
||||
import {
|
||||
useWalletBalance, useWalletAddresses, useTokensList,
|
||||
useRelayQuote, useExecuteRelaySwap, useSignSwap,
|
||||
useTrxSwapQuote, useFetchTrxQuote, useExecuteTrxSwap,
|
||||
type Chain, type RelaySwapResponse, type TrxSwapQuoteData,
|
||||
} from '@features/wallet'
|
||||
import { ROUTES } from '@shared/config/routes'
|
||||
import { useDebounce } from '@shared/lib/hooks/useDebounce'
|
||||
import { TOKENS_LIST, buildTokensFromBalance, useSwapForm } from '../../swap-form/model/useSwapForm'
|
||||
import { SwapCard } from '../../swap-form/ui/SwapCard'
|
||||
@@ -26,6 +29,9 @@ function nativeAddr(chain: string) {
|
||||
}
|
||||
|
||||
export function BridgeForm() {
|
||||
const navigate = useNavigate()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const {
|
||||
fromAmount, fromUsd,
|
||||
fromToken, toToken,
|
||||
@@ -37,6 +43,7 @@ export function BridgeForm() {
|
||||
const [toNetwork, setToNetwork] = useState('BSC')
|
||||
const [modalData, setModalData] = useState<RelaySwapResponse | null>(null)
|
||||
const [trxModalQuote, setTrxModalQuote] = useState<TrxSwapQuoteData | null>(null)
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null)
|
||||
|
||||
const isTrxNetwork = fromNetwork === 'TRX'
|
||||
|
||||
@@ -84,7 +91,7 @@ export function BridgeForm() {
|
||||
|
||||
const { data: quoteData } = useRelayQuote(quotePayload)
|
||||
const { mutate: executeSwap, isPending: isSwapping } = useExecuteRelaySwap()
|
||||
const { mutate: signSwap } = useSignSwap()
|
||||
const { mutate: signSwap, isPending: isSigning } = useSignSwap()
|
||||
|
||||
const trxQuotePayload = isTrxNetwork && parsedAmount > 0
|
||||
? { from: fromToken.symbol, to: toToken.symbol, amountHuman: debouncedAmount }
|
||||
@@ -92,7 +99,9 @@ export function BridgeForm() {
|
||||
|
||||
const { data: trxQuoteData } = useTrxSwapQuote(trxQuotePayload)
|
||||
const { mutate: fetchTrxQuote, isPending: isFetchingTrxQuote } = useFetchTrxQuote()
|
||||
const { mutate: executeTrxSwap } = useExecuteTrxSwap()
|
||||
const { mutate: executeTrxSwap, isPending: isExecutingTrxSwap } = useExecuteTrxSwap()
|
||||
|
||||
const isProcessing = isSigning || isExecutingTrxSwap
|
||||
|
||||
const displayToAmount = isTrxNetwork
|
||||
? (trxQuoteData?.expectedOutFormatted ?? '0')
|
||||
@@ -162,7 +171,23 @@ export function BridgeForm() {
|
||||
onClose={() => setModalData(null)}
|
||||
onConfirm={() => {
|
||||
const txData = modalData.steps[0]?.items[0]?.data
|
||||
if (txData) signSwap({ chain: fromNetwork as Chain, txData })
|
||||
if (txData) {
|
||||
setErrorMessage(null)
|
||||
signSwap(
|
||||
{ chain: fromNetwork as Chain, txData },
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'balance', fromNetwork] })
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'balance', toNetwork] })
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'portfolio'] })
|
||||
navigate(ROUTES.WALLET)
|
||||
},
|
||||
onError: (err) => {
|
||||
setErrorMessage(err instanceof Error ? err.message : 'Не удалось подписать транзакцию')
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
setModalData(null)
|
||||
}}
|
||||
/>
|
||||
@@ -176,11 +201,38 @@ export function BridgeForm() {
|
||||
amountHuman={fromAmount}
|
||||
onClose={() => setTrxModalQuote(null)}
|
||||
onConfirm={() => {
|
||||
executeTrxSwap(trxModalQuote.quoteId)
|
||||
setErrorMessage(null)
|
||||
executeTrxSwap(trxModalQuote.quoteId, {
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'balance', 'TRX'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'balance', toNetwork] })
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'portfolio'] })
|
||||
navigate(ROUTES.WALLET)
|
||||
},
|
||||
onError: (err) => {
|
||||
setErrorMessage(err instanceof Error ? err.message : 'Не удалось выполнить бридж')
|
||||
},
|
||||
})
|
||||
setTrxModalQuote(null)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isProcessing && (
|
||||
<Notification
|
||||
status="warning"
|
||||
message="Обработка транзакции..."
|
||||
onClose={() => {}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{errorMessage && (
|
||||
<Notification
|
||||
status="error"
|
||||
message={errorMessage}
|
||||
onClose={() => setErrorMessage(null)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -59,6 +59,15 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.qrWrap {
|
||||
align-self: center;
|
||||
padding: 12px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
line-height: 0;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary, rgba(255,255,255,0.5));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { QRCodeSVG } from 'qrcode.react'
|
||||
import { useWalletAddresses, type Chain } from '@features/wallet'
|
||||
import styles from './ReceiveModal.module.css'
|
||||
|
||||
@@ -87,6 +88,18 @@ export function ReceiveModal({ open, onClose, chain }: ReceiveModalProps) {
|
||||
{copied ? 'Скопировано!' : 'Копировать'}
|
||||
</button>
|
||||
</div>
|
||||
{address && (
|
||||
<div className={styles.qrWrap}>
|
||||
<QRCodeSVG
|
||||
value={address}
|
||||
size={196}
|
||||
level="M"
|
||||
bgColor="#ffffff"
|
||||
fgColor="#000000"
|
||||
marginSize={2}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { PrimaryButton } from '@shared/ui'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { Notification, PrimaryButton } from '@shared/ui'
|
||||
import {
|
||||
useWalletBalance, useWalletAddresses, useTokensList,
|
||||
useRelayQuote, useExecuteRelaySwap, useSignSwap,
|
||||
useTrxSwapQuote, useFetchTrxQuote, useExecuteTrxSwap,
|
||||
type Chain, type RelaySwapResponse, type TrxSwapQuoteData,
|
||||
} from '@features/wallet'
|
||||
import { ROUTES } from '@shared/config/routes'
|
||||
import { useDebounce } from '@shared/lib/hooks/useDebounce'
|
||||
import { TOKENS_LIST, buildTokensFromBalance, useSwapForm } from '../model/useSwapForm'
|
||||
import { SwapCard } from './SwapCard'
|
||||
@@ -26,6 +29,9 @@ function nativeAddr(chain: string) {
|
||||
}
|
||||
|
||||
export function SwapForm() {
|
||||
const navigate = useNavigate()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const {
|
||||
fromAmount, fromUsd,
|
||||
fromToken, toToken,
|
||||
@@ -36,6 +42,7 @@ export function SwapForm() {
|
||||
const [fromNetwork, setFromNetwork] = useState('ETH')
|
||||
const [modalData, setModalData] = useState<RelaySwapResponse | null>(null)
|
||||
const [trxModalQuote, setTrxModalQuote] = useState<TrxSwapQuoteData | null>(null)
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null)
|
||||
|
||||
const isTrxNetwork = fromNetwork === 'TRX'
|
||||
|
||||
@@ -75,7 +82,7 @@ export function SwapForm() {
|
||||
|
||||
const { data: quoteData } = useRelayQuote(quotePayload)
|
||||
const { mutate: executeSwap, isPending: isSwapping } = useExecuteRelaySwap()
|
||||
const { mutate: signSwap } = useSignSwap()
|
||||
const { mutate: signSwap, isPending: isSigning } = useSignSwap()
|
||||
|
||||
// ── TRX ─────────────────────────────────────────────────────────────────
|
||||
const trxQuotePayload = isTrxNetwork && parsedAmount > 0
|
||||
@@ -84,7 +91,9 @@ export function SwapForm() {
|
||||
|
||||
const { data: trxQuoteData } = useTrxSwapQuote(trxQuotePayload)
|
||||
const { mutate: fetchTrxQuote, isPending: isFetchingTrxQuote } = useFetchTrxQuote()
|
||||
const { mutate: executeTrxSwap } = useExecuteTrxSwap()
|
||||
const { mutate: executeTrxSwap, isPending: isExecutingTrxSwap } = useExecuteTrxSwap()
|
||||
|
||||
const isProcessing = isSigning || isExecutingTrxSwap
|
||||
|
||||
// ── Display values ───────────────────────────────────────────────────────
|
||||
const displayToAmount = isTrxNetwork
|
||||
@@ -153,7 +162,22 @@ export function SwapForm() {
|
||||
onClose={() => setModalData(null)}
|
||||
onConfirm={() => {
|
||||
const txData = modalData.steps[0]?.items[0]?.data
|
||||
if (txData) signSwap({ chain: fromNetwork as Chain, txData })
|
||||
if (txData) {
|
||||
setErrorMessage(null)
|
||||
signSwap(
|
||||
{ chain: fromNetwork as Chain, txData },
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'balance', fromNetwork] })
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'portfolio'] })
|
||||
navigate(ROUTES.WALLET)
|
||||
},
|
||||
onError: (err) => {
|
||||
setErrorMessage(err instanceof Error ? err.message : 'Не удалось подписать транзакцию')
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
setModalData(null)
|
||||
}}
|
||||
/>
|
||||
@@ -167,11 +191,37 @@ export function SwapForm() {
|
||||
amountHuman={fromAmount}
|
||||
onClose={() => setTrxModalQuote(null)}
|
||||
onConfirm={() => {
|
||||
executeTrxSwap(trxModalQuote.quoteId)
|
||||
setErrorMessage(null)
|
||||
executeTrxSwap(trxModalQuote.quoteId, {
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'balance', 'TRX'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'portfolio'] })
|
||||
navigate(ROUTES.WALLET)
|
||||
},
|
||||
onError: (err) => {
|
||||
setErrorMessage(err instanceof Error ? err.message : 'Не удалось выполнить свап')
|
||||
},
|
||||
})
|
||||
setTrxModalQuote(null)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isProcessing && (
|
||||
<Notification
|
||||
status="warning"
|
||||
message="Обработка транзакции..."
|
||||
onClose={() => {}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{errorMessage && (
|
||||
<Notification
|
||||
status="error"
|
||||
message={errorMessage}
|
||||
onClose={() => setErrorMessage(null)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user