# Как обменивать токены
Любой токен, выпущенный на блокчейне Waves, можно обменять на другой токен на децентрализованной бирже. Отправляя ордер (заявку на обмен), вы не передаете токены на биржу — они остаются на вашем аккаунте до момента, когда матчер (движок биржи) выполнит заявку и создаст транзакцию обмена. Блокчейн гарантирует, что условия обмена будут не хуже, чем указаны в заявке. Подробнее см. в разделе Ордер.
Пример децентрализованной биржи — приложение WX Network, разработанное сторонней командой из сообщества.
WX Network не поддерживает обмен NFT и смарт-ассетов.
# Создание ордера
# С помощью WX Network
Используйте online/desktop- или мобильное приложение. См. раздел Как начать торговать на бирже WX Network базы знаний WX Network.
# С помощью CCXT
CCXT (CryptoCurrency eXchange Trading) — JavaScript/Python/PHP-библиотека для торговли криптовалютами и получения рыночных данных. Она поддерживает более 100 бирж, в том числе WX Network.
Обмен с помощью CCXT доступен только для рекомендованных пар токенов. Чтобы обменивать любые пары токенов, используйте другие клиентские библиотеки — см. примеры ниже.
Подробная информация приведена в разделе CCXT для WX Network документации WX Network.
# С помощью JavaScript
# Установка параметров матчера
Используйте следующий адрес матчера:
- Для Testnet: https://matcher-testnet.wx.network
- Для Mainnet: https://matcher.wx.network
Чтобы получить публичный ключ матчера, используйте метод GET /matcher
API матчера.
# Установка ассетной пары
Ассетную пару образуют два ассета, которые вы хотите обменять: amount-ассет и price-ассет. Который из двух ассетов является price-ассетом, не зависит от того, какой ассет вы отдаете и какой получаете.
Вы можете посмотреть ассетные пары и идентификаторы ассетов в WX Network для Mainnet и для Testnet на странице Торговля. Первый ассет в паре — это amount-ассет, второй — price-ассет.
Вы также можете получить ассетные пары с помощью метода GET /matcher/orderbook
или GET /matcher/settings
. Подробнее см. раздел Matcher API документации WX Network.
Идентификаторы ассетов отличаются на Mainnet и на Testnet.
WAVES — главный токен блокчейна Waves — не имеет идентификатора, в качестве ID нужно указывать значение 'WAVES'.
# Заполнение параметров ордера, подписание и отправка на матчер
Используйте функции библиотеки waves-transactions
:
- Функция
order
создает ордер и генерирует подпись. Для генерации подписи используется секретная фраза (seed) аккаунта. - Функция
submitOrder
отправляет подписанный ордер на матчер.
Описание функций приведено в документации библиотеки на GitHub.
Комиссию матчера для ордера можно рассчитать с помощью метода POST /matcher/orderbook/{amountAsset}/{priceAsset}/calculateFee
API матчера. В зависимости от пары ассетов, комиссия может быть фиксированной или процентной. Подробнее в разделе Комиссия матчера документации WX Network.
import { order, submitOrder } from '@waves/waves-transactions';
import fetch from 'node-fetch';
const seed = 'insert your seed here';
const matcherUrl = 'https://matcher-testnet.wx.network';
// Для Mainnet укажите 'https://matcher.wx.network'
const matcherPublicKey = '8QUAqtTckM5B8gvcuP7mMswat9SjKUuafJMusEoSn1Gy';
// Для Mainnet укажите '9cpfKN9suPNvfeUNphzxXMjcnn974eme8ZhWUjaktzU5'
const amountAssetId = 'WAVES';
const priceAssetId = '25FEqEjRkqK6yCkiT7Lz6SAYz7gUFCtxfCChnrVFD5AT'; // XTN на Testnet
// Для Mainnet укажите 'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
// Фактическое количество amount-ассета нужно умножить на 10^amountAssetDecimals
const amount = 100000000; // 1 WAVES
// Цену, выраженную в price-ассете, нужно умножить на 10^(8 + priceAssetDecimals – amountAssetDecimals)
const price = 9500000; // 9,5 XTN за один WAVES
// Получаем комиссию, рассчитанную на основе параметров ордера
let response = await fetch(matcherUrl + '/matcher/orderbook/'
+ amountAssetId + '/' + priceAssetId + '/calculateFee',
{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ orderType: 'buy', amount: amount, price: price })
});
if (!response.ok) console.log("Не удалось рассчитать комиссию");
let fee = await response.json();
let orderParams = {
amount: amount,
price: price,
amountAsset: amountAssetId,
priceAsset: priceAssetId,
matcherPublicKey: matcherPublicKey,
orderType: 'buy',
version: 3,
matcherFee: fee.base.matcherFee,
matcherFeeAssetId: fee.base.feeAssetId
}
const signedOrder = order(orderParams, seed);
await submitOrder(signedOrder, matcherUrl);
let orderId = signedOrder.id;
console.log('ID ордера: '+ orderId);
# С помощью Python
Комиссию матчера для ордера можно рассчитать с помощью метода POST /matcher/orderbook/{amountAsset}/{priceAsset}/calculateFee
API матчера. В зависимости от пары ассетов, комиссия может быть фиксированной или процентной. Подробнее в разделе Комиссия матчера документации WX Network.
import pywaves as pw
import requests
pw.setNode('https://nodes-testnet.wavesnodes.com', chain = 'testnet')
# Для Mainnet: pw.setNode()
pw.setMatcher('https://matcher-testnet.wx.network')
# Для Mainnet: pw.setMatcher()
waves = 'WAVES'
xtn = '25FEqEjRkqK6yCkiT7Lz6SAYz7gUFCtxfCChnrVFD5AT' # XTN на Testnet
# Для Mainnet укажите 'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
asset_pair = pw.AssetPair(pw.Asset(waves), pw.Asset(xtn))
# Фактическое количество amount-ассета нужно умножить на 10^amountAssetDecimals
amount = 100_000_000 # 1 WAVES
price = 9.5 # 9,5 XTN за один WAVES
# Цену, выраженную в price-ассете, нужно умножить на 10^(8 + priceAssetDecimals – amountAssetDecimals)
norm_price = 9_500_000
# Получаем комиссию, рассчитанную на основе параметров ордера
matcher_fee = requests.post(f'{pw.MATCHER}/matcher/orderbook/{waves}/{xtn}/calculateFee',
headers = { 'Accept': 'application/json' },
json = { 'orderType': 'buy', 'amount': amount, 'price': norm_price }
).json()['base']['matcherFee']
my_address = pw.Address(seed = 'insert your seed here')
buy_order = my_address.buy(asset_pair, amount = amount, price = price,
matcherFee = matcher_fee, matcherFeeAssetId = xtn)
print(f'Buy order ID: {buy_order.orderId}')
# Проверка статуса ордера
# С помощью WX Network
Размещенный ордер отображается на вкладке Мои открытые ордера в online/desktop-приложении или на вкладке Мои ордера в мобильном приложении.
# С помощью API матчера
Чтобы получить статус ордера, достаточно знать его идентификатор и ассетную пару. Используйте метод GET /matcher/orderbook/{amountAsset}/{priceAsset}/{orderId}
. Получение статуса доступно для ордеров, размещенный не более 30 дней назад. Для частично выполненных ордеров метод также возвращает сумму выполненной части.
Описание метода приведено в разделе Matcher API документации WX Network.
Пример запроса:
curl 'https://matcher-testnet.wx.network/matcher/orderbook/WAVES/3KFXBGGLCjA5Z2DuW4Dq9fDDrHjJJP1ZEkaoajSzuKsC/9kRXfmrhWhsGBohygMoo91RgcnmJUB37K4rQQN4rEidT'
Приведенный пример подходит для утилиты cURL
. Вы можете адаптировать запрос для своего языка программирования.
# С помощью JavaScript
const matcherUrl = 'https://matcher-testnet.wx.network';
const amountAssetId = 'WAVES';
const priceAssetId = '25FEqEjRkqK6yCkiT7Lz6SAYz7gUFCtxfCChnrVFD5AT'; // XTN на Testnet
// Для Mainnet укажите 'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
const orderId = '9kRXfmrhWhsGBohygMoo91RgcnmJUB37K4rQQN4rEidT';
let response = await fetch(matcherUrl + '/matcher/orderbook/' + amountAsset + '/' + priceAsset + '/' + orderId);
let json = await response.json();
console.log('Статус ордера: ' + json.status);
# С помощью Python
# Используем ордер из предыдущего примера
print(buy_order.status())
# Отмена ордера
Вы можете отменить ордер, если он еще не выполнен полностью.
# С помощью WX Network
Вы можете отменить ордер:
- В online/desktop-приложении: нажмите Отмена на вкладке Мои открытые ордера.
- В мобильном приложении: Note: нажмите X на вкладке Мои ордера.
# С помощью JavaScript
Запрос на отмену ордера должен быть подписан отправителем ордера.
Используйте функции библиотеки waves-transactions
:
- Функция
cancelOrder
создает и подписывает запрос на отмену ордера. - Функция
cancelSubmittedOrder
отправляет подписанный запрос на матчер.
Описание функций см. в документации библиотеки на Github.
Пример:
import {cancelOrder, cancelSubmittedOrder } from "@waves/waves-transactions";
const matcherUrl = 'https://matcher-testnet.wx.network';
const amountAssetId = 'WAVES';
const priceAssetId = '25FEqEjRkqK6yCkiT7Lz6SAYz7gUFCtxfCChnrVFD5AT'; // XTN на Testnet
// Для Mainnet укажите 'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
const seed = 'insert your seed here';
const orderId= '9kRXfmrhWhsGBohygMoo91RgcnmJUB37K4rQQN4rEidT';
const co = cancelOrder({ orderId: orderId }, seed);
const canceledOrder = await cancelSubmittedOrder(co, amountAsset, priceAsset, matcherUrl);
console.log(canceledOrder.status);
# С помощью Python
# Используем ордер из предыдущего примера
buy_order.cancel()
# Получение списка ордеров
# С помощью WX Network
Список ордеров можно посмотреть на вкладках Мои открытые ордера и Моя история ордеров в online/desktop-приложении или на вкладке Мои ордера в мобильном приложении. См. разделы Как начать торговать на бирже WX Network (Online & Desktop) и Как начать торговать на бирже WX Network (Mobile) справки WX Network.
# С помощью JavaScript
Для получения списка размещенных аккаунтом ордеров предназначен метод GET /matcher/orderbook/{publicKey}
. Описание метода приведено в разделе Matcher API документации WX Network.
В заголовке запроса необходимо указать подпись массива байтов, состоящего из байтов публичного ключа аккаунта и байтов текущей временной метки. Для генерации подписи используется функция signBytes и секретная фраза (seed) аккаунта.
import { libs } from '@waves/waves-transactions';
const matcherUrl = 'https://matcher-testnet.wx.network';
const seed = 'insert your seed here';
const { LONG, BASE58_STRING } = libs.marshall.serializePrimitives;
const getOrdersApiSignature = (seed, senderPublicKey, timestamp) => {
const pBytes = BASE58_STRING(senderPublicKey);
const timestampBytes = LONG(timestamp);
const bytes = Uint8Array.from([
...Array.from(pBytes),
...Array.from(timestampBytes),
]);
return libs.crypto.signBytes(seed, bytes);
};
const timestamp = Date.now();
const senderPublicKey = libs.crypto.publicKey(seed);
const signature = getOrdersApiSignature(seed, senderPublicKey, timestamp);
const url = `${matcherUrl}/matcher/orderbook/${senderPublicKey}`; // Добавьте ?activeOnly=true для получения только активных ордеров
let response = await fetch(url, {
headers: {
"Timestamp": timestamp,
"Signature": signature
}
});
let json = await response.json();
console.table(json);
# С помощью Python
Получить список ордеров по заданной ассетной паре, отправленных аккаунтом, можно с помощью функции getOrderHistory
библиотеки PyWaves.
import pywaves as pw
my_address = pw.Address(seed='insert your seed here')
pw.setNode('https://nodes-testnet.wavesnodes.com', chain = 'testnet')
# Для Mainnet: pw.setNode()
pw.setMatcher('https://matcher-testnet.wx.network')
# Для Mainnet: pw.setMatcher()
waves = 'WAVES'
xtn = '25FEqEjRkqK6yCkiT7Lz6SAYz7gUFCtxfCChnrVFD5AT' # XTN on Testnet
# Для Mainnet укажите 'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
asset_pair = pw.AssetPair(pw.Asset(waves), pw.Asset(xtn))
my_orders = my_address.getOrderHistory(asset_pair)