diff --git a/atomic_defi_design/Dex/Components/DexGradientAppButton.qml b/atomic_defi_design/Dex/Components/DexGradientAppButton.qml index 5624512c13..b4485f7c9a 100644 --- a/atomic_defi_design/Dex/Components/DexGradientAppButton.qml +++ b/atomic_defi_design/Dex/Components/DexGradientAppButton.qml @@ -22,7 +22,6 @@ DexRectangle property bool text_left_align: false - property int minWidth: 90 property real textScale: 1 diff --git a/atomic_defi_design/Dex/Exchange/ProView/DexComboBoxLine.qml b/atomic_defi_design/Dex/Exchange/ProView/DexComboBoxLine.qml index 7c3404f433..0d8269efb9 100644 --- a/atomic_defi_design/Dex/Exchange/ProView/DexComboBoxLine.qml +++ b/atomic_defi_design/Dex/Exchange/ProView/DexComboBoxLine.qml @@ -78,7 +78,7 @@ RowLayout Layout.preferredWidth: parent.width - 15 text_value: !details ? "" : - `${details.ticker}   ${details.name}` + `${details.ticker}
${details.name}` font.pixelSize: Style.textSizeSmall3 elide: Text.ElideRight wrapMode: Text.NoWrap @@ -96,7 +96,7 @@ RowLayout font: DexTypo.body2 wrapMode: Label.NoWrap ToolTip.text: coin_value - Component.onCompleted: font.pixelSize = 11.5 + Component.onCompleted: font.pixelSize = 11 } Dex.Text @@ -112,7 +112,7 @@ RowLayout font: DexTypo.body2 wrapMode: Label.NoWrap ToolTip.text: fiat_value - Component.onCompleted: font.pixelSize = 11.5 + Component.onCompleted: font.pixelSize = 11 } } } diff --git a/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/Main.qml b/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/Main.qml index ca94aec96e..f89056a9eb 100644 --- a/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/Main.qml +++ b/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/Main.qml @@ -11,20 +11,29 @@ import Dex.Components 1.0 as Dex import AtomicDEX.MarketMode 1.0 import AtomicDEX.TradingError 1.0 -Widget +ColumnLayout { - title: qsTr("Place Order") + Layout.preferredWidth: 305 + Layout.fillHeight: true + property alias currentIndex: orderformTabView.currentIndex property int loop_count: 0 property bool show_waiting_for_trade_preimage: false; property var fees: API.app.trading_pg.fees property var preimage_rpc_busy: API.app.trading_pg.preimage_rpc_busy - property string protocolIcon: General.platformIcon(General.coinPlatform(left_ticker)) property var trade_preimage_error: fees.hasOwnProperty('error') ? fees["error"].split("] ").slice(-1) : "" readonly property bool trade_preimage_ready: fees.hasOwnProperty('base_transaction_fees_ticker') - readonly property bool can_submit_trade: last_trading_error === TradingError.None + property int takerOrderform_idx: 0 + property int makerOrderform_idx: 1 - margins: 10 - collapsable: false + function reset_fees_state() + { + show_waiting_for_trade_preimage = false; + check_trade_preimage.stop() + loop_count = 0 + API.app.trading_pg.reset_fees() + takerForm.dexErrors.text_value = "" + makerForm.dexErrors.text_value = "" + } Connections { target: API.app.trading_pg @@ -59,257 +68,135 @@ Widget } } - function reset_fees_state() + Timer { - show_waiting_for_trade_preimage = false; - check_trade_preimage.stop() - loop_count = 0 - API.app.trading_pg.reset_fees() - errors.text_value = "" + id: check_trade_preimage + interval: 500; + running: false; + repeat: true; + triggeredOnStart: true; + onTriggered: { + loop_count++; + console.log("Getting fees info... " + loop_count + "/50") + if (trade_preimage_ready) + { + show_waiting_for_trade_preimage = false + loop_count = 0 + stop() + confirm_trade_modal.open() + } + else if (trade_preimage_error != "") + { + loop_count = 0 + takerForm.dexErrors.text_value = trade_preimage_error.toString() + makerForm.dexErrors.text_value = trade_preimage_error.toString() + show_waiting_for_trade_preimage = false + stop() + } + else if (loop_count > 50) + { + loop_count = 0 + show_waiting_for_trade_preimage = false + trade_preimage_error = "Trade preimage timed out, try again." + stop() + } + } } - // Market mode selector - RowLayout + Qaterial.LatoTabBar { - Layout.topMargin: 5 - Layout.bottomMargin: 2 - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: parent.width - height: 32 + id: orderformTabView - MarketModeSelector + background: null + Layout.leftMargin: 6 + + Qaterial.LatoTabButton { - Layout.alignment: Qt.AlignLeft - Layout.preferredWidth: (parent.width / 100) * 46 - Layout.preferredHeight: 32 - marketMode: MarketMode.Buy - ticker: atomic_qt_utilities.retrieve_main_ticker(left_ticker) + text: qsTr("Taker Order") + font.pixelSize: 14 + textColor: checked ? Dex.CurrentTheme.foregroundColor : Dex.CurrentTheme.foregroundColor2 + textSecondaryColor: Dex.CurrentTheme.foregroundColor2 + indicatorColor: Dex.CurrentTheme.foregroundColor } - - Item { Layout.fillWidth: true } - - MarketModeSelector + Qaterial.LatoTabButton { - Layout.alignment: Qt.AlignRight - Layout.preferredWidth: (parent.width / 100) * 46 - Layout.preferredHeight: 32 - ticker: atomic_qt_utilities.retrieve_main_ticker(left_ticker) + text: qsTr("Maker Order") + font.pixelSize: 14 + textColor: checked ? Dex.CurrentTheme.foregroundColor : Dex.CurrentTheme.foregroundColor2 + textSecondaryColor: Dex.CurrentTheme.foregroundColor2 + indicatorColor: Dex.CurrentTheme.foregroundColor } } - // Protocol text for platform tokens - Item + Rectangle { - height: 32 - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: parent.width - visible: protocolIcon != "" + Layout.fillHeight: true + color: Dex.CurrentTheme.floatingBackgroundColor + radius: 10 + Layout.preferredWidth: 305 - ColumnLayout + Qaterial.SwipeView { - spacing: 2 + id: orderformSwipeView + clip: true + interactive: false + currentIndex: orderformTabView.currentIndex anchors.fill: parent - anchors.centerIn: parent - Dex.Text + onCurrentIndexChanged: { - id: protocolTitle - Layout.preferredWidth: parent.width - text_value: "Protocol:" - font.pixelSize: Style.textSizeSmall1 - horizontalAlignment: Text.AlignHCenter - color: Style.colorText2 + API.app.trading_pg.maker_mode = currentIndex === makerOrderform_idx ? true : false + orderformSwipeView.currentItem.update() + API.app.trading_pg.reset_order() + reset_fees_state() } - RowLayout + Item { - id: protocol - Layout.alignment: Qt.AlignHCenter - - DefaultImage - { - id: protocolImg - source: protocolIcon - Layout.preferredHeight: 16 - Layout.preferredWidth: Layout.preferredHeight - } + id: takerOrderform - DexLabel + OrderForm { - id: protocolText - text_value: General.getProtocolText(left_ticker) - wrapMode: DexLabel.NoWrap - font.pixelSize: Style.textSizeSmall1 - color: Style.colorText2 + id: takerForm + width: parent.width + height: 330 + Layout.alignment: Qt.AlignHCenter + swap_btn.enabled: last_trading_error === TradingError.None && !show_waiting_for_trade_preimage && takerForm.dexErrors.text_value == "" + swap_btn.onClicked: + { + console.log("Getting fees info...") + API.app.trading_pg.determine_fees() + show_waiting_for_trade_preimage = true + check_trade_preimage.start() + } + swap_btn_spinner.visible: show_waiting_for_trade_preimage } } - } - } - - // Order selected indicator - Item - { - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: parent.width - height: 32 - - RowLayout - { - id: orderSelection - visible: API.app.trading_pg.preferred_order.price !== undefined - anchors.fill: parent - anchors.verticalCenter: parent.verticalCenter - DefaultText + Item { - Layout.leftMargin: 15 - color: Dex.CurrentTheme.warningColor - text: qsTr("Order Selected") - } - - Item { Layout.fillWidth: true } + id: makerOrderform - Qaterial.FlatButton - { - Layout.preferredHeight: parent.height - Layout.preferredWidth: 30 - Layout.rightMargin: 5 - foregroundColor: Dex.CurrentTheme.warningColor - onClicked: { - API.app.trading_pg.reset_order() - reset_fees_state() - } - - Qaterial.ColorIcon + OrderForm { - anchors.centerIn: parent - iconSize: 16 - color: Dex.CurrentTheme.warningColor - source: Qaterial.Icons.close + id: makerForm + width: parent.width + height: 330 + Layout.alignment: Qt.AlignHCenter + swap_btn.enabled: last_trading_error === TradingError.None && !show_waiting_for_trade_preimage && makerForm.dexErrors.text_value == "" + swap_btn.onClicked: + { + console.log("Getting fees info...") + console.log("API.app.trading_pg.market_mode") + console.log(API.app.trading_pg.market_mode) + // TODO: Apply reduced fees on maker orders + API.app.trading_pg.determine_fees() + show_waiting_for_trade_preimage = true; + check_trade_preimage.start() + } + swap_btn_spinner.visible: show_waiting_for_trade_preimage } } } - - Rectangle - { - visible: API.app.trading_pg.preferred_order.price !== undefined - anchors.fill: parent - radius: 8 - color: 'transparent' - border.color: Dex.CurrentTheme.warningColor - } - } - - OrderForm - { - id: formBase - width: parent.width - height: 330 - Layout.alignment: Qt.AlignHCenter - } - - Item { Layout.fillHeight: true } - - // Error messages - Item - { - height: 55 - Layout.preferredWidth: parent.width - - // Show errors - Dex.Text - { - id: errors - visible: errors.text_value !== "" - anchors.fill: parent - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - font.pixelSize: Style.textSizeSmall4 - color: Dex.CurrentTheme.warningColor - text_value: General.getTradingError( - last_trading_error, - curr_fee_info, - base_ticker, - rel_ticker, left_ticker, right_ticker) - elide: Text.ElideRight - } - } - - TotalView - { - height: 70 - Layout.preferredWidth: parent.width - Layout.alignment: Qt.AlignHCenter - } - - DexGradientAppButton - { - id: swap_btn - height: 32 - Layout.preferredWidth: parent.width - 30 - Layout.alignment: Qt.AlignHCenter - - radius: 16 - text: qsTr("START SWAP") - font.weight: Font.Medium - enabled: can_submit_trade && !show_waiting_for_trade_preimage && errors.text_value == "" - onClicked: - { - console.log("Getting fees info...") - API.app.trading_pg.determine_fees() - show_waiting_for_trade_preimage = true; - check_trade_preimage.start() - } - - Item - { - visible: show_waiting_for_trade_preimage - height: parent.height - 10 - width: parent.width - 10 - anchors.fill: parent - anchors.centerIn: parent - - DefaultBusyIndicator - { - id: preimage_BusyIndicator - anchors.fill: parent - anchors.centerIn: parent - indicatorSize: 32 - indicatorDotSize: 5 - } - } - } - - Timer { - id: check_trade_preimage - interval: 500; - running: false; - repeat: true; - triggeredOnStart: true; - onTriggered: { - loop_count++; - console.log("Getting fees info... " + loop_count + "/50") - if (trade_preimage_ready) - { - show_waiting_for_trade_preimage = false - loop_count = 0 - stop() - confirm_trade_modal.open() - } - else if (trade_preimage_error != "") - { - loop_count = 0 - errors.text_value = trade_preimage_error.toString() - show_waiting_for_trade_preimage = false - stop() - } - else if (loop_count > 50) - { - loop_count = 0 - show_waiting_for_trade_preimage = false - trade_preimage_error = "Trade preimage timed out, try again." - stop() - } - } } -} +} \ No newline at end of file diff --git a/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/MarketModeSelector.qml b/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/MarketModeSelector.qml index b4ffbdbf17..799e0b8a15 100644 --- a/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/MarketModeSelector.qml +++ b/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/MarketModeSelector.qml @@ -1,4 +1,5 @@ import QtQuick 2.12 +import QtQuick.Layouts 1.15 import App 1.0 import Dex.Themes 1.0 as Dex @@ -9,9 +10,10 @@ Rectangle { property int marketMode: Dex.MarketMode.Sell property string ticker: "" + property string protocolIcon: General.platformIcon(General.coinPlatform(left_ticker)) radius: 18 - opacity: marketMode != API.app.trading_pg.market_mode ? 0.1 : 1 + opacity: marketMode != API.app.trading_pg.market_mode ? 0.25: 1 gradient: Gradient { @@ -32,15 +34,28 @@ Rectangle position: 1 } } - - DefaultText + RowLayout { anchors.centerIn: parent - color: API.app.trading_pg.market_mode == marketMode ? Dex.CurrentTheme.gradientButtonTextEnabledColor : Dex.CurrentTheme.foregroundColor - text: + spacing: 8 + + DefaultText + { + color: API.app.trading_pg.market_mode == marketMode ? Dex.CurrentTheme.gradientButtonTextEnabledColor : Dex.CurrentTheme.foregroundColor + text: + { + if (marketMode == Dex.MarketMode.Sell) qsTr("Sell %1", "TICKER").arg(ticker) + else qsTr("Buy %1", "TICKER").arg(ticker) + } + } + + DefaultImage { - if (marketMode == Dex.MarketMode.Sell) qsTr("Sell %1", "TICKER").arg(ticker) - else qsTr("Buy %1", "TICKER").arg(ticker) + id: protocolImg + visible: protocolIcon != "" + source: protocolIcon + Layout.preferredHeight: protocolIcon != "" ? 16 : 0 + Layout.preferredWidth: Layout.preferredHeight } } diff --git a/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/OrderForm.qml b/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/OrderForm.qml index 3e508ca18c..1cc7440e66 100644 --- a/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/OrderForm.qml +++ b/atomic_defi_design/Dex/Exchange/ProView/PlaceOrderForm/OrderForm.qml @@ -2,14 +2,21 @@ import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQuick.Controls 2.15 import QtGraphicalEffects 1.0 - +import Qaterial 1.0 as Qaterial import "../../../Components" +import "../../../Constants" import App 1.0 import Dex.Themes 1.0 as Dex +import Dex.Components 1.0 as Dex +import AtomicDEX.TradingError 1.0 +import AtomicDEX.MarketMode 1.0 as Dex ColumnLayout { id: root + anchors.horizontalCenter: parent.horizontalCenter + anchors.fill: parent + anchors.margins: 20 spacing: 8 function focusVolumeField() @@ -20,6 +27,9 @@ ColumnLayout readonly property string total_amount: API.app.trading_pg.total_amount readonly property int input_height: 65 readonly property int subfield_margin: 5 + property alias swap_btn: swap_btn + property alias swap_btn_spinner: swap_btn_spinner + property alias dexErrors: dexErrors // Will move to backend: Minimum Fee @@ -52,6 +62,37 @@ ColumnLayout function onBackend_volumeChanged() { input_volume.text = exchange_trade.backend_volume; } } + // Market mode selector + RowLayout + { + Layout.topMargin: 2 + Layout.bottomMargin: 2 + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: parent.width + height: 28 + visible: !API.app.trading_pg.maker_mode + + MarketModeSelector + { + Layout.alignment: Qt.AlignLeft + Layout.preferredWidth: 125 + Layout.preferredHeight: 28 + marketMode: Dex.MarketMode.Buy + ticker: atomic_qt_utilities.retrieve_main_ticker(left_ticker) + } + + Item { Layout.fillWidth: true } + + MarketModeSelector + { + marketMode: Dex.MarketMode.Sell + Layout.alignment: Qt.AlignRight + Layout.preferredWidth: 125 + Layout.preferredHeight: 28 + ticker: atomic_qt_utilities.retrieve_main_ticker(left_ticker) + } + } + Item { Layout.preferredWidth: parent.width @@ -263,4 +304,121 @@ ColumnLayout font.pixelSize: 13 } } + + + Item { Layout.fillHeight: true } + + // Error messages + // TODO: Move to toasts + Item + { + height: 55 + Layout.preferredWidth: parent.width + + // Show errors + Dex.Text + { + id: dexErrors + visible: dexErrors.text_value !== "" + anchors.fill: parent + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + font.pixelSize: Style.textSizeSmall4 + color: Dex.CurrentTheme.warningColor + text_value: General.getTradingError( + last_trading_error, + curr_fee_info, + base_ticker, + rel_ticker, left_ticker, right_ticker) + elide: Text.ElideRight + } + } + + Item { Layout.fillHeight: true } + + // Order selected indicator + Item + { + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: parent.width - 16 + height: 28 + + RowLayout + { + id: orderSelection + visible: API.app.trading_pg.preferred_order.price !== undefined + anchors.fill: parent + anchors.verticalCenter: parent.verticalCenter + + DefaultText + { + Layout.leftMargin: 15 + color: Dex.CurrentTheme.warningColor + text: qsTr("Order Selected") + } + + Item { Layout.fillWidth: true } + + Qaterial.FlatButton + { + Layout.preferredHeight: parent.height + Layout.preferredWidth: 30 + Layout.rightMargin: 5 + foregroundColor: Dex.CurrentTheme.warningColor + onClicked: { + API.app.trading_pg.reset_order() + reset_fees_state() + } + + Qaterial.ColorIcon + { + anchors.centerIn: parent + iconSize: 16 + color: Dex.CurrentTheme.warningColor + source: Qaterial.Icons.close + } + } + } + + Rectangle + { + visible: API.app.trading_pg.preferred_order.price !== undefined + anchors.fill: parent + radius: 8 + color: 'transparent' + border.color: Dex.CurrentTheme.warningColor + } + } + + + TotalView + { + height: 70 + Layout.preferredWidth: parent.width + Layout.alignment: Qt.AlignHCenter + } + + DefaultBusyIndicator + { + id: swap_btn_spinner + Layout.alignment: Qt.AlignHCenter + indicatorSize: 28 + indicatorDotSize: 4 + } + Item + { + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: parent.width - 16 + height: 28 + + DexGradientAppButton + { + id: swap_btn + height: 32 + anchors.fill: parent + radius: 16 + text: API.app.trading_pg.maker_mode ? qsTr("CREATE MAKER SWAP") : qsTr("START TAKER SWAP") + font.weight: Font.Medium + } + } } \ No newline at end of file diff --git a/atomic_defi_design/Dex/Exchange/ProView/SearchableTickerSelector.qml b/atomic_defi_design/Dex/Exchange/ProView/SearchableTickerSelector.qml index 6bda8f68fe..68b621ef0d 100644 --- a/atomic_defi_design/Dex/Exchange/ProView/SearchableTickerSelector.qml +++ b/atomic_defi_design/Dex/Exchange/ProView/SearchableTickerSelector.qml @@ -18,13 +18,13 @@ Dex.ComboBoxWithSearchBar property string ticker property bool index_changed: false - height: 70 + height: 85 enabled: !block_everything textRole: "ticker" valueRole: "ticker" - popupMaxHeight: Math.min(model.rowCount() * 70 + 70, 600) + popupMaxHeight: Math.min(model.rowCount() * 85 + 85, 600) popupForceMaxHeight: true searchBar.visible: true @@ -34,7 +34,7 @@ Dex.ComboBoxWithSearchBar { id: _delegate width: control.width - height: visible ? 70 : 0 + height: visible ? 85 : 0 highlighted: control.highlightedIndex === index contentItem: DexComboBoxLine { details: model } @@ -52,7 +52,7 @@ Dex.ComboBoxWithSearchBar property int update_count: 0 property var prev_details - padding: 10 + padding: 8 function forceUpdateDetails() { diff --git a/atomic_defi_design/Dex/Exchange/ProView/TickerSelectors.qml b/atomic_defi_design/Dex/Exchange/ProView/TickerSelectors.qml index 6c52fed103..8b317cecba 100644 --- a/atomic_defi_design/Dex/Exchange/ProView/TickerSelectors.qml +++ b/atomic_defi_design/Dex/Exchange/ProView/TickerSelectors.qml @@ -6,9 +6,12 @@ import "../../Components" import "../../Constants" // Ticker selectors. -Row +RowLayout { id: selectors + Layout.topMargin: 8 + Layout.bottomMargin: 2 + Layout.alignment: Qt.AlignHCenter function renewIndex() { @@ -21,9 +24,8 @@ Row SearchableTickerSelector { id: selectorLeft - - width: 210 - height: parent.height + Layout.preferredWidth: 195 + Layout.preferredHeight: 85 left_side: true model: API.app.trading_pg.market_pairs_mdl.left_selection_box @@ -38,10 +40,12 @@ Row } } + Item { Layout.fillWidth: true } + SwapIcon { - width: 25 - anchors.verticalCenter: parent.verticalCenter + Layout.preferredHeight: 25 + Layout.alignment: Qt.AlignVCenter top_arrow_ticker: selectorLeft.ticker bottom_arrow_ticker: selectorRight.ticker hovered: swap_button.containsMouse @@ -59,13 +63,13 @@ Row } } + Item { Layout.fillWidth: true } + SearchableTickerSelector { id: selectorRight - - width: 210 - height: parent.height - + Layout.preferredWidth: 195 + Layout.preferredHeight: 85 left_side: false model: API.app.trading_pg.market_pairs_mdl.right_selection_box ticker: right_ticker diff --git a/atomic_defi_design/Dex/Exchange/ProView/TradingInfo/Main.qml b/atomic_defi_design/Dex/Exchange/ProView/TradingInfo/Main.qml index cb6f0d4425..3246d7b555 100644 --- a/atomic_defi_design/Dex/Exchange/ProView/TradingInfo/Main.qml +++ b/atomic_defi_design/Dex/Exchange/ProView/TradingInfo/Main.qml @@ -5,6 +5,8 @@ import QtQuick.Controls 2.15 import Qaterial 1.0 as Qaterial import Dex.Themes 1.0 as Dex +import Dex.Components 1.0 as Dex +import AtomicDEX.MarketMode 1.0 import "../../../Constants" import "../../../Components" import "../../Trade" @@ -13,6 +15,7 @@ import "../../ProView" ColumnLayout { Layout.preferredWidth: 450 + Layout.fillHeight: true property alias currentIndex: tabView.currentIndex Qaterial.LatoTabBar @@ -70,7 +73,19 @@ ColumnLayout { Layout.fillHeight: true Layout.fillWidth: true - spacing: 10 + Layout.topMargin: 8 + spacing: 8 + + // Ticker selectors. + TickerSelectors + { + id: selectors + Layout.preferredWidth: 435 + Layout.preferredHeight: 85 + Layout.leftMargin: 8 + Layout.rightMargin: 8 + } + // Chart Chart { @@ -91,6 +106,7 @@ ColumnLayout Layout.rightMargin: 5 Layout.fillWidth: true Layout.fillHeight: true + width: 435 } } diff --git a/atomic_defi_design/Dex/Exchange/ProView/TradingInfo/PriceLine.qml b/atomic_defi_design/Dex/Exchange/ProView/TradingInfo/PriceLine.qml index cab141ecff..4eb305bef1 100644 --- a/atomic_defi_design/Dex/Exchange/ProView/TradingInfo/PriceLine.qml +++ b/atomic_defi_design/Dex/Exchange/ProView/TradingInfo/PriceLine.qml @@ -66,17 +66,6 @@ ColumnLayout visible: price_entered && !invalid_cex_price Layout.alignment: Qt.AlignCenter - DefaultText - { - id: price_diff_text - Layout.topMargin: 10 - Layout.bottomMargin: Layout.topMargin - Layout.alignment: Qt.AlignHCenter - color: parseFloat(cexPriceDiff) <= 0 ? Dex.CurrentTheme.okColor : Dex.CurrentTheme.warningColor - text_value: (parseFloat(cexPriceDiff) > 0 ? qsTr("Expensive") : qsTr("Expedient")) + ":    " + qsTr("%1 compared to CEX", "PRICE_DIFF%").arg("" + General.formatPercent(General.limitDigits(cexPriceDiff)) + "") - font.pixelSize: fontSize - } - RowLayout { Layout.alignment: Qt.AlignHCenter @@ -103,6 +92,15 @@ ColumnLayout } } + DefaultText + { + id: price_diff_text + anchors.horizontalCenter: parent.horizontalCenter + color: parseFloat(cexPriceDiff) <= 0 ? Dex.CurrentTheme.okColor : Dex.CurrentTheme.warningColor + text_value: (parseFloat(cexPriceDiff) > 0 ? qsTr("Expensive") : qsTr("Expedient")) + ":    " + qsTr("%1 compared to CEX", "PRICE_DIFF%").arg("" + General.formatPercent(General.limitDigits(cexPriceDiff)) + "") + font.pixelSize: fontSizeBigger + } + DefaultText { text_value: General.formatPercent(-lineScale) diff --git a/atomic_defi_design/Dex/Exchange/Trade/BestOrder/List.qml b/atomic_defi_design/Dex/Exchange/Trade/BestOrder/List.qml index 85a7be4ebe..552ee7bbff 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/BestOrder/List.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/BestOrder/List.qml @@ -14,9 +14,11 @@ import Dex.Components 1.0 as Dex Widget { id: _control - title: qsTr("Best Orders") + title: qsTr("Best Orders for %1").arg(left_ticker) + margins: 10 spacing: 10 + collapsable: false Header { diff --git a/atomic_defi_design/Dex/Exchange/Trade/BestOrder/ListDelegate.qml b/atomic_defi_design/Dex/Exchange/Trade/BestOrder/ListDelegate.qml index bcf1fa9c30..be08030d7a 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/BestOrder/ListDelegate.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/BestOrder/ListDelegate.qml @@ -169,15 +169,22 @@ Item else { placeOrderForm.visible = General.flipFalse(placeOrderForm.visible) - if (API.app.trading_pg.market_mode == MarketMode.Buy) + if (!API.app.trading_pg.maker_mode) { - app.pairChanged(coin, rel_ticker) + if (API.app.trading_pg.market_mode == MarketMode.Buy) + { + app.pairChanged(coin, rel_ticker) + } + else + { + app.pairChanged(base_ticker, coin) + } + API.app.trading_pg.orderbook.select_best_order(uuid) } else { - app.pairChanged(base_ticker, coin) + setPair(false, coin) } - API.app.trading_pg.orderbook.select_best_order(uuid) } } } diff --git a/atomic_defi_design/Dex/Exchange/Trade/ConfirmTradeModal.qml b/atomic_defi_design/Dex/Exchange/Trade/ConfirmTradeModal.qml index 4054ef6606..8056ecbef9 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/ConfirmTradeModal.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/ConfirmTradeModal.qml @@ -17,8 +17,9 @@ MultipageModal id: root readonly property var fees: API.app.trading_pg.fees width: 720 - horizontalPadding: 20 - verticalPadding: 20 + height: window.height - 80 + horizontalPadding: 10 + verticalPadding: 10 closePolicy: Popup.NoAutoClose MultipageModalContent @@ -28,7 +29,7 @@ MultipageModal titleAlignment: Qt.AlignHCenter titleTopMargin: 0 topMarginAfterTitle: 10 - flickMax: window.height - 480 + flickMax: window.height - 385 header: [ RowLayout @@ -43,6 +44,7 @@ MultipageModal PairItemBadge { ticker: base_ticker + is_left: true fullname: General.coinName(base_ticker) amount: base_amount Layout.fillHeight: true @@ -75,59 +77,6 @@ MultipageModal { id: price_line Layout.fillWidth: true - }, - - ColumnLayout - { - id: warnings_text - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - - // Large margin warning - FloatingBackground - { - Layout.alignment: Qt.AlignCenter - width: childrenRect.width - height: childrenRect.height - color: Style.colorRed2 - visible: Math.abs(parseFloat(API.app.trading_pg.cex_price_diff)) >= 50 - - RowLayout - { - Layout.fillWidth: true - - Item { width: 3 } - - DefaultCheckBox - { - id: allow_bad_trade - Layout.alignment: Qt.AlignCenter - textColor: Style.colorWhite0 - visible: Math.abs(parseFloat(API.app.trading_pg.cex_price_diff)) >= 50 - spacing: 2 - boxWidth: 16 - boxHeight: 16 - boxRadius: 8 - label.wrapMode: Label.NoWrap - text: qsTr("Trade price is more than 50% different to CEX! Confirm?") - font: DexTypo.caption - } - } - } - - DefaultText - { - Layout.alignment: Qt.AlignHCenter - text_value: qsTr("This swap request can not be undone and is a final event!") - } - - DefaultText - { - id: warnings_tx_time_text - Layout.alignment: Qt.AlignHCenter - text_value: qsTr("This transaction can take up to 60 mins - DO NOT close this application!") - font.pixelSize: Style.textSizeSmall4 - } } ] @@ -138,9 +87,9 @@ MultipageModal readonly property var default_config: API.app.trading_pg.get_raw_mm2_coin_cfg(rel_ticker) readonly property bool is_dpow_configurable: config_section.default_config.requires_notarization || false - width: dex_pair_badges.width - 20 + width: dex_pair_badges.width - 40 Layout.alignment: Qt.AlignCenter - Layout.topMargin: 8 + Layout.topMargin: 4 spacing: 5 @@ -239,7 +188,39 @@ MultipageModal } } - // Custom config checkbox + // Large margin warning + FloatingBackground + { + Layout.alignment: Qt.AlignCenter + width: childrenRect.width + height: childrenRect.height + color: Style.colorRed2 + visible: Math.abs(parseFloat(API.app.trading_pg.cex_price_diff)) >= 50 + + RowLayout + { + Layout.fillWidth: true + + Item { width: 3 } + + DefaultCheckBox + { + id: allow_bad_trade + Layout.alignment: Qt.AlignCenter + textColor: Style.colorWhite0 + visible: Math.abs(parseFloat(API.app.trading_pg.cex_price_diff)) >= 50 + spacing: 2 + boxWidth: 16 + boxHeight: 16 + boxRadius: 8 + label.wrapMode: Label.NoWrap + text: qsTr("Trade price is more than 50% different to CEX! Confirm?") + font: DexTypo.caption + } + } + } + + // Custom config section Item { Layout.alignment: Qt.AlignCenter @@ -251,9 +232,30 @@ MultipageModal { id: use_custom anchors.horizontalCenter: parent.horizontalCenter - spacing: 5 + DefaultCheckBox + { + id: _cancelPreviousCheckbox + visible: API.app.trading_pg.maker_mode + boxWidth: 20 + boxHeight: 20 + checked: true + height: 40 + text: qsTr("Cancel all existing orders for %1/%2?").arg(base_ticker).arg(rel_ticker) + } + + DefaultCheckBox + { + id: _goodUntilCanceledCheckbox + visible: !API.app.trading_pg.maker_mode + boxWidth: 20 + boxHeight: 20 + checked: true + height: 40 + text: qsTr("Good until cancelled (order will remain on orderbook until filled or cancelled)") + } + DefaultCheckBox { id: enable_custom_config @@ -261,7 +263,7 @@ MultipageModal spacing: 2 boxWidth: 20 boxHeight: 20 - height: 50 + height: 40 label.wrapMode: Label.NoWrap text: qsTr("Use custom protection settings for incoming %1 transactions", "TICKER").arg(rel_ticker) @@ -390,6 +392,31 @@ MultipageModal } } + ColumnLayout + { + id: warnings_text + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + + + DefaultText + { + Layout.alignment: Qt.AlignHCenter + text_value: qsTr("This swap request can not be undone and is a final event!") + font: DexTypo.italic12 + color: Dex.CurrentTheme.foregroundColor2 + } + + DefaultText + { + id: warnings_tx_time_text + Layout.alignment: Qt.AlignHCenter + text_value: qsTr("This transaction can take up to 60 mins - DO NOT close this application!") + font: DexTypo.italic12 + color: Dex.CurrentTheme.foregroundColor2 + } + } + Item { visible: buy_sell_rpc_busy @@ -437,7 +464,9 @@ MultipageModal trade({ enable_custom_config: enable_custom_config.checked, is_dpow_configurable: config_section.is_dpow_configurable, enable_dpow_confs: enable_dpow_confs.checked, - required_confirmation_count: required_confirmation_count.value, }, + required_confirmation_count: required_confirmation_count.value, + cancel_previous: _cancelPreviousCheckbox.checked, + good_until_canceled: _goodUntilCanceledCheckbox.checked}, config_section.default_config) API.app.trading_pg.reset_fees() } diff --git a/atomic_defi_design/Dex/Exchange/Trade/Market.qml b/atomic_defi_design/Dex/Exchange/Trade/Market.qml index 2940068ecf..3c6af075e6 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/Market.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/Market.qml @@ -73,16 +73,12 @@ ColumnLayout OrderBook.Vertical { id: orderBook - Layout.fillHeight: true - Layout.fillWidth: true } // Best Orders BestOrder.List { id: bestOrders - Layout.fillHeight: true - Layout.fillWidth: true } } } diff --git a/atomic_defi_design/Dex/Exchange/Trade/OrderBook/List.qml b/atomic_defi_design/Dex/Exchange/Trade/OrderBook/List.qml index 23e54d6606..16b15f0d9d 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/OrderBook/List.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/OrderBook/List.qml @@ -25,6 +25,7 @@ Item clip: true reuseItems: true spacing: 8 + opacity: API.app.trading_pg.maker_mode ? 0.6 : 1 onContentHeightChanged: { diff --git a/atomic_defi_design/Dex/Exchange/Trade/OrderBook/ListDelegate.qml b/atomic_defi_design/Dex/Exchange/Trade/OrderBook/ListDelegate.qml index 2e21b85061..03819d17fe 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/OrderBook/ListDelegate.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/OrderBook/ListDelegate.qml @@ -45,6 +45,10 @@ Item { if (mouse_area.containsMouse) { + if (API.app.trading_pg.maker_mode) + { + return qsTr("Orderbook is disabled while creating maker orders") + } let relMaxTakerVol = parseFloat(API.app.trading_pg.orderbook.rel_max_taker_vol.decimal); let baseMaxTakerVol = parseFloat(API.app.trading_pg.orderbook.base_max_taker_vol.decimal); @@ -106,6 +110,7 @@ Item onClicked: { if (is_mine) return + if (API.app.trading_pg.maker_mode) return if (enough_funds_to_pay_min_volume ) { diff --git a/atomic_defi_design/Dex/Exchange/Trade/OrderBook/Vertical.qml b/atomic_defi_design/Dex/Exchange/Trade/OrderBook/Vertical.qml index 4a572f8b9d..74d07bcafc 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/OrderBook/Vertical.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/OrderBook/Vertical.qml @@ -11,13 +11,14 @@ import Dex.Themes 1.0 as Dex Widget { - title: qsTr("Order Book") + title: qsTr("%1 Orderbook").arg(left_ticker + "/" + right_ticker) readonly property string pair_trades_24hr: API.app.trading_pg.pair_trades_24hr readonly property string pair_volume_24hr: API.app.trading_pg.pair_volume_24hr readonly property string pair: atomic_qt_utilities.retrieve_main_ticker(left_ticker) + "/" + atomic_qt_utilities.retrieve_main_ticker(right_ticker) - margins: 8 - spacing: 2 + margins: 10 + spacing: 10 + collapsable: false Header { diff --git a/atomic_defi_design/Dex/Exchange/Trade/PriceLineSimplified.qml b/atomic_defi_design/Dex/Exchange/Trade/PriceLineSimplified.qml index abbc8c8125..4eb4d92c18 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/PriceLineSimplified.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/PriceLineSimplified.qml @@ -22,7 +22,7 @@ ColumnLayout readonly property int fontSizeBigger: Style.textSizeSmall2 readonly property int lineScale: General.getComparisonScale(cexPriceDiff) - spacing: 35 + spacing: 24 RowLayout { @@ -126,10 +126,22 @@ ColumnLayout { text_value: General.formatPercent(lineScale) font.pixelSize: fontSize + anchors.left: parent.left anchors.top: parent.top anchors.topMargin: -15 } + DefaultText + { + id: price_diff_text + anchors.top: parent.top + anchors.topMargin: -15 + anchors.horizontalCenter: parent.horizontalCenter + color: parseFloat(cexPriceDiff) <= 0 ? Dex.CurrentTheme.okColor : Dex.CurrentTheme.warningColor + text_value: (parseFloat(cexPriceDiff) > 0 ? qsTr("Expensive") : qsTr("Expedient")) + ":    " + qsTr("%1 compared to CEX", "PRICE_DIFF%").arg("" + General.formatPercent(General.limitDigits(cexPriceDiff)) + "") + font.pixelSize: fontSizeBigger + } + DefaultText { text_value: General.formatPercent(-lineScale) @@ -141,14 +153,5 @@ ColumnLayout } } - DefaultText - { - id: price_diff_text - Layout.topMargin: 10 - Layout.alignment: Qt.AlignHCenter - color: parseFloat(cexPriceDiff) <= 0 ? Dex.CurrentTheme.okColor : Dex.CurrentTheme.warningColor - text_value: (parseFloat(cexPriceDiff) > 0 ? qsTr("Expensive") : qsTr("Expedient")) + ":    " + qsTr("%1 compared to CEX", "PRICE_DIFF%").arg("" + General.formatPercent(General.limitDigits(cexPriceDiff)) + "") - font.pixelSize: fontSize - } } } diff --git a/atomic_defi_design/Dex/Exchange/Trade/ProView.qml b/atomic_defi_design/Dex/Exchange/Trade/ProView.qml index 9550a275fc..6ebe7a1f6b 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/ProView.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/ProView.qml @@ -40,7 +40,6 @@ RowLayout { id: form - property alias tickerSelectors: selectors property alias trInfo: tradingInfo property alias marketsOrderBook: marketsOrderBook property alias placeOrderForm: placeOrderForm @@ -108,29 +107,14 @@ RowLayout } } - ColumnLayout + // Trading Informations + TradingInfo.Main { + id: tradingInfo Layout.alignment: Qt.AlignTop - Layout.minimumWidth: selectors.visible || tradingInfo.visible ? 450 : -1 - Layout.maximumWidth: (!orderBook.visible && !bestOrders.visible) || (!placeOrderForm.visible) ? -1 : 450 + Layout.minimumWidth: tradingInfo.visible ? 450 : -1 + Layout.maximumWidth: (!marketsOrderBook.visible) || (!placeOrderForm.visible) ? -1 : 450 Layout.fillHeight: true - spacing: 10 - - // Ticker selectors. - TickerSelectors - { - id: selectors - Layout.fillWidth: true - Layout.preferredHeight: 70 - } - - // Trading Informations - TradingInfo.Main - { - id: tradingInfo - Layout.maximumWidth: 450 - Layout.fillHeight: true - } } // Best Orders & Order Book @@ -153,13 +137,11 @@ RowLayout Layout.maximumWidth: 305 Layout.fillWidth: true Layout.fillHeight: true - - resizable: false } ModalLoader { id: confirm_trade_modal - sourceComponent: ConfirmTradeModal {} + sourceComponent: ConfirmTradeModal { } } } diff --git a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/OrderRemovedModal.qml b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/OrderRemovedModal.qml index dc49f96c39..4d5c8fe011 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/OrderRemovedModal.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/OrderRemovedModal.qml @@ -17,7 +17,7 @@ MultipageModal Layout.fillWidth: true wrapMode: Text.WordWrap - text: qsTr("The selected order does not exist anymore, it might have been matched or canceled, and no order with a better price is available.\nPlease select a new order.") + text: qsTr("The selected order does not exist anymore, it might have been matched or cancelled, and no order with a better price is available.\nPlease select a new order.") } footer: diff --git a/atomic_defi_design/Dex/Exchange/Trade/Trade.qml b/atomic_defi_design/Dex/Exchange/Trade/Trade.qml index a102ecb8ce..aba6f1c6ba 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/Trade.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/Trade.qml @@ -48,27 +48,32 @@ Item readonly property bool price_is_empty: parseFloat(non_null_price) <= 0 readonly property string backend_price: API.app.trading_pg.price + readonly property int last_trading_error: API.app.trading_pg.last_trading_error + readonly property string max_volume: API.app.trading_pg.max_volume + readonly property string backend_volume: API.app.trading_pg.volume + property bool sell_mode: API.app.trading_pg.market_mode.toString() === "Sell" + readonly property string base_amount: API.app.trading_pg.base_amount + readonly property string rel_amount: API.app.trading_pg.rel_amount + function setPrice(v) { API.app.trading_pg.price = v API.app.trading_pg.determine_error_cases() } - readonly property int last_trading_error: API.app.trading_pg.last_trading_error - readonly property string max_volume: API.app.trading_pg.max_volume - readonly property string backend_volume: API.app.trading_pg.volume + function setVolume(v) { API.app.trading_pg.volume = v API.app.trading_pg.determine_error_cases() } + + function setMakerMode(v) { + API.app.trading_pg.maker_mode = v + } - property bool sell_mode: API.app.trading_pg.market_mode.toString( - ) === "Sell" function setMarketMode(v) { API.app.trading_pg.market_mode = v } - readonly property string base_amount: API.app.trading_pg.base_amount - readonly property string rel_amount: API.app.trading_pg.rel_amount - + Timer { id: swap_cooldown @@ -144,9 +149,20 @@ Item } if (sell_mode) - API.app.trading_pg.place_sell_order(nota, confs) + { + if (API.app.trading_pg.maker_mode) + { + API.app.trading_pg.place_setprice_order(nota, confs, options.cancel_previous) + } + else + { + API.app.trading_pg.place_sell_order(nota, confs, options.good_until_canceled) + } + } else - API.app.trading_pg.place_buy_order(nota, confs) + { + API.app.trading_pg.place_buy_order(nota, confs, options.good_until_canceled) + } orderPlaced() } @@ -170,7 +186,6 @@ Item width: parent.width height: parent.height * 0.06 - proViewTickerSelectors: proView.tickerSelectors proViewTrInfo: proView.trInfo proViewMarketsOrderBook: proView.marketsOrderBook proViewPlaceOrderForm: proView.placeOrderForm diff --git a/atomic_defi_design/Dex/Exchange/Trade/Trading/TradeViewHeader.qml b/atomic_defi_design/Dex/Exchange/Trade/Trading/TradeViewHeader.qml index be41d57a74..f92fc23130 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/Trading/TradeViewHeader.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/Trading/TradeViewHeader.qml @@ -19,7 +19,6 @@ import "../../../Constants" Item { // property var proViewChart - property var proViewTickerSelectors property var proViewTrInfo property var proViewMarketsOrderBook property var proViewPlaceOrderForm @@ -34,8 +33,8 @@ Item { id: cursorRect width: _simpleLabel.width + 28 - height: _simpleLabel.height + 14 - radius: 16 + height: _simpleLabel.height + 8 + radius: 8 anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: API.app.trading_pg.current_trading_mode == TradingMode.Simple ? _simpleLabel.horizontalCenter : _proLabel.horizontalCenter color: Dex.CurrentTheme.tabSelectedColor @@ -90,11 +89,12 @@ Item outlined: false highlighted: false + padding: 6 foregroundColor: Dex.CurrentTheme.foregroundColor icon.source: Qaterial.Icons.cog text: qsTr("Pro View Settings") - font: DexTypo.subtitle1 + font: DexTypo.subtitle2 onClicked: { @@ -110,31 +110,27 @@ Item contentItem: Item { implicitWidth: 200 - implicitHeight: 240 + implicitHeight: 200 Column { anchors.fill: parent - padding: 10 + padding: 8 spacing: 8 DefaultText { text: qsTr("Display Settings"); font: DexTypo.body2 } HorizontalLine { width: parent.width - 20; anchors.horizontalCenter: parent.horizontalCenter; opacity: .4 } - CheckEye { text: qsTr("Ticker Selectors"); target: proViewTickerSelectors } - - HorizontalLine { width: parent.width - 20; anchors.horizontalCenter: parent.horizontalCenter; opacity: .4 } - CheckEye { text: qsTr("Trading Information"); target: proViewTrInfo } HorizontalLine { width: parent.width - 20; anchors.horizontalCenter: parent.horizontalCenter; opacity: .4 } - CheckEye { text: qsTr("Markets"); target: proViewMarketsOrderBook } + CheckEye { text: qsTr("Order Book"); target: proViewMarketsOrderBook } HorizontalLine { width: parent.width - 20; anchors.horizontalCenter: parent.horizontalCenter; opacity: .4 } - CheckEye { text: qsTr("Place Order"); target: proViewPlaceOrderForm } + CheckEye { text: qsTr("Order Form"); target: proViewPlaceOrderForm } } } } diff --git a/src/core/atomicdex/api/mm2/rpc_v1/rpc.buy.cpp b/src/core/atomicdex/api/mm2/rpc_v1/rpc.buy.cpp index 06778770c5..00f1680723 100644 --- a/src/core/atomicdex/api/mm2/rpc_v1/rpc.buy.cpp +++ b/src/core/atomicdex/api/mm2/rpc_v1/rpc.buy.cpp @@ -15,7 +15,6 @@ ******************************************************************************/ //! Deps -#include #include //! Project Headers @@ -75,5 +74,9 @@ namespace atomic_dex::mm2 { SPDLOG_INFO("The order is not picked from orderbook we create it from volume = {}, price = {}", j.at("volume").dump(4), request.price); } + if (request.order_type.has_value()) + { + j["order_type"] = request.order_type.value(); + } } } // namespace atomic_dex::mm2 \ No newline at end of file diff --git a/src/core/atomicdex/api/mm2/rpc_v1/rpc.buy.hpp b/src/core/atomicdex/api/mm2/rpc_v1/rpc.buy.hpp index 5e31e108e4..8ad547d304 100644 --- a/src/core/atomicdex/api/mm2/rpc_v1/rpc.buy.hpp +++ b/src/core/atomicdex/api/mm2/rpc_v1/rpc.buy.hpp @@ -21,7 +21,7 @@ #include //! Deps -#include +#include //! Project Header #include @@ -43,7 +43,9 @@ namespace atomic_dex::mm2 bool selected_order_use_input_volume{false}; std::optional base_nota{std::nullopt}; std::optional base_confs{std::nullopt}; + // bool is_max; std::optional min_volume{std::nullopt}; + std::optional order_type; }; void to_json(nlohmann::json& j, const buy_request& request); diff --git a/src/core/atomicdex/api/mm2/rpc_v1/rpc.sell.cpp b/src/core/atomicdex/api/mm2/rpc_v1/rpc.sell.cpp index 6779feb367..4566ea7e48 100644 --- a/src/core/atomicdex/api/mm2/rpc_v1/rpc.sell.cpp +++ b/src/core/atomicdex/api/mm2/rpc_v1/rpc.sell.cpp @@ -15,7 +15,6 @@ ******************************************************************************/ //! Deps -#include #include //! Project Headers diff --git a/src/core/atomicdex/api/mm2/rpc_v1/rpc.setprice.cpp b/src/core/atomicdex/api/mm2/rpc_v1/rpc.setprice.cpp index a9d0816d74..6977cefa90 100644 --- a/src/core/atomicdex/api/mm2/rpc_v1/rpc.setprice.cpp +++ b/src/core/atomicdex/api/mm2/rpc_v1/rpc.setprice.cpp @@ -28,8 +28,10 @@ namespace atomic_dex::mm2 j["price"] = request.price; j["rel"] = request.rel; j["volume"] = request.volume; - j["cancel_previous"] = request.cancel_previous; - j["max"] = request.max; + if (request.cancel_previous.has_value()) + { + j["cancel_previous"] = request.cancel_previous.value(); + } if (request.base_nota.has_value()) { j["base_nota"] = request.base_nota.value(); diff --git a/src/core/atomicdex/api/mm2/rpc_v1/rpc.setprice.hpp b/src/core/atomicdex/api/mm2/rpc_v1/rpc.setprice.hpp index 8eb234e274..f169a0002d 100644 --- a/src/core/atomicdex/api/mm2/rpc_v1/rpc.setprice.hpp +++ b/src/core/atomicdex/api/mm2/rpc_v1/rpc.setprice.hpp @@ -31,8 +31,7 @@ namespace atomic_dex::mm2 std::string rel; std::string price; std::string volume; - bool max{false}; - bool cancel_previous{false}; + std::optional cancel_previous{false}; std::optional base_nota; std::optional base_confs; std::optional rel_nota; diff --git a/src/core/atomicdex/pages/qt.trading.page.cpp b/src/core/atomicdex/pages/qt.trading.page.cpp index 7499496a68..4ee89c213f 100644 --- a/src/core/atomicdex/pages/qt.trading.page.cpp +++ b/src/core/atomicdex/pages/qt.trading.page.cpp @@ -21,6 +21,7 @@ //! Project Headers #include "atomicdex/api/mm2/rpc_v1/rpc.buy.hpp" #include "atomicdex/api/mm2/rpc_v1/rpc.sell.hpp" +#include "atomicdex/api/mm2/rpc_v1/rpc.setprice.hpp" #include "atomicdex/api/mm2/rpc_v2/rpc2.trade_preimage.hpp" #include "atomicdex/pages/qt.portfolio.page.hpp" #include "atomicdex/pages/qt.settings.page.hpp" @@ -138,7 +139,91 @@ namespace atomic_dex } void - trading_page::place_buy_order(const QString& base_nota, const QString& base_confs) + trading_page::place_setprice_order(const QString& base_nota, const QString& base_confs, const QString& cancel_previous) + { + this->set_buy_sell_rpc_busy(true); + this->set_buy_sell_last_rpc_data(QJsonObject{{}}); + + auto& mm2_system = m_system_manager.get_system(); + const auto* market_selector = get_market_pairs_mdl(); + const auto& base = market_selector->get_left_selected_coin(); + const auto& rel = market_selector->get_right_selected_coin(); + t_float_50 rel_min_trade = safe_float(get_orderbook_wrapper()->get_rel_min_taker_vol().toStdString()); + t_float_50 rel_min_volume_f = safe_float(get_min_trade_vol().toStdString()); + + t_setprice_request req{ + .base = base.toStdString(), + .rel = rel.toStdString(), + .price = m_price.toStdString(), + .volume = m_volume.toStdString(), + .cancel_previous = cancel_previous == "true", + .base_nota = base_nota.isEmpty() ? std::optional{std::nullopt} : boost::lexical_cast(base_nota.toStdString()), + .base_confs = base_confs.isEmpty() ? std::optional{std::nullopt} : base_confs.toUInt(), + .min_volume = (rel_min_volume_f <= rel_min_trade) ? std::optional{std::nullopt} : get_min_trade_vol().toStdString() + }; + + nlohmann::json batch; + nlohmann::json setprice_request = mm2::template_request("setprice"); + mm2::to_json(setprice_request, req); + batch.push_back(setprice_request); + setprice_request["userpass"] = "*******"; + + //! Answer + SPDLOG_DEBUG("setprice_request is : {}", setprice_request.dump(4)); + auto answer_functor = [this](const web::http::http_response& resp) + { + std::string body = TO_STD_STR(resp.extract_string(true).get()); + if (resp.status_code() == web::http::status_codes::OK) + { + if (body.find("error") == std::string::npos) + { + auto answers = nlohmann::json::parse(body); + nlohmann::json answer = answers[0]; + this->set_buy_sell_last_rpc_data(nlohmann_json_object_to_qt_json_object(answer)); + auto& cur_mm2_system = m_system_manager.get_system(); + SPDLOG_DEBUG("order successfully placed, refreshing orders and swap"); + cur_mm2_system.batch_fetch_orders_and_swap(); + } + else + { + auto error_json = QJsonObject({{"error_code", -1}, {"error_message", QString::fromStdString(body)}}); + SPDLOG_ERROR("error place_setprice_order: {}", body); + this->set_buy_sell_last_rpc_data(error_json); + } + } + else + { + auto error_json = QJsonObject({{"error_code", resp.status_code()}, {"error_message", QString::fromStdString(body)}}); + this->set_buy_sell_last_rpc_data(error_json); + } + this->set_buy_sell_rpc_busy(false); + this->clear_forms("place_setprice_order"); + }; + + //! Async call + mm2_system.get_mm2_client() + .async_rpc_batch_standalone(batch) + .then(answer_functor) + .then( + [this]([[maybe_unused]] pplx::task previous_task) + { + try + { + previous_task.wait(); + } + catch (const std::exception& e) + { + SPDLOG_ERROR("pplx task error: {}", e.what()); + auto error_json = QJsonObject({{"error_code", web::http::status_codes::InternalError}, {"error_message", e.what()}}); + this->set_buy_sell_last_rpc_data(error_json); + this->set_buy_sell_rpc_busy(false); + this->clear_forms("place_setprice_order"); + } + }); + } + + void + trading_page::place_buy_order(const QString& base_nota, const QString& base_confs, const QString& good_until_canceled) { this->set_buy_sell_rpc_busy(true); this->set_buy_sell_last_rpc_data(QJsonObject{{}}); @@ -178,6 +263,19 @@ namespace atomic_dex .base_confs = base_confs.isEmpty() ? std::optional{std::nullopt} : base_confs.toUInt(), .min_volume = (rel_min_volume_f <= rel_min_trade) ? std::optional{std::nullopt} : get_min_trade_vol().toStdString()}; + if (good_until_canceled == "true") + { + SPDLOG_DEBUG("Good until cancelled order"); + req.order_type = nlohmann::json::object(); + req.order_type.value()["type"] = "GoodTillCancelled"; + } + else + { + SPDLOG_DEBUG("Fill or kill order"); + req.order_type = nlohmann::json::object(); + req.order_type.value()["type"] = "FillOrKill"; + } + if (is_selected_min_max || is_selected_order) { req.min_volume = std::optional{std::nullopt}; @@ -269,7 +367,7 @@ namespace atomic_dex } void - trading_page::place_sell_order(const QString& rel_nota, const QString& rel_confs) + trading_page::place_sell_order(const QString& rel_nota, const QString& rel_confs, const QString& good_until_canceled) { this->set_buy_sell_rpc_busy(true); this->set_buy_sell_last_rpc_data(QJsonObject{{}}); @@ -312,6 +410,18 @@ namespace atomic_dex req.order_type.value()["type"] = "FillOrKill"; req.min_volume = std::optional{std::nullopt}; } + else if (good_until_canceled == "true") + { + SPDLOG_DEBUG("Good until cancelled order"); + req.order_type = nlohmann::json::object(); + req.order_type.value()["type"] = "GoodTillCancelled"; + } + else + { + SPDLOG_DEBUG("Fill or kill order"); + req.order_type = nlohmann::json::object(); + req.order_type.value()["type"] = "FillOrKill"; + } if (is_selected_min_max) { @@ -602,6 +712,23 @@ namespace atomic_dex //! Properties related to trading namespace atomic_dex { + bool + trading_page::get_maker_mode() const + { + return m_maker_mode; + } + + void + trading_page::set_maker_mode(bool market_mode) + { + if (this->m_maker_mode != market_mode) + { + this->m_maker_mode = market_mode; + emit makerModeChanged(); + this->set_market_mode(MarketMode::Sell); + } + } + MarketMode trading_page::get_market_mode() const { diff --git a/src/core/atomicdex/pages/qt.trading.page.hpp b/src/core/atomicdex/pages/qt.trading.page.hpp index ccbbf2c3c3..4aaa14dedf 100644 --- a/src/core/atomicdex/pages/qt.trading.page.hpp +++ b/src/core/atomicdex/pages/qt.trading.page.hpp @@ -46,6 +46,7 @@ namespace atomic_dex // Trading logic Q properties Q_PROPERTY(MarketMode market_mode READ get_market_mode WRITE set_market_mode NOTIFY marketModeChanged) + Q_PROPERTY(bool maker_mode READ get_maker_mode WRITE set_maker_mode NOTIFY makerModeChanged) Q_PROPERTY(TradingError last_trading_error READ get_trading_error WRITE set_trading_error NOTIFY tradingErrorChanged) Q_PROPERTY(TradingMode current_trading_mode READ get_current_trading_mode WRITE set_current_trading_mode NOTIFY tradingModeChanged) Q_PROPERTY(QString price READ get_price WRITE set_price NOTIFY priceChanged) @@ -107,6 +108,7 @@ namespace atomic_dex //! Trading Logic MarketMode m_market_mode{MarketModeGadget::Sell}; + bool m_maker_mode{false}; TradingError m_last_trading_error{TradingErrorGadget::None}; TradingMode m_current_trading_mode{TradingModeGadget::Pro}; SelectedOrderStatus m_selected_order_status{SelectedOrderGadget::None}; @@ -161,8 +163,9 @@ namespace atomic_dex Q_INVOKABLE bool set_pair(bool is_left_side, const QString& changed_ticker); Q_INVOKABLE void set_current_orderbook(const QString& base, const QString& rel); ///< market_selector (called and selecting another coin) - Q_INVOKABLE void place_buy_order(const QString& base_nota = "", const QString& base_confs = ""); - Q_INVOKABLE void place_sell_order(const QString& rel_nota = "", const QString& rel_confs = ""); + Q_INVOKABLE void place_buy_order(const QString& base_nota = "", const QString& base_confs = "", const QString& good_until_canceled = ""); + Q_INVOKABLE void place_sell_order(const QString& rel_nota = "", const QString& rel_confs = "", const QString& good_until_canceled = ""); + Q_INVOKABLE void place_setprice_order(const QString& rel_nota = "", const QString& rel_confs = "", const QString& cancel_previous = ""); Q_INVOKABLE void reset_order(); @@ -178,6 +181,8 @@ namespace atomic_dex void set_buy_sell_rpc_busy(bool status); //! Trading Logic + [[nodiscard]] bool get_maker_mode() const; + void set_maker_mode(bool market_mode); [[nodiscard]] MarketMode get_market_mode() const; void set_market_mode(MarketMode market_mode); [[nodiscard]] TradingError get_trading_error() const; @@ -232,6 +237,7 @@ namespace atomic_dex //! Trading logic void priceChanged(); void volumeChanged(); + void makerModeChanged(); void marketModeChanged(); void maxVolumeChanged(); void tradingErrorChanged(); diff --git a/src/core/atomicdex/pages/widgets/dex/qt.orderbook.cpp b/src/core/atomicdex/pages/widgets/dex/qt.orderbook.cpp index 29a50e8adf..4b702b2116 100644 --- a/src/core/atomicdex/pages/widgets/dex/qt.orderbook.cpp +++ b/src/core/atomicdex/pages/widgets/dex/qt.orderbook.cpp @@ -81,7 +81,7 @@ namespace atomic_dex void qt_orderbook_wrapper::refresh_orderbook_model_data(mm2::orderbook_result_rpc answer) { - SPDLOG_INFO("[qt_orderbook_wrapper::refresh_orderbook_model_data] bids/asks size: {}/{}", answer.bids.size(), answer.asks.size()); + // SPDLOG_INFO("[qt_orderbook_wrapper::refresh_orderbook_model_data] bids/asks size: {}/{}", answer.bids.size(), answer.asks.size()); this->m_asks->refresh_orderbook_model_data(answer.asks); this->m_bids->refresh_orderbook_model_data(answer.bids); const auto data = this->m_system_manager.get_system().get_bestorders_data(); @@ -91,12 +91,12 @@ namespace atomic_dex } else if (m_best_orders->rowCount() == 0) { - SPDLOG_INFO("[qt_orderbook_wrapper::refresh_orderbook_model_data] : reset_best_orders"); + // SPDLOG_INFO("[qt_orderbook_wrapper::refresh_orderbook_model_data] : reset_best_orders"); m_best_orders->reset_orderbook(data, true); } else { - SPDLOG_INFO("[qt_orderbook_wrapper::refresh_orderbook_model_data] : refresh_best_orders"); + // SPDLOG_INFO("[qt_orderbook_wrapper::refresh_orderbook_model_data] : refresh_best_orders"); m_best_orders->refresh_orderbook_model_data(data, true); } this->set_both_taker_vol();