14.05.2026 rip
This commit is contained in:
1
dist/assets/index-3J8Zo9Sf.css
vendored
1
dist/assets/index-3J8Zo9Sf.css
vendored
File diff suppressed because one or more lines are too long
60
dist/assets/index-CHC6dclK.js
vendored
Normal file
60
dist/assets/index-CHC6dclK.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/index-DdoCSUef.css
vendored
Normal file
1
dist/assets/index-DdoCSUef.css
vendored
Normal file
File diff suppressed because one or more lines are too long
60
dist/assets/index-Hdj79d7b.js
vendored
60
dist/assets/index-Hdj79d7b.js
vendored
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" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>ЭКСА — Ваш мост в мир цифровых активов</title>
|
<title>ЭКСА — Ваш мост в мир цифровых активов</title>
|
||||||
<script type="module" crossorigin src="/assets/index-Hdj79d7b.js"></script>
|
<script type="module" crossorigin src="/assets/index-CHC6dclK.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-3J8Zo9Sf.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-DdoCSUef.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -35,6 +35,12 @@ export interface SendWalletResponse {
|
|||||||
data: { txid: string; chain: Chain }
|
data: { txid: string; chain: Chain }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface WalletAddress {
|
||||||
|
chain: Chain
|
||||||
|
address: string
|
||||||
|
derivationPath: string
|
||||||
|
}
|
||||||
|
|
||||||
export const CHAINS: Chain[] = ['ETH', 'BSC', 'BTC', 'TRX', 'SOL']
|
export const CHAINS: Chain[] = ['ETH', 'BSC', 'BTC', 'TRX', 'SOL']
|
||||||
|
|
||||||
async function walletGet<T>(path: string, allowRetry: boolean = true): Promise<T> {
|
async function walletGet<T>(path: string, allowRetry: boolean = true): Promise<T> {
|
||||||
@@ -94,6 +100,11 @@ async function walletPost<T>(path: string, body: unknown, allowRetry: boolean =
|
|||||||
return data as T
|
return data as T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getWalletAddresses(): Promise<WalletAddress[]> {
|
||||||
|
const res = await walletGet<{ success: boolean; data: WalletAddress[] }>('/api/wallets')
|
||||||
|
return res.data
|
||||||
|
}
|
||||||
|
|
||||||
export async function getWalletBalance(chain: Chain): Promise<WalletBalanceData> {
|
export async function getWalletBalance(chain: Chain): Promise<WalletBalanceData> {
|
||||||
const res = await walletGet<{ success: boolean; data: WalletBalanceData }>(`/api/wallets/${chain}/balance`)
|
const res = await walletGet<{ success: boolean; data: WalletBalanceData }>(`/api/wallets/${chain}/balance`)
|
||||||
return res.data
|
return res.data
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export { useAllWalletBalances, usePrices, useSendWallet } from './model/useWalletData'
|
export { useAllWalletBalances, usePrices, useSendWallet, useWalletAddresses } from './model/useWalletData'
|
||||||
export type { Chain, FormattedAmount, WalletBalanceData, PriceEntry, SendWalletPayload, SendWalletResponse } from './api/walletApi'
|
export type { Chain, FormattedAmount, WalletBalanceData, PriceEntry, SendWalletPayload, SendWalletResponse, WalletAddress } from './api/walletApi'
|
||||||
export { CHAINS } from './api/walletApi'
|
export { CHAINS } from './api/walletApi'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useQuery, useQueries, useMutation } from '@tanstack/react-query'
|
import { useQuery, useQueries, useMutation } from '@tanstack/react-query'
|
||||||
import { getWalletBalance, getPrices, sendWallet, CHAINS, type Chain, type SendWalletPayload } from '../api/walletApi'
|
import { getWalletBalance, getPrices, sendWallet, getWalletAddresses, CHAINS, type Chain, type SendWalletPayload } from '../api/walletApi'
|
||||||
|
|
||||||
export function useAllWalletBalances() {
|
export function useAllWalletBalances() {
|
||||||
return useQueries({
|
return useQueries({
|
||||||
@@ -25,3 +25,11 @@ export function useSendWallet() {
|
|||||||
sendWallet(chain, payload),
|
sendWallet(chain, payload),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useWalletAddresses() {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ['wallet', 'addresses'],
|
||||||
|
queryFn: getWalletAddresses,
|
||||||
|
staleTime: 10 * 60 * 1000,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
1
src/widgets/receive-modal/index.ts
Normal file
1
src/widgets/receive-modal/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { ReceiveModal } from './ui/ReceiveModal'
|
||||||
151
src/widgets/receive-modal/ui/ReceiveModal.module.css
Normal file
151
src/widgets/receive-modal/ui/ReceiveModal.module.css
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
@keyframes dialogIn {
|
||||||
|
from { opacity: 0; transform: scale(0.96); }
|
||||||
|
to { opacity: 1; transform: scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog {
|
||||||
|
background: var(--bg-mid, #151520);
|
||||||
|
border: 1px solid var(--glass-border, rgba(255,255,255,0.1));
|
||||||
|
border-radius: 20px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 480px;
|
||||||
|
animation: dialogIn 0.18s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 20px 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary, #fff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.closeBtn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: var(--text-secondary, rgba(255,255,255,0.4));
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 4px;
|
||||||
|
line-height: 1;
|
||||||
|
transition: color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.closeBtn:hover {
|
||||||
|
color: var(--text-primary, #fff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
padding: 20px 24px 24px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--text-secondary, rgba(255,255,255,0.5));
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fieldRow {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addressInput {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
background: var(--glass-bg, rgba(255,255,255,0.05));
|
||||||
|
border: 1px solid var(--glass-border, rgba(255,255,255,0.1));
|
||||||
|
border-radius: 10px;
|
||||||
|
color: var(--text-primary, #fff);
|
||||||
|
font-family: var(--font-mono, monospace);
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
outline: none;
|
||||||
|
cursor: text;
|
||||||
|
transition: border-color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addressInput:focus {
|
||||||
|
border-color: var(--interactive, #4a6dff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyBtn {
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 40px;
|
||||||
|
padding: 0 16px;
|
||||||
|
background: rgba(0, 196, 140, 0.12);
|
||||||
|
border: 1px solid rgba(0, 196, 140, 0.3);
|
||||||
|
color: #00c48c;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-family: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s, border-color 0.2s, color 0.2s;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyBtn:hover:not(:disabled) {
|
||||||
|
background: rgba(0, 196, 140, 0.25);
|
||||||
|
border-color: #00c48c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyBtn:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyBtnDone {
|
||||||
|
background: rgba(0, 196, 140, 0.25);
|
||||||
|
border-color: #00c48c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton {
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: linear-gradient(90deg, rgba(255,255,255,0.05) 25%, rgba(255,255,255,0.1) 50%, rgba(255,255,255,0.05) 75%);
|
||||||
|
background-size: 200% 100%;
|
||||||
|
animation: shimmer 1.4s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shimmer {
|
||||||
|
0% { background-position: 200% 0; }
|
||||||
|
100% { background-position: -200% 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #ff4d4d;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 520px) {
|
||||||
|
.fieldRow {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyBtn {
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
96
src/widgets/receive-modal/ui/ReceiveModal.tsx
Normal file
96
src/widgets/receive-modal/ui/ReceiveModal.tsx
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useWalletAddresses, type Chain } from '@features/wallet'
|
||||||
|
import styles from './ReceiveModal.module.css'
|
||||||
|
|
||||||
|
const CHAIN_LABEL: Record<Chain, string> = {
|
||||||
|
ETH: 'Ethereum',
|
||||||
|
BSC: 'BNB Smart Chain',
|
||||||
|
BTC: 'Bitcoin',
|
||||||
|
TRX: 'Tron',
|
||||||
|
SOL: 'Solana',
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReceiveModalProps {
|
||||||
|
open: boolean
|
||||||
|
onClose: () => void
|
||||||
|
chain: Chain
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ReceiveModal({ open, onClose, chain }: ReceiveModalProps) {
|
||||||
|
const { data: addresses, isLoading, isError } = useWalletAddresses()
|
||||||
|
const [copied, setCopied] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) return
|
||||||
|
function onKey(e: KeyboardEvent) {
|
||||||
|
if (e.key === 'Escape') onClose()
|
||||||
|
}
|
||||||
|
window.addEventListener('keydown', onKey)
|
||||||
|
return () => window.removeEventListener('keydown', onKey)
|
||||||
|
}, [open, onClose])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) setCopied(false)
|
||||||
|
}, [open])
|
||||||
|
|
||||||
|
if (!open) return null
|
||||||
|
|
||||||
|
const entry = addresses?.find(a => a.chain === chain)
|
||||||
|
const address = entry?.address ?? ''
|
||||||
|
|
||||||
|
function handleCopy() {
|
||||||
|
if (!address) return
|
||||||
|
navigator.clipboard.writeText(address).then(() => {
|
||||||
|
setCopied(true)
|
||||||
|
setTimeout(() => setCopied(false), 2000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleOverlay(e: React.MouseEvent<HTMLDivElement>) {
|
||||||
|
if (e.target === e.currentTarget) onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.overlay} onMouseDown={handleOverlay}>
|
||||||
|
<div className={styles.dialog}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<span className={styles.title}>Получить {CHAIN_LABEL[chain]}</span>
|
||||||
|
<button className={styles.closeBtn} type="button" onClick={onClose} aria-label="Закрыть">✕</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.body}>
|
||||||
|
{isLoading && (
|
||||||
|
<div className={styles.skeleton} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isError && (
|
||||||
|
<p className={styles.error}>Не удалось загрузить адрес. Попробуйте позже.</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!isLoading && !isError && (
|
||||||
|
<>
|
||||||
|
<label className={styles.label}>Ваш {chain}-адрес</label>
|
||||||
|
<div className={styles.fieldRow}>
|
||||||
|
<input
|
||||||
|
className={styles.addressInput}
|
||||||
|
type="text"
|
||||||
|
readOnly
|
||||||
|
value={address}
|
||||||
|
onFocus={e => e.target.select()}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
className={`${styles.copyBtn} ${copied ? styles.copyBtnDone : ''}`}
|
||||||
|
type="button"
|
||||||
|
onClick={handleCopy}
|
||||||
|
disabled={!address}
|
||||||
|
>
|
||||||
|
{copied ? 'Скопировано!' : 'Копировать'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -51,7 +51,13 @@
|
|||||||
|
|
||||||
.center {
|
.center {
|
||||||
text-align: center !important;
|
text-align: center !important;
|
||||||
width: 140px;
|
width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btnGroup {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.star {
|
.star {
|
||||||
@@ -177,6 +183,29 @@
|
|||||||
border-color: #4a6dff;
|
border-color: #4a6dff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.receiveBtn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
background: rgba(0, 196, 140, 0.12);
|
||||||
|
border: 1px solid rgba(0, 196, 140, 0.3);
|
||||||
|
color: #00c48c;
|
||||||
|
border-radius: 10px;
|
||||||
|
height: 36px;
|
||||||
|
min-width: 120px;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-family: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s, border-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiveBtn:hover {
|
||||||
|
background: rgba(0, 196, 140, 0.25);
|
||||||
|
border-color: #00c48c;
|
||||||
|
}
|
||||||
|
|
||||||
.noFont {
|
.noFont {
|
||||||
font-family: inherit !important;
|
font-family: inherit !important;
|
||||||
}
|
}
|
||||||
@@ -276,6 +305,7 @@
|
|||||||
.mobileActions {
|
.mobileActions {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,8 +323,9 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sendBtn {
|
.sendBtn,
|
||||||
width: 100%;
|
.receiveBtn {
|
||||||
|
flex: 1;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useTokenRows } from '../model/useTokenRows'
|
import { useTokenRows } from '../model/useTokenRows'
|
||||||
import { SendModal, TICKER_TO_CHAIN, type Chain } from '@widgets/send-modal'
|
import { SendModal, TICKER_TO_CHAIN, type Chain } from '@widgets/send-modal'
|
||||||
|
import { ReceiveModal } from '@widgets/receive-modal'
|
||||||
import styles from './TokenTable.module.css'
|
import styles from './TokenTable.module.css'
|
||||||
|
|
||||||
export function TokenTable() {
|
export function TokenTable() {
|
||||||
@@ -10,6 +11,10 @@ export function TokenTable() {
|
|||||||
open: false,
|
open: false,
|
||||||
network: 'ETH',
|
network: 'ETH',
|
||||||
})
|
})
|
||||||
|
const [receiveModal, setReceiveModal] = useState<{ open: boolean; chain: Chain }>({
|
||||||
|
open: false,
|
||||||
|
chain: 'ETH',
|
||||||
|
})
|
||||||
|
|
||||||
function openSend(ticker: string) {
|
function openSend(ticker: string) {
|
||||||
const network = TICKER_TO_CHAIN[ticker] ?? 'ETH'
|
const network = TICKER_TO_CHAIN[ticker] ?? 'ETH'
|
||||||
@@ -20,6 +25,15 @@ export function TokenTable() {
|
|||||||
setSendModal((s) => ({ ...s, open: false }))
|
setSendModal((s) => ({ ...s, open: false }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openReceive(ticker: string) {
|
||||||
|
const chain = TICKER_TO_CHAIN[ticker] ?? 'ETH'
|
||||||
|
setReceiveModal({ open: true, chain })
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeReceive() {
|
||||||
|
setReceiveModal((s) => ({ ...s, open: false }))
|
||||||
|
}
|
||||||
|
|
||||||
function toggleFav(i: number) {
|
function toggleFav(i: number) {
|
||||||
setFavs((prev) => prev.map((v, idx) => (idx === i ? !v : v)))
|
setFavs((prev) => prev.map((v, idx) => (idx === i ? !v : v)))
|
||||||
}
|
}
|
||||||
@@ -30,6 +44,12 @@ export function TokenTable() {
|
|||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const receiveIcon = (
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#00C48C" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M17 7L7 17M7 17H17M7 17V7" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={`${styles.wrap} ${isLoading ? styles.loading : ''}`}>
|
<div className={`${styles.wrap} ${isLoading ? styles.loading : ''}`}>
|
||||||
@@ -83,14 +103,24 @@ export function TokenTable() {
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className={styles.center}>
|
<td className={styles.center}>
|
||||||
<button
|
<div className={styles.btnGroup}>
|
||||||
className={styles.sendBtn}
|
<button
|
||||||
type="button"
|
className={styles.receiveBtn}
|
||||||
onClick={(e) => { e.stopPropagation(); openSend(t.ticker) }}
|
type="button"
|
||||||
>
|
onClick={(e) => { e.stopPropagation(); openReceive(t.ticker) }}
|
||||||
{sendIcon}
|
>
|
||||||
Отправить
|
{receiveIcon}
|
||||||
</button>
|
Получить
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={styles.sendBtn}
|
||||||
|
type="button"
|
||||||
|
onClick={(e) => { e.stopPropagation(); openSend(t.ticker) }}
|
||||||
|
>
|
||||||
|
{sendIcon}
|
||||||
|
Отправить
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
@@ -138,6 +168,10 @@ export function TokenTable() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.mobileActions}>
|
<div className={styles.mobileActions}>
|
||||||
|
<button className={styles.receiveBtn} type="button" onClick={() => openReceive(rows[0]?.ticker ?? '')}>
|
||||||
|
{receiveIcon}
|
||||||
|
Получить
|
||||||
|
</button>
|
||||||
<button className={styles.sendBtn} type="button" onClick={() => openSend(rows[0]?.ticker ?? '')}>
|
<button className={styles.sendBtn} type="button" onClick={() => openSend(rows[0]?.ticker ?? '')}>
|
||||||
{sendIcon}
|
{sendIcon}
|
||||||
Отправить
|
Отправить
|
||||||
@@ -150,6 +184,11 @@ export function TokenTable() {
|
|||||||
network={sendModal.network}
|
network={sendModal.network}
|
||||||
tokens={rows}
|
tokens={rows}
|
||||||
/>
|
/>
|
||||||
|
<ReceiveModal
|
||||||
|
open={receiveModal.open}
|
||||||
|
onClose={closeReceive}
|
||||||
|
chain={receiveModal.chain}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user