// SPDX-License-Identifier: BSD-3-Clause // Copyright (c) 2020-2021, The Monero Project. #include "xmrto.h" #include "appcontext.h" QMap XmrTo::stateMap; XmrTo::XmrTo(AppContext *ctx, QObject *parent) : QObject(parent), m_ctx(ctx) { m_baseUrl = m_ctx->networkType == NetworkType::Type::MAINNET ? "https://xmr.to" : "https://test.xmr.to"; m_netTor = new UtilsNetworking(this->m_ctx->network); m_netClear = new UtilsNetworking(this->m_ctx->networkClearnet); m_apiTor = new XmrToApi(this, m_netTor, m_baseUrl); m_apiClear = new XmrToApi(this, m_netClear, m_baseUrl); connect(m_apiTor, &XmrToApi::ApiResponse, this, &XmrTo::onApiResponse); connect(m_apiClear, &XmrToApi::ApiResponse, this, &XmrTo::onApiResponse); connect(this, &XmrTo::orderPaymentRequired, this->m_ctx, QOverload::of(&AppContext::onCreateTransaction)); XmrTo::stateMap[OrderState::Status_Idle] = "IDLE"; XmrTo::stateMap[OrderState::Status_OrderCreating] = "CREATING"; XmrTo::stateMap[OrderState::Status_OrderUnpaid] = "UNPAID"; XmrTo::stateMap[OrderState::Status_OrderToBeCreated] = "TO_BE_CREATED"; XmrTo::stateMap[OrderState::Status_OrderUnderPaid] = "UNDERPAID"; XmrTo::stateMap[OrderState::Status_OrderPaidUnconfirmed] = "PAID_UNCONFIRMED"; XmrTo::stateMap[OrderState::Status_OrderPaid] = "PAID"; XmrTo::stateMap[OrderState::Status_OrderBTCSent] = "BTC_SENT"; XmrTo::stateMap[OrderState::Status_OrderTimedOut] = "TIMED_OUT"; XmrTo::stateMap[OrderState::Status_OrderFailed] = "FAILED"; XmrTo::stateMap[OrderState::Status_OrderXMRSent] = "XMR_SENT"; this->tableModel = new XmrToModel(&this->orders, this); } void XmrTo::createOrder(double amount, const QString ¤cy, const QString &btcAddress) { // ^[13][a-km-zA-HJ-NP-Z0-9]{26,33}$ XmrToOrder *order; order = new XmrToOrder(this->m_ctx, m_netTor, m_baseUrl, false, &this->rates, this); connect(order, &XmrToOrder::orderFailed, this, &XmrTo::orderFailed); connect(order, &XmrToOrder::orderPaid, this, &XmrTo::orderPaid); connect(order, &XmrToOrder::orderPaidUnconfirmed, this, &XmrTo::orderPaidUnconfirmed); connect(order, &XmrToOrder::orderPaymentRequired, this, &XmrTo::orderPaymentRequired); connect(order, &XmrToOrder::orderChanged, this->tableModel, &XmrToModel::update); order->create(amount, currency, btcAddress); this->orders.append(order); tableModel->update(); } void XmrTo::onApiResponse(const XmrToResponse &resp) { if (!resp.ok) { this->onApiFailure(resp); return; } emit connectionSuccess(); if (resp.endpoint == Endpoint::RATES) { onRatesReceived(resp.obj); } } void XmrTo::onApiFailure(const XmrToResponse &resp) { emit connectionError(resp.message); } void XmrTo::onGetRates() { m_apiTor->getRates(); } void XmrTo::onRatesReceived(const QJsonObject &doc) { this->rates.price = doc.value("price").toString().toDouble(); this->rates.ln_lower_limit = doc.value("ln_lower_limit").toString().toDouble(); this->rates.ln_upper_limit = doc.value("ln_upper_limit").toString().toDouble(); this->rates.lower_limit = doc.value("lower_limit").toString().toDouble(); this->rates.upper_limit = doc.value("upper_limit").toString().toDouble(); this->rates.zero_conf_enabled = doc.value("zero_conf_enabled").toBool(); this->rates.zero_conf_max_amount = doc.value("zero_conf_enabled").toString().toDouble(); emit ratesUpdated(rates); } void XmrTo::onNetworkChanged(bool clearnet) { m_api = clearnet ? m_apiClear : m_apiTor; } void XmrTo::onWalletClosed() { // @TODO: cleanup for(const auto &order: this->orders) order->deleteLater(); this->tableModel->update(); } void XmrTo::onWalletOpened() { // @TODO: read past XMR.To orders, start pending ones } void XmrTo::onViewOrder(const QString &orderId) { QString url = QString("%1/nojs/status/%2").arg(this->m_baseUrl).arg(orderId); emit openURL(url); }