Обмен криптовалют логика
Criado em: 28 de janeiro de 2025
Criado em: 28 de janeiro de 2025
Добавить логики обмена один TON=100PAS одинTON=5USDT
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <link rel="stylesheet" href="styles.css"> <link rel="icon" href="images/icon.png" type="image/png" /> <title>Обмен криптовалют</title> <script src="https://unpkg.com/@tonconnect/[email protected]/dist/tonconnect-ui.min.js"></script> <script src="scripts/main.js" defer></script> </head> <body> <div id="connect-button-root"></div> <script> // Инициализируем TonConnect UI const tonConnectUI = new TON_CONNECT_UI.TonConnectUI({ manifestUrl: 'https://ton-connect.github.io/demo-dapp-with-react-ui/tonconnect-manifest.json', buttonRootId: 'connect-button-root' });text// Отслеживаем изменение статуса (подключения кошелька) tonConnectUI.onStatusChange((walletInfo) => { console.log("TonConnect status:", walletInfo); const addressElement = document.getElementById('userAddress'); if (walletInfo?.account?.address) { addressElement.innerText = "Ваш адрес: " + walletInfo.account.address; } else { addressElement.innerText = "Кошелёк не подключён"; } }); </script> <div class="container"> <h1>Обмен криптовалют</h1> <div class="exchange-form"> <input type="text" id="amount" placeholder="Сумма для обмена" /> <select id="currencyFrom"> <option value="TON">TON</option> <option value="USDT">USDT</option> <option value="PAS">PAS</option> </select> <select id="currencyTo"> <option value="TON">TON</option> <option value="USDT">USDT</option> <option value="PAS">PAS</option> </select> <button onclick="exchange()">Обменять</button> </div> </div> <div id="markets-info"></div> <div id="userAddress">Кошелёк не подключён</div> <div id="exchangeResult"></div> <script> async function exchange() { const amount = document.getElementById('amount').value; const currencyFrom = document.getElementById('currencyFrom').value; const currencyTo = document.getElementById('currencyTo').value; // Проверка суммы if (!amount || isNaN(amount) || amount <= 0) { alert('Пожалуйста, введите корректную сумму для обмена.'); return; } // Проверка подключения кошелька const walletInfo = tonConnectUI.wallet; if (!walletInfo?.account?.address) { alert('Кошелёк не подключён. Пожалуйста, подключите кошелёк.'); return; } // Проверка на обмен валюты на саму себя if (currencyFrom === currencyTo) { alert('Вы пытаетесь обменять валюту на саму себя. Пожалуйста, выберите другую валюту.'); return; } // Адреса кошельков для обмена const exchangeWallets = { TON: "UQBQPunc6ZKNaHzTNG-6e-taSer8EPfZSVjcEBUKBLcQMWKw", PAS: "UQBQPunc6ZKNaHzTNG-6e-taSer8EPfZSVjcEBUKBLcQMWKw", USDT: "UQDF5gjmaMrHjquTr75vnDj35VBbv4S8nuB8IoiGfAnZNsAy" }; // Комиссия за сделку (например, 1% от суммы) const commissionRate = 0.01; const commission = amount * commissionRate; const amountAfterCommission = amount - commission; // Формируем транзакцию const transaction = { validUntil: Math.floor(Date.now() / 1000) + 600, // 10 минут messages: [ { address: exchangeWallets[currencyTo], // Адрес кошелька для получения amount: amountAfterCommission * 1e9, // Сумма в наноТонах (для TON) payload: 'te6cckEBAQEAAgAAAEysucg=' // Полезная нагрузка (уточните у разработчика контракта) }, { address: "UQBQPunc6ZKNaHzTNG-6e-taSer8EPfZSVjcEBUKBLcQMWKw", // Адрес кошелька для комиссии amount: commission * 1e9, // Сумма комиссии в наноТонах payload: 'te6cckEBAQEAAgAAAEysucg=' // Полезная нагрузка (уточните у разработчика контракта) } ] }; try { // Отправляем транзакцию через TonConnect const result = await tonConnectUI.sendTransaction(transaction); console.log("Транзакция успешно отправлена:", result); // Обновляем интерфейс document.getElementById('exchangeResult').innerText = `Обмен успешно выполнен! Сумма: ${amountAfterCommission} ${currencyTo}, комиссия: ${commission} ${currencyFrom}`; } catch (error) { console.error("Ошибка при отправке транзакции:", error); document.getElementById('exchangeResult').innerText = `Ошибка при обмене: ${error.message}`; } } </script> <script> // Логика обмена (пример для TON -> USDT) if (currencyFrom === 'TON' && currencyTo === 'USDT') { const transaction = { validUntil: Math.floor(Date.now() / 1000) + 600, // 10 минут messages: [ { address: 'UQBQPunc6ZKNaHzTNG-6e-taSer8EPfZSVjcEBUKBLcQMWKw', // Адрес контракта для обмена amount: amount * 1e9, // Комиссия 0.01 TON в наноТонах } ] }; async function exchange() { const amount = document.getElementById('amount').value; const currencyFrom = document.getElementById('currencyFrom').value; const currencyTo = document.getElementById('currencyTo').value; // Проверка суммы if (!amount || isNaN(amount) || amount <= 0) { alert('Пожалуйста, введите корректную сумму для обмена.'); return; } // Проверка подключения кошелька const walletInfo = tonConnectUI.account; if (!walletInfo?.address) { alert('Кошелёк не подключён. Пожалуйста, подключите кошелёк.'); return; } // Логика обмена let transaction; try { if (currencyFrom === 'TON' && currencyTo === 'USDT') { transaction = { validUntil: Math.floor(Date.now() / 1000) + 600, // 10 минут messages: [ { address: TOKEN_ADDRESSES.USDT, amount: (amount * 1e9).toString(), // Комиссия 0.01 TON в наноТонах payload: begin_cell() .store_uint(0x18, 6) .store_slice(walletInfo.address) .store_coins(0) .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) .store_uint(op::transfer_notification(), 32) .store_uint(0, 64) .end_cell() } ] }; } else if (currencyFrom === 'USDT' && currencyTo === 'TON') { transaction = { validUntil: Math.floor(Date.now() / 1000) + 600, messages: [ { address: TOKEN_ADDRESSES.TON, amount: (amount * 1e6).toString(), // Комиссия 0.01 TON в наноТонах payload: begin_cell() .store_uint(0x18, 6) .store_slice(walletInfo.address) .store_coins(0) .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) .store_uint(op::transfer_notification(), 32) .store_uint(0, 64) .end_cell() } ] }; } // Отправка транзакции через TonConnect const result = await tonConnectUI.sendTransaction(transaction); console.log("Транзакция успешно отправлена:", result); alert("Транзакция успешно отправлена!"); } catch (error) { console.error("Ошибка при отправке транзакции:", error); alert("Ошибка при отправке транзакции. Пожалуйста, попробуйте снова."); }
}
</script>
Ниже приведён пример упрощённой реализации логики конвертации по заданным курсам:
Из этих двух правил легко вывести все остальные комбинации:
amount * 5/100 = amount * 0.05.amount * 100/5 = amount * 20.Ниже пример кода, где мы добавляем логику обмена в функцию exchange(). Обратите внимание, что в данном примере для простоты показан только расчёт итогового количества токенов. Логика реального формирования транзакции (адреса, payload и т.д.) может отличаться в зависимости от вашего смарт-контракта и требует уточнения.
html<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <link rel="stylesheet" href="styles.css"> <link rel="icon" href="images/icon.png" type="image/png" /> <title>Обмен криптовалют</title> <!-- Подключение TonConnect UI --> <script src="https://unpkg.com/@tonconnect/[email protected]/dist/tonconnect-ui.min.js"></script> <script src="scripts/main.js" defer></script> </head> <body> <!-- Кнопка для подключения кошелька TonConnect --> <div id="connect-button-root"></div> <script> // Инициализируем TonConnect UI const tonConnectUI = new TON_CONNECT_UI.TonConnectUI({ manifestUrl: 'https://ton-connect.github.io/demo-dapp-with-react-ui/tonconnect-manifest.json', buttonRootId: 'connect-button-root' }); // Отслеживаем изменение статуса (подключения кошелька) tonConnectUI.onStatusChange((walletInfo) => { console.log("TonConnect status:", walletInfo); const addressElement = document.getElementById('userAddress'); if (walletInfo?.account?.address) { addressElement.innerText = "Ваш адрес: " + walletInfo.account.address; } else { addressElement.innerText = "Кошелёк не подключён"; } }); </script> <div class="container"> <h1>Обмен криптовалют</h1> <div class="exchange-form"> <input type="text" id="amount" placeholder="Сумма для обмена" /> <select id="currencyFrom"> <option value="TON">TON</option> <option value="USDT">USDT</option> <option value="PAS">PAS</option> </select> <select id="currencyTo"> <option value="TON">TON</option> <option value="USDT">USDT</option> <option value="PAS">PAS</option> </select> <button onclick="exchange()">Обменять</button> </div> </div> <div id="markets-info"></div> <div id="userAddress">Кошелёк не подключён</div> <div id="exchangeResult"></div> <script> // Пример адресов, на которые вы будете отправлять монеты const exchangeWallets = { TON: "UQBQPunc6ZKNaHzTNG-6e-taSer8EPfZSVjcEBUKBLcQMWKw", USDT: "UQDF5gjmaMrHjquTr75vnDj35VBbv4S8nuB8IoiGfAnZNsAy", PAS: "UQBQPunc6ZKNaHzTNG-6e-taSer8EPfZSVjcEBUKBLcQMWKw" }; // Процент комиссии (пример: 1%) const commissionRate = 0.01; async function exchange() { const amountInput = document.getElementById('amount').value; const currencyFrom = document.getElementById('currencyFrom').value; const currencyTo = document.getElementById('currencyTo').value; // Проверка суммы const amount = parseFloat(amountInput); if (!amount || isNaN(amount) || amount <= 0) { alert('Пожалуйста, введите корректную сумму для обмена.'); return; } // Проверка подключения кошелька const walletInfo = tonConnectUI.wallet; if (!walletInfo?.account?.address) { alert('Кошелёк не подключён. Пожалуйста, подключите кошелёк.'); return; } // Проверка на обмен валюты на саму себя if (currencyFrom === currencyTo) { alert('Вы пытаетесь обменять валюту на саму себя. Пожалуйста, выберите другую валюту.'); return; } // 1. Расчёт итогового количества, исходя из заданных курсов let resultAmount = 0; switch (true) { case (currencyFrom === 'TON' && currencyTo === 'PAS'): // 1 TON = 100 PAS resultAmount = amount * 100; break; case (currencyFrom === 'TON' && currencyTo === 'USDT'): // 1 TON = 5 USDT resultAmount = amount * 5; break; case (currencyFrom === 'PAS' && currencyTo === 'TON'): // 100 PAS = 1 TON => делим на 100 resultAmount = amount / 100; break; case (currencyFrom === 'USDT' && currencyTo === 'TON'): // 5 USDT = 1 TON => делим на 5 resultAmount = amount / 5; break; case (currencyFrom === 'PAS' && currencyTo === 'USDT'): // PAS -> TON -> USDT => (amount / 100) * 5 = amount * 0.05 resultAmount = (amount / 100) * 5; break; case (currencyFrom === 'USDT' && currencyTo === 'PAS'): // USDT -> TON -> PAS => (amount / 5) * 100 = amount * 20 resultAmount = (amount / 5) * 100; break; } // 2. Расчёт комиссии const commission = amount * commissionRate; const amountAfterCommission = amount - commission; // 3. Формируем "транзакции" для отправки (пример!) // Обратите внимание, что в реальном обменнике вам нужно будет: // - сначала отправлять исходную валюту на смарт-контракт обменника // - смарт-контракт должен вернуть вам нужное количество целевой валюты // - комиссия может сниматься автоматически контрактом // Здесь для примера мы показываем одну транзакцию на сам обмен и одну – на комиссию. // ВАЖНО: Здесь мы исходим из того, что "TON" – это основной токен блокчейна и его // мы можем отправлять напрямую в нанотонах. Для USDT/PAS как кастомных токенов // обычно нужен отдельный механизм (Jetton transfer или сторонний контракт). // Код ниже просто демонстрирует общий подход и потребует доработки под конкретный смарт-контракт. const transaction = { validUntil: Math.floor(Date.now() / 1000) + 600, // 10 минут messages: [ { // Адрес кошелька/контракта, куда отправляем "целевую" валюту // (в реальном кейсе сначала отправляем currencyFrom в обменник, который уже выдаст currencyTo) address: exchangeWallets[currencyTo], // Сумма в нанотонах: если это TON, умножаем на 1e9. // Если это не TON (USDT/PAS), потребуются дополнительные шаги по формированию Jetton-транзакции. amount: (amountAfterCommission * 1e9).toFixed(0), payload: 'te6cckEBAQEAAgAAAEysucg=' }, { // Адрес кошелька для комиссии (например, наш сервис) address: "UQBQPunc6ZKNaHzTNG-6e-taSer8EPfZSVjcEBUKBLcQMWKw", amount: (commission * 1e9).toFixed(0), payload: 'te6cckEBAQEAAgAAAEysucg=' } ] }; try { // Отправляем транзакцию через TonConnect const result = await tonConnectUI.sendTransaction(transaction); console.log("Транзакция успешно отправлена:", result); // Обновляем интерфейс document.getElementById('exchangeResult').innerText = `Обмен успешно выполнен!\n` + `Вы меняете: ${amount} ${currencyFrom}\n` + `Ожидаемая сумма на выходе: ~${resultAmount.toFixed(4)} ${currencyTo}\n` + `С учётом комиссии 1% (отправили исходной валюты - ${amountAfterCommission.toFixed(4)})\n` + `Комиссия составила: ${commission.toFixed(4)} ${currencyFrom}`; } catch (error) { console.error("Ошибка при отправке транзакции:", error); document.getElementById('exchangeResult').innerText = `Ошибка при обмене: ${error.message}`; } } </script> </body> </html>
Расчёт итоговой суммы
Мы используем простые математические операции, основанные на заданных курсах. Для каждого случая (currencyFrom → currencyTo) выбираем соответствующую формулу.
Комиссия
В примере взята комиссия 1% от исходной суммы, чтобы показать, как она может вычитаться из отправляемой суммы. В реальных сценариях комиссия может сниматься иначе (например, за счёт контракта или отдельной транзакции).
Формирование транзакции
amount * 1e9 (наноТОНы).te6cckEBAQEAAgAAAEysucg=, но в реальном проекте он будет отличаться для каждого типа токена.validUntil даёт время (в секундах), в течение которого транзакция считается валидной (например, 10 минут).Подключение к кошельку
tonConnectUI.wallet). Если не подключён, выдаём предупреждение.В реальном обменнике
payload/данных для контракта.Пример выше — упрощённая демонстрация того, как можно использовать логику курсов и отправку транзакции через TonConnect. Для полноценного обмена необходимо дописать/подключить смарт-контракт, который будет хранить резервы и автоматически выдавать нужную валюту в ответ на входящую транзакцию.