mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-19 18:18:38 +00:00
feat(Swap): display the exchange rate approximation in swap
Show the exchange rate approximation in swap. The exchange rate shows when the swap input is valid. It has 3 states: 1. invisibile - when the pay/receive input is empty 2. visible and loading - while fetching the routes. Happens whenever the swap input changes AND the input is valid 3. visbile, with data - once the routes have been fetched
This commit is contained in:
parent
85e12f8761
commit
36872b6f1c
@ -11,7 +11,7 @@ SplitView {
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property var sizesModel: [StatusBaseButton.Size.Tiny, StatusBaseButton.Size.Small, StatusBaseButton.Size.Large]
|
||||
readonly property var sizesModel: [StatusBaseButton.Size.XSmall, StatusBaseButton.Size.Tiny, StatusBaseButton.Size.Small, StatusBaseButton.Size.Large]
|
||||
|
||||
readonly property string effectiveEmoji: ctrlEmojiEnabled.checked ? ctrlEmoji.text : ""
|
||||
readonly property int effectiveTextPosition: ctrlTextPosLeft.checked ? StatusBaseButton.TextPosition.Left
|
||||
@ -30,16 +30,17 @@ SplitView {
|
||||
anchors.centerIn: parent
|
||||
rowSpacing: 10
|
||||
columnSpacing: 10
|
||||
columns: 4
|
||||
columns: 5
|
||||
|
||||
Label { text: "" }
|
||||
Label { text: "XSmall" }
|
||||
Label { text: "Tiny" }
|
||||
Label { text: "Small" }
|
||||
Label { text: "Large" }
|
||||
|
||||
Label {
|
||||
text: "StatusButton"
|
||||
Layout.columnSpan: 4
|
||||
Layout.columnSpan: 5
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
@ -128,7 +129,7 @@ SplitView {
|
||||
|
||||
Label {
|
||||
text: "StatusFlatButton"
|
||||
Layout.columnSpan: 4
|
||||
Layout.columnSpan: 5
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
|
@ -1988,5 +1988,104 @@ Item {
|
||||
|
||||
closeAndVerfyModal()
|
||||
}
|
||||
|
||||
function test_exchange_rate() {
|
||||
// Asset chosen but no pay value set state -------------------------------------------------------------------------------
|
||||
root.swapFormData.fromTokenAmount = "1"
|
||||
root.swapFormData.selectedAccountAddress = "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
|
||||
root.swapFormData.selectedNetworkChainId = 11155111
|
||||
root.swapFormData.fromTokensKey = "ETH"
|
||||
root.swapFormData.toTokenKey = ""
|
||||
|
||||
// Launch popup
|
||||
launchAndVerfyModal()
|
||||
|
||||
const quoteItem = findChild(controlUnderTest, "quoteApproximationRight")
|
||||
verify(!!quoteItem)
|
||||
|
||||
const sellItem = findChild(controlUnderTest, "quoteApproximationLeft")
|
||||
verify(!!sellItem)
|
||||
|
||||
const priceItem = findChild(controlUnderTest, "quoteApproximationPrice")
|
||||
verify(!!priceItem)
|
||||
|
||||
const invertQuoteApproximation = findChild(controlUnderTest, "invertQuoteApproximation")
|
||||
verify(!!invertQuoteApproximation)
|
||||
|
||||
verify(!sellItem.visible)
|
||||
verify(!quoteItem.visible)
|
||||
verify(!priceItem.visible)
|
||||
verify(!invertQuoteApproximation.visible)
|
||||
|
||||
fetchSuggestedRoutesCalled.clear()
|
||||
root.swapFormData.toTokenKey = "STT"
|
||||
|
||||
tryCompare(fetchSuggestedRoutesCalled, "count", 1)
|
||||
tryCompare(sellItem, "visible", true)
|
||||
compare(sellItem.text, "1 ETH ≈ ")
|
||||
verify(quoteItem.visible)
|
||||
verify(quoteItem.loading)
|
||||
verify(!priceItem.visible)
|
||||
verify(!invertQuoteApproximation.visible)
|
||||
|
||||
// emit routes ready
|
||||
let txHasRouteNoApproval = root.dummySwapTransactionRoutes.txHasRouteNoApproval
|
||||
txHasRouteNoApproval.uuid = root.swapAdaptor.uuid
|
||||
txHasRouteNoApproval.amountToReceive = "1000000000000000000" // "1" in STT
|
||||
root.swapStore.suggestedRoutesReady(txHasRouteNoApproval, "", "")
|
||||
|
||||
tryVerify( () => quoteItem.visible)
|
||||
verify(!quoteItem.loading)
|
||||
verify(priceItem.visible)
|
||||
verify(invertQuoteApproximation.visible)
|
||||
|
||||
tryCompare(sellItem, "text", "1 ETH ≈ ")
|
||||
tryCompare(quoteItem, "text", "1 STT ")
|
||||
verify(priceItem.text.startsWith("(1 ")) //Hardcoded to crypto amount input - 1 in our case
|
||||
|
||||
fetchSuggestedRoutesCalled.clear()
|
||||
root.swapFormData.fromTokenAmount = "2"
|
||||
|
||||
// Back to loading states
|
||||
tryCompare(fetchSuggestedRoutesCalled, "count", 1)
|
||||
tryCompare(quoteItem, "visible", true)
|
||||
verify(quoteItem.loading)
|
||||
verify(!priceItem.visible)
|
||||
verify(!invertQuoteApproximation.visible)
|
||||
|
||||
// emit routes ready
|
||||
txHasRouteNoApproval = root.dummySwapTransactionRoutes.txHasRouteNoApproval
|
||||
txHasRouteNoApproval.uuid = root.swapAdaptor.uuid
|
||||
txHasRouteNoApproval.amountToReceive = "4000000000000000000" // "4" in STT
|
||||
root.swapStore.suggestedRoutesReady(txHasRouteNoApproval, "", "")
|
||||
|
||||
tryCompare(sellItem, "text", "1 ETH ≈ ")
|
||||
tryCompare(quoteItem, "text", "2 STT ")
|
||||
verify(priceItem.text.startsWith("(1 ")) //Hardcoded to crypto amount input - 1 in our case
|
||||
verify(invertQuoteApproximation.visible)
|
||||
|
||||
mouseClick(invertQuoteApproximation)
|
||||
tryCompare(sellItem, "text", "1 STT ≈ ")
|
||||
tryCompare(quoteItem, "text", "0.5 ETH ")
|
||||
|
||||
// resetting to default
|
||||
fetchSuggestedRoutesCalled.clear()
|
||||
root.swapFormData.fromTokenAmount = "1"
|
||||
|
||||
// Back to loading states
|
||||
tryCompare(fetchSuggestedRoutesCalled, "count", 1)
|
||||
tryCompare(quoteItem, "visible", true)
|
||||
verify(quoteItem.loading)
|
||||
verify(!priceItem.visible)
|
||||
|
||||
// emit routes ready
|
||||
txHasRouteNoApproval = root.dummySwapTransactionRoutes.txHasRouteNoApproval
|
||||
txHasRouteNoApproval.uuid = root.swapAdaptor.uuid
|
||||
txHasRouteNoApproval.amountToReceive = "1000000000000000000" // "1" in STT
|
||||
root.swapStore.suggestedRoutesReady(txHasRouteNoApproval, "", "")
|
||||
|
||||
tryCompare(sellItem, "text", "1 ETH ≈ ")
|
||||
tryCompare(quoteItem, "text", "1 STT ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ Button {
|
||||
id: root
|
||||
|
||||
enum Size {
|
||||
XSmall,
|
||||
Tiny,
|
||||
Small,
|
||||
Large
|
||||
@ -72,6 +73,8 @@ Button {
|
||||
readonly property bool iconOnly: root.display === AbstractButton.IconOnly || root.text === ""
|
||||
readonly property int iconSize: {
|
||||
switch(root.size) {
|
||||
case StatusBaseButton.Size.XSmall:
|
||||
return 13
|
||||
case StatusBaseButton.Size.Tiny:
|
||||
return 16
|
||||
case StatusBaseButton.Size.Small:
|
||||
@ -94,6 +97,8 @@ Button {
|
||||
}
|
||||
if (root.icon.name) {
|
||||
switch (size) {
|
||||
case StatusBaseButton.Size.XSmall:
|
||||
return 6
|
||||
case StatusBaseButton.Size.Tiny:
|
||||
return Theme.halfPadding
|
||||
case StatusBaseButton.Size.Small:
|
||||
@ -110,6 +115,8 @@ Button {
|
||||
return isRoundIcon ? 8 : spacing
|
||||
}
|
||||
switch (size) {
|
||||
case StatusBaseButton.Size.XSmall:
|
||||
return 3
|
||||
case StatusBaseButton.Size.Tiny:
|
||||
return 5
|
||||
case StatusBaseButton.Size.Small:
|
||||
|
@ -176,7 +176,7 @@ StatusDialog {
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
text: qsTr("On:")
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 13
|
||||
font.pixelSize: Theme.additionalTextSize
|
||||
lineHeight: 38
|
||||
lineHeightMode: Text.FixedHeight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@ -317,6 +317,86 @@ StatusDialog {
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: approximationRow
|
||||
property bool inversedOrder: false
|
||||
readonly property SwapInputPanel leftPanel: inversedOrder ? receivePanel : payPanel
|
||||
readonly property SwapInputPanel rightPanel: inversedOrder ? payPanel : receivePanel
|
||||
|
||||
readonly property string lhsSymbol: leftPanel.tokenKey ?? ""
|
||||
readonly property double lhsAmount: leftPanel.value
|
||||
readonly property string rhsSymbol: rightPanel.tokenKey ?? ""
|
||||
readonly property double rhsAmount: rightPanel.value
|
||||
readonly property int rhsDecimals: rightPanel.rawValueMultiplierIndex
|
||||
readonly property bool amountLoading: receivePanel.mainInputLoading || payPanel.mainInputLoading
|
||||
|
||||
readonly property string quote: !!lhsAmount && !!rhsAmount ? SQUtils.AmountsArithmetic.div(
|
||||
SQUtils.AmountsArithmetic.fromNumber(rhsAmount),
|
||||
SQUtils.AmountsArithmetic.fromNumber(lhsAmount)).toFixed(rhsDecimals) : 1
|
||||
readonly property string price: root.swapAdaptor.currencyStore.getFiatValue(1, lhsSymbol)
|
||||
|
||||
function formatCurrency(amount, symbol) {
|
||||
return root.swapAdaptor.currencyStore.formatCurrencyAmount(amount, symbol,
|
||||
{ roundingMode: LocaleUtils.RoundingMode.Down, stripTrailingZeroes: true })
|
||||
}
|
||||
|
||||
visible: root.swapAdaptor.validSwapProposalReceived || root.swapAdaptor.swapProposalLoading
|
||||
spacing: 0
|
||||
|
||||
onVisibleChanged: inversedOrder = false // restore to default
|
||||
onAmountLoadingChanged: inversedOrder = false // restore to default
|
||||
|
||||
StatusBaseText {
|
||||
objectName: "quoteApproximationLeft"
|
||||
text: "%1 ≈ ".arg(approximationRow.formatCurrency(1, approximationRow.lhsSymbol))
|
||||
|
||||
color: Theme.palette.directColor4
|
||||
font {
|
||||
weight: Font.Medium
|
||||
pixelSize: Theme.additionalTextSize
|
||||
}
|
||||
}
|
||||
|
||||
StatusTextWithLoadingState {
|
||||
Layout.preferredWidth: loading ? 40 : implicitWidth
|
||||
objectName: "quoteApproximationRight"
|
||||
text: "%1 ".arg(approximationRow.formatCurrency(approximationRow.quote, approximationRow.rhsSymbol))
|
||||
|
||||
customColor: Theme.palette.directColor4
|
||||
font {
|
||||
weight: Font.Medium
|
||||
pixelSize: Theme.additionalTextSize
|
||||
}
|
||||
loading: approximationRow.amountLoading
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: quoteApproximation
|
||||
objectName: "quoteApproximationPrice"
|
||||
text: "(%1)".arg(approximationRow.formatCurrency(
|
||||
approximationRow.price,
|
||||
root.swapAdaptor.currencyStore.currentCurrency
|
||||
))
|
||||
|
||||
color: Theme.palette.directColor5
|
||||
font {
|
||||
weight: Font.Medium
|
||||
pixelSize: Theme.additionalTextSize
|
||||
}
|
||||
visible: !approximationRow.amountLoading
|
||||
}
|
||||
|
||||
StatusFlatButton {
|
||||
objectName: "invertQuoteApproximation"
|
||||
icon.name: "swap"
|
||||
size: StatusBaseButton.Size.XSmall
|
||||
onClicked: approximationRow.inversedOrder = !approximationRow.inversedOrder
|
||||
hoverColor: "transparent"
|
||||
textColor: hovered ? Theme.palette.directColor4 : Theme.palette.directColor5
|
||||
visible: !approximationRow.amountLoading
|
||||
}
|
||||
}
|
||||
|
||||
EditSlippagePanel {
|
||||
id: editSlippagePanel
|
||||
objectName: "editSlippagePanel"
|
||||
|
Loading…
x
Reference in New Issue
Block a user