19.05.2026 okkk
This commit is contained in:
@@ -62,6 +62,10 @@ export function getPaymentQuote(usdtAmount: number): Promise<PaymentQuote> {
|
|||||||
return doPaymentRequest(`/payment/quote?usdt_amount=${usdtAmount}`, {}, true)
|
return doPaymentRequest(`/payment/quote?usdt_amount=${usdtAmount}`, {}, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPaymentQuoteByRub(rubAmount: number): Promise<PaymentQuote> {
|
||||||
|
return doPaymentRequest(`/payment/quote/rub?total_rub=${rubAmount}`, {}, true)
|
||||||
|
}
|
||||||
|
|
||||||
export interface CreateOrderPayload {
|
export interface CreateOrderPayload {
|
||||||
usdt_amount: number
|
usdt_amount: number
|
||||||
usdt_exchange_rate: number
|
usdt_exchange_rate: number
|
||||||
|
|||||||
13
src/features/payment/hooks/usePaymentQuoteByRub.ts
Normal file
13
src/features/payment/hooks/usePaymentQuoteByRub.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { useQuery } from '@tanstack/react-query'
|
||||||
|
import { getPaymentQuoteByRub } from '../api/paymentApi'
|
||||||
|
import type { PaymentQuote } from '../api/paymentApi'
|
||||||
|
|
||||||
|
export function usePaymentQuoteByRub(rubAmount: number) {
|
||||||
|
return useQuery<PaymentQuote>({
|
||||||
|
queryKey: ['payment', 'quote', 'rub', rubAmount],
|
||||||
|
queryFn: () => getPaymentQuoteByRub(rubAmount),
|
||||||
|
enabled: rubAmount > 0,
|
||||||
|
staleTime: 30_000,
|
||||||
|
retry: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export { usePaymentConfig } from './hooks/usePaymentConfig'
|
export { usePaymentConfig } from './hooks/usePaymentConfig'
|
||||||
export { usePaymentQuote } from './hooks/usePaymentQuote'
|
export { usePaymentQuote } from './hooks/usePaymentQuote'
|
||||||
|
export { usePaymentQuoteByRub } from './hooks/usePaymentQuoteByRub'
|
||||||
export { useCreateOrder } from './hooks/useCreateOrder'
|
export { useCreateOrder } from './hooks/useCreateOrder'
|
||||||
export type { PaymentConfig, PaymentQuote, CreateOrderPayload, OrderResult } from './api/paymentApi'
|
export type { PaymentConfig, PaymentQuote, CreateOrderPayload, OrderResult } from './api/paymentApi'
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
import { useConverter, progressPercent } from '@widgets/currency-converter'
|
import { useConverter, progressPercent } from '@widgets/currency-converter'
|
||||||
import { useDebounce } from '@shared/lib/hooks/useDebounce'
|
import { useDebounce } from '@shared/lib/hooks/useDebounce'
|
||||||
import { usePaymentQuote, usePaymentConfig, useCreateOrder } from '@features/payment'
|
import { usePaymentQuote, usePaymentQuoteByRub, usePaymentConfig, useCreateOrder } from '@features/payment'
|
||||||
import { CommissionPanel } from './CommissionPanel'
|
import { CommissionPanel } from './CommissionPanel'
|
||||||
import { AgreementCheck } from './AgreementCheck'
|
import { AgreementCheck } from './AgreementCheck'
|
||||||
import styles from './ConverterSection.module.css'
|
import styles from './ConverterSection.module.css'
|
||||||
@@ -8,31 +9,69 @@ import { GAS_PRICE } from '@shared/config/constants'
|
|||||||
|
|
||||||
export function ConverterSection() {
|
export function ConverterSection() {
|
||||||
const c = useConverter({ usdtRate: 0 })
|
const c = useConverter({ usdtRate: 0 })
|
||||||
|
const [direction, setDirection] = useState<'usdt_to_rub' | 'rub_to_usdt'>('usdt_to_rub')
|
||||||
|
const [rubInputVal, setRubInputVal] = useState('1000')
|
||||||
|
|
||||||
const debouncedUsdt = useDebounce(c.numRub, 400)
|
|
||||||
const { data: quote, isError: quoteError } = usePaymentQuote(debouncedUsdt)
|
|
||||||
const { data: config } = usePaymentConfig()
|
const { data: config } = usePaymentConfig()
|
||||||
|
|
||||||
const configUsdtRate = Number(config?.usdt_exchange_rate) || 0
|
const configUsdtRate = Number(config?.usdt_exchange_rate) || 0
|
||||||
const gasPriceRub = Number(config?.gas_fee) || GAS_PRICE
|
const gasPriceRub = Number(config?.gas_fee) || GAS_PRICE
|
||||||
|
|
||||||
const rubTotal = quote?.total_price ?? ''
|
const isUsdtToRub = direction === 'usdt_to_rub'
|
||||||
const rubTotalNum = Number(rubTotal) || 0
|
|
||||||
|
|
||||||
const commission = Number(quote?.service_fee) || 0
|
const debouncedUsdt = useDebounce(c.numRub, 400)
|
||||||
const effectiveRate = c.numRub > 0 ? rubTotalNum / c.numRub : 0
|
const { data: quoteUsdtToRub, isError: quoteError } = usePaymentQuote(isUsdtToRub ? debouncedUsdt : 0)
|
||||||
|
|
||||||
|
const numRubInput = Number.parseFloat(rubInputVal) || 0
|
||||||
|
const debouncedRub = useDebounce(numRubInput, 400)
|
||||||
|
const { data: quoteRubToUsdt, isError: quoteRubError } = usePaymentQuoteByRub(!isUsdtToRub ? debouncedRub : 0)
|
||||||
|
|
||||||
|
function updateRubInput(raw: string) {
|
||||||
|
setRubInputVal(raw.replace(/[^0-9.]/g, ''))
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSwap() {
|
||||||
|
setDirection(d => d === 'usdt_to_rub' ? 'rub_to_usdt' : 'usdt_to_rub')
|
||||||
|
}
|
||||||
|
|
||||||
|
const rubTotal = quoteUsdtToRub?.total_price ?? ''
|
||||||
|
const rubTotalNum = Number(rubTotal) || 0
|
||||||
|
const usdtFromRub = quoteRubToUsdt?.usdt_amount ?? ''
|
||||||
|
const usdtFromRubNum = Number(usdtFromRub) || 0
|
||||||
|
|
||||||
|
const commission = isUsdtToRub
|
||||||
|
? Number(quoteUsdtToRub?.service_fee) || 0
|
||||||
|
: Number(quoteRubToUsdt?.service_fee) || 0
|
||||||
|
|
||||||
|
const displayRubAmount = isUsdtToRub ? rubTotalNum : numRubInput
|
||||||
|
const effectiveRate = isUsdtToRub
|
||||||
|
? (c.numRub > 0 ? rubTotalNum / c.numRub : 0)
|
||||||
|
: (usdtFromRubNum > 0 ? numRubInput / usdtFromRubNum : 0)
|
||||||
|
|
||||||
const { mutate: submitOrder, isPending } = useCreateOrder()
|
const { mutate: submitOrder, isPending } = useCreateOrder()
|
||||||
|
|
||||||
function handlePay() {
|
function handlePay() {
|
||||||
submitOrder({
|
if (isUsdtToRub) {
|
||||||
usdt_amount: c.numRub,
|
submitOrder({
|
||||||
usdt_exchange_rate: 1,
|
usdt_amount: c.numRub,
|
||||||
gas_fee: 1,
|
usdt_exchange_rate: 1,
|
||||||
total_price: Number(rubTotal) || 0,
|
gas_fee: 1,
|
||||||
})
|
total_price: Number(rubTotal) || 0,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
submitOrder({
|
||||||
|
usdt_amount: usdtFromRubNum,
|
||||||
|
usdt_exchange_rate: 1,
|
||||||
|
gas_fee: 1,
|
||||||
|
total_price: numRubInput,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isPayDisabled = isUsdtToRub
|
||||||
|
? (!rubTotal || isPending || !c.agreed)
|
||||||
|
: (!usdtFromRub || isPending || !c.agreed)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrap}>
|
<div className={styles.wrap}>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
@@ -63,62 +102,120 @@ export function ConverterSection() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.field}>
|
{isUsdtToRub ? (
|
||||||
<div className={styles.fieldLabel}>Конвертируете</div>
|
<>
|
||||||
<div className={styles.fieldInput}>
|
<div className={styles.field}>
|
||||||
<input
|
<div className={styles.fieldLabel}>Конвертируете</div>
|
||||||
type="text"
|
<div className={styles.fieldInput}>
|
||||||
value={c.rubVal}
|
<input
|
||||||
onChange={(e) => c.updateRub(e.target.value)}
|
type="text"
|
||||||
placeholder="0"
|
value={c.rubVal}
|
||||||
inputMode="decimal"
|
onChange={(e) => c.updateRub(e.target.value)}
|
||||||
/>
|
placeholder="0"
|
||||||
<div className={styles.currency}>
|
inputMode="decimal"
|
||||||
<span className={`${styles.currencyIcon} ${styles.currencyUsdt}`}>₮</span>
|
/>
|
||||||
USDT
|
<div className={styles.currency}>
|
||||||
|
<span className={`${styles.currencyIcon} ${styles.currencyUsdt}`}>₮</span>
|
||||||
|
USDT
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{quoteError && (
|
||||||
|
<div className={styles.fieldError}>
|
||||||
|
Сумма слишком большая и превышает 600 000 ₽
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{quoteError && (
|
|
||||||
<div className={styles.fieldError}>
|
|
||||||
Сумма слишком большая и превышает 600 000 ₽
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.swapWrap}>
|
<div className={styles.swapWrap}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={styles.swapBtn}
|
className={styles.swapBtn}
|
||||||
onClick={c.toggleMode}
|
onClick={handleSwap}
|
||||||
aria-label="Поменять направление"
|
aria-label="Поменять направление"
|
||||||
>
|
>
|
||||||
<svg width={16} height={16} viewBox="0 0 16 16" fill="none">
|
<svg width={16} height={16} viewBox="0 0 16 16" fill="none">
|
||||||
<path
|
<path
|
||||||
d="M8 2v12M4 10l4 4 4-4"
|
d="M8 2v12M4 10l4 4 4-4"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
strokeWidth={1.5}
|
strokeWidth={1.5}
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.field}>
|
|
||||||
<div className={styles.fieldLabel}>Платите</div>
|
|
||||||
<div className={styles.fieldInput}>
|
|
||||||
<input type="text" value={rubTotal} readOnly placeholder="0" />
|
|
||||||
<div className={styles.currency}>
|
|
||||||
<span className={`${styles.currencyIcon} ${styles.currencyRub}`}>₽</span>
|
|
||||||
RUB
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
<div className={styles.field}>
|
||||||
|
<div className={styles.fieldLabel}>Платите</div>
|
||||||
|
<div className={styles.fieldInput}>
|
||||||
|
<input type="text" value={rubTotal} readOnly placeholder="0" />
|
||||||
|
<div className={styles.currency}>
|
||||||
|
<span className={`${styles.currencyIcon} ${styles.currencyRub}`}>₽</span>
|
||||||
|
RUB
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className={styles.field}>
|
||||||
|
<div className={styles.fieldLabel}>Конвертируете</div>
|
||||||
|
<div className={styles.fieldInput}>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={rubInputVal}
|
||||||
|
onChange={(e) => updateRubInput(e.target.value)}
|
||||||
|
placeholder="0"
|
||||||
|
inputMode="decimal"
|
||||||
|
/>
|
||||||
|
<div className={styles.currency}>
|
||||||
|
<span className={`${styles.currencyIcon} ${styles.currencyRub}`}>₽</span>
|
||||||
|
RUB
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{quoteRubError && (
|
||||||
|
<div className={styles.fieldError}>
|
||||||
|
Сумма слишком большая и превышает 600 000 ₽
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.swapWrap}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.swapBtn}
|
||||||
|
onClick={handleSwap}
|
||||||
|
aria-label="Поменять направление"
|
||||||
|
>
|
||||||
|
<svg width={16} height={16} viewBox="0 0 16 16" fill="none">
|
||||||
|
<path
|
||||||
|
d="M8 2v12M4 10l4 4 4-4"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.field}>
|
||||||
|
<div className={styles.fieldLabel}>Платите</div>
|
||||||
|
<div className={styles.fieldInput}>
|
||||||
|
<input type="text" value={usdtFromRub} readOnly placeholder="0" />
|
||||||
|
<div className={styles.currency}>
|
||||||
|
<span className={`${styles.currencyIcon} ${styles.currencyUsdt}`}>₮</span>
|
||||||
|
USDT
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CommissionPanel
|
<CommissionPanel
|
||||||
amount={rubTotalNum}
|
amount={displayRubAmount}
|
||||||
progress={progressPercent(rubTotalNum)}
|
progress={progressPercent(displayRubAmount)}
|
||||||
commission={commission}
|
commission={commission}
|
||||||
effectiveRate={effectiveRate}
|
effectiveRate={effectiveRate}
|
||||||
/>
|
/>
|
||||||
@@ -132,7 +229,7 @@ export function ConverterSection() {
|
|||||||
type="button"
|
type="button"
|
||||||
className={styles.payBtn}
|
className={styles.payBtn}
|
||||||
onClick={handlePay}
|
onClick={handlePay}
|
||||||
disabled={!rubTotal || isPending || !c.agreed}
|
disabled={isPayDisabled}
|
||||||
>
|
>
|
||||||
{isPending ? 'Обработка...' : 'Оплатить'}
|
{isPending ? 'Обработка...' : 'Оплатить'}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
import { GAS_PRICE, USDT_RATE } from '@shared/config/constants'
|
import { GAS_PRICE, USDT_RATE } from '@shared/config/constants'
|
||||||
import { useConverter } from '../model/useConverter'
|
import { useConverter } from '../model/useConverter'
|
||||||
import { progressPercent } from '../model/tiers'
|
import { progressPercent } from '../model/tiers'
|
||||||
import { usePaymentConfig, usePaymentQuote } from '@features/payment'
|
import { usePaymentConfig, usePaymentQuote, usePaymentQuoteByRub } from '@features/payment'
|
||||||
import { useDebounce } from '@shared/lib/hooks/useDebounce'
|
import { useDebounce } from '@shared/lib/hooks/useDebounce'
|
||||||
import { CommissionTable } from './CommissionTable'
|
import { CommissionTable } from './CommissionTable'
|
||||||
import styles from './Converter.module.css'
|
import styles from './Converter.module.css'
|
||||||
@@ -11,20 +12,44 @@ import { ROUTES } from '@shared/config/routes'
|
|||||||
|
|
||||||
export function Converter() {
|
export function Converter() {
|
||||||
const { data: config } = usePaymentConfig()
|
const { data: config } = usePaymentConfig()
|
||||||
|
const [direction, setDirection] = useState<'usdt_to_rub' | 'rub_to_usdt'>('usdt_to_rub')
|
||||||
|
const [rubInputVal, setRubInputVal] = useState('1000')
|
||||||
|
|
||||||
const configUsdtRate = Number(config?.usdt_exchange_rate) || USDT_RATE
|
const configUsdtRate = Number(config?.usdt_exchange_rate) || USDT_RATE
|
||||||
const gasPriceRub = Number(config?.gas_fee) || GAS_PRICE
|
const gasPriceRub = Number(config?.gas_fee) || GAS_PRICE
|
||||||
|
|
||||||
const c = useConverter({ usdtRate: configUsdtRate })
|
const c = useConverter({ usdtRate: configUsdtRate })
|
||||||
|
|
||||||
|
const isUsdtToRub = direction === 'usdt_to_rub'
|
||||||
|
|
||||||
const debouncedUsdt = useDebounce(c.numRub, 400)
|
const debouncedUsdt = useDebounce(c.numRub, 400)
|
||||||
const { data: quote } = usePaymentQuote(debouncedUsdt)
|
const { data: quoteUsdtToRub } = usePaymentQuote(isUsdtToRub ? debouncedUsdt : 0)
|
||||||
|
|
||||||
const rubTotal = quote?.total_price ?? ''
|
const numRubInput = Number.parseFloat(rubInputVal) || 0
|
||||||
|
const debouncedRub = useDebounce(numRubInput, 400)
|
||||||
|
const { data: quoteRubToUsdt } = usePaymentQuoteByRub(!isUsdtToRub ? debouncedRub : 0)
|
||||||
|
|
||||||
|
function updateRubInput(raw: string) {
|
||||||
|
setRubInputVal(raw.replace(/[^0-9.]/g, ''))
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSwap() {
|
||||||
|
setDirection(d => d === 'usdt_to_rub' ? 'rub_to_usdt' : 'usdt_to_rub')
|
||||||
|
}
|
||||||
|
|
||||||
|
const rubTotal = quoteUsdtToRub?.total_price ?? ''
|
||||||
const rubTotalNum = Number(rubTotal) || 0
|
const rubTotalNum = Number(rubTotal) || 0
|
||||||
|
const usdtFromRub = quoteRubToUsdt?.usdt_amount ?? ''
|
||||||
|
const usdtFromRubNum = Number(usdtFromRub) || 0
|
||||||
|
|
||||||
const commission = Number(quote?.service_fee) || 0
|
const commission = isUsdtToRub
|
||||||
const effectiveRate = c.numRub > 0 ? rubTotalNum / c.numRub : 0
|
? Number(quoteUsdtToRub?.service_fee) || 0
|
||||||
|
: Number(quoteRubToUsdt?.service_fee) || 0
|
||||||
|
|
||||||
|
const displayRubAmount = isUsdtToRub ? rubTotalNum : numRubInput
|
||||||
|
const effectiveRate = isUsdtToRub
|
||||||
|
? (c.numRub > 0 ? rubTotalNum / c.numRub : 0)
|
||||||
|
: (usdtFromRubNum > 0 ? numRubInput / usdtFromRubNum : 0)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.section} id="converter">
|
<section className={styles.section} id="converter">
|
||||||
@@ -57,52 +82,102 @@ export function Converter() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.field}>
|
{isUsdtToRub ? (
|
||||||
<div className={styles.fieldInput}>
|
<>
|
||||||
<input
|
<div className={styles.field}>
|
||||||
type="text"
|
<div className={styles.fieldInput}>
|
||||||
value={c.rubVal}
|
<input
|
||||||
onChange={(e) => c.updateRub(e.target.value)}
|
type="text"
|
||||||
placeholder="0"
|
value={c.rubVal}
|
||||||
inputMode="decimal"
|
onChange={(e) => c.updateRub(e.target.value)}
|
||||||
/>
|
placeholder="0"
|
||||||
<div className={styles.currency}>
|
inputMode="decimal"
|
||||||
<span className={`${styles.currencyIcon} ${styles.currencyUsdt}`}>₮</span> USDT
|
/>
|
||||||
|
<div className={styles.currency}>
|
||||||
|
<span className={`${styles.currencyIcon} ${styles.currencyUsdt}`}>₮</span> USDT
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.swapWrap}>
|
<div className={styles.swapWrap}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={styles.swapBtn}
|
className={styles.swapBtn}
|
||||||
aria-label="Поменять направление"
|
onClick={handleSwap}
|
||||||
>
|
aria-label="Поменять направление"
|
||||||
<svg width={16} height={16} viewBox="0 0 16 16" fill="none">
|
>
|
||||||
<path
|
<svg width={16} height={16} viewBox="0 0 16 16" fill="none">
|
||||||
d="M8 2v12M4 10l4 4 4-4"
|
<path
|
||||||
stroke="currentColor"
|
d="M8 2v12M4 10l4 4 4-4"
|
||||||
strokeWidth={1.5}
|
stroke="currentColor"
|
||||||
strokeLinecap="round"
|
strokeWidth={1.5}
|
||||||
strokeLinejoin="round"
|
strokeLinecap="round"
|
||||||
/>
|
strokeLinejoin="round"
|
||||||
</svg>
|
/>
|
||||||
</button>
|
</svg>
|
||||||
</div>
|
</button>
|
||||||
|
|
||||||
<div className={styles.field}>
|
|
||||||
<div className={styles.fieldInput}>
|
|
||||||
<input type="text" value={rubTotal} readOnly placeholder="0" />
|
|
||||||
<div className={styles.currency}>
|
|
||||||
<span className={`${styles.currencyIcon} ${styles.currencyRub}`}>₽</span> RUB
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
<div className={styles.field}>
|
||||||
|
<div className={styles.fieldInput}>
|
||||||
|
<input type="text" value={rubTotal} readOnly placeholder="0" />
|
||||||
|
<div className={styles.currency}>
|
||||||
|
<span className={`${styles.currencyIcon} ${styles.currencyRub}`}>₽</span> RUB
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className={styles.field}>
|
||||||
|
<div className={styles.fieldInput}>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={rubInputVal}
|
||||||
|
onChange={(e) => updateRubInput(e.target.value)}
|
||||||
|
placeholder="0"
|
||||||
|
inputMode="decimal"
|
||||||
|
/>
|
||||||
|
<div className={styles.currency}>
|
||||||
|
<span className={`${styles.currencyIcon} ${styles.currencyRub}`}>₽</span> RUB
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.swapWrap}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.swapBtn}
|
||||||
|
onClick={handleSwap}
|
||||||
|
aria-label="Поменять направление"
|
||||||
|
>
|
||||||
|
<svg width={16} height={16} viewBox="0 0 16 16" fill="none">
|
||||||
|
<path
|
||||||
|
d="M8 2v12M4 10l4 4 4-4"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.field}>
|
||||||
|
<div className={styles.fieldInput}>
|
||||||
|
<input type="text" value={usdtFromRub} readOnly placeholder="0" />
|
||||||
|
<div className={styles.currency}>
|
||||||
|
<span className={`${styles.currencyIcon} ${styles.currencyUsdt}`}>₮</span> USDT
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CommissionTable
|
<CommissionTable
|
||||||
amount={rubTotalNum}
|
amount={displayRubAmount}
|
||||||
progress={progressPercent(rubTotalNum)}
|
progress={progressPercent(displayRubAmount)}
|
||||||
commission={commission}
|
commission={commission}
|
||||||
effectiveRate={effectiveRate}
|
effectiveRate={effectiveRate}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export function buildTokensFromBalance(data: WalletBalanceData): Token[] {
|
|||||||
const RATE = 82.2578
|
const RATE = 82.2578
|
||||||
|
|
||||||
export function useSwapForm() {
|
export function useSwapForm() {
|
||||||
const [fromAmount, setFromAmountRaw] = useState('0.25')
|
const [fromAmount, setFromAmountRaw] = useState('0')
|
||||||
const [fromToken, setFromToken] = useState<Token>(TOKENS.SOL)
|
const [fromToken, setFromToken] = useState<Token>(TOKENS.SOL)
|
||||||
const [toToken, setToToken] = useState<Token>(TOKENS.USDC)
|
const [toToken, setToToken] = useState<Token>(TOKENS.USDC)
|
||||||
const [isRefreshing, setIsRefreshing] = useState(false)
|
const [isRefreshing, setIsRefreshing] = useState(false)
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user