mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-07-20 05:50:32 +00:00
fix(amm): apply slippage to exact-output input
This commit is contained in:
parent
a94731881f
commit
0e6a38742d
@ -52,10 +52,16 @@ Rectangle {
|
|||||||
|
|
||||||
readonly property real feeAmount: swapState.feeAmount(parsedSellAmount)
|
readonly property real feeAmount: swapState.feeAmount(parsedSellAmount)
|
||||||
readonly property real minReceivedAmount: swapState.minReceived(parsedBuyAmount, slippageTolerancePercent)
|
readonly property real minReceivedAmount: swapState.minReceived(parsedBuyAmount, slippageTolerancePercent)
|
||||||
|
readonly property real maxSentAmount: swapState.maxSent(parsedSellAmount, slippageTolerancePercent)
|
||||||
readonly property real priceImpactPercent: swapState.priceImpactPercent(parsedSellAmount, parsedBuyAmount, sellReserve, buyReserve)
|
readonly property real priceImpactPercent: swapState.priceImpactPercent(parsedSellAmount, parsedBuyAmount, sellReserve, buyReserve)
|
||||||
|
|
||||||
readonly property string swapMode: editingSide === "buy" ? "swap-exact-output" : "swap-exact-input"
|
readonly property bool exactOutput: editingSide === "buy"
|
||||||
readonly property string swapModeText: editingSide === "buy" ? qsTr("Exact output") : qsTr("Exact input")
|
readonly property string swapMode: exactOutput ? "swap-exact-output" : "swap-exact-input"
|
||||||
|
readonly property string swapModeText: exactOutput ? qsTr("Exact output") : qsTr("Exact input")
|
||||||
|
readonly property string limitLabel: exactOutput ? qsTr("Max sent") : qsTr("Min received")
|
||||||
|
readonly property string limitText: exactOutput
|
||||||
|
? swapState.formatTokenAmount(maxSentAmount, sellToken ? sellToken.symbol : "")
|
||||||
|
: swapState.formatTokenAmount(minReceivedAmount, buyToken ? buyToken.symbol : "")
|
||||||
|
|
||||||
readonly property bool hasAmount: editingSide === "sell" ? parsedSellInput > 0 : parsedBuyInput > 0
|
readonly property bool hasAmount: editingSide === "sell" ? parsedSellInput > 0 : parsedBuyInput > 0
|
||||||
readonly property bool tokensSelected: sellToken !== null && buyToken !== null
|
readonly property bool tokensSelected: sellToken !== null && buyToken !== null
|
||||||
@ -102,7 +108,8 @@ Rectangle {
|
|||||||
"buyToken": buyToken ? buyToken.symbol : "",
|
"buyToken": buyToken ? buyToken.symbol : "",
|
||||||
"sellAmount": formatAmountValue(parsedSellAmount),
|
"sellAmount": formatAmountValue(parsedSellAmount),
|
||||||
"buyAmount": formatAmountValue(parsedBuyAmount),
|
"buyAmount": formatAmountValue(parsedBuyAmount),
|
||||||
"minReceived": formatAmountValue(minReceivedAmount),
|
"minReceived": exactOutput ? "" : formatAmountValue(minReceivedAmount),
|
||||||
|
"maxSent": exactOutput ? formatAmountValue(maxSentAmount) : "",
|
||||||
"feeAmount": swapState.formatTokenAmount(feeAmount, sellToken ? sellToken.symbol : ""),
|
"feeAmount": swapState.formatTokenAmount(feeAmount, sellToken ? sellToken.symbol : ""),
|
||||||
"priceImpactPercent": swapState.formatPercent(priceImpactPercent),
|
"priceImpactPercent": swapState.formatPercent(priceImpactPercent),
|
||||||
"priceImpactPercentValue": priceImpactPercent,
|
"priceImpactPercentValue": priceImpactPercent,
|
||||||
@ -211,7 +218,8 @@ Rectangle {
|
|||||||
feeText: swapState.formatTokenAmount(root.feeAmount, root.sellToken ? root.sellToken.symbol : "")
|
feeText: swapState.formatTokenAmount(root.feeAmount, root.sellToken ? root.sellToken.symbol : "")
|
||||||
priceImpactText: swapState.formatPercent(root.priceImpactPercent)
|
priceImpactText: swapState.formatPercent(root.priceImpactPercent)
|
||||||
priceImpactPercent: root.priceImpactPercent
|
priceImpactPercent: root.priceImpactPercent
|
||||||
minReceivedText: swapState.formatTokenAmount(root.minReceivedAmount, root.buyToken ? root.buyToken.symbol : "")
|
limitLabel: root.limitLabel
|
||||||
|
limitText: root.limitText
|
||||||
}
|
}
|
||||||
|
|
||||||
SlippageToleranceControl {
|
SlippageToleranceControl {
|
||||||
|
|||||||
@ -22,16 +22,22 @@ ColumnLayout {
|
|||||||
spacing: 4
|
spacing: 4
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
objectName: "swapPayLabel"
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("You pay")
|
text: root.snapshot.swapMode === "swap-exact-output"
|
||||||
|
? qsTr("You pay at most")
|
||||||
|
: qsTr("You pay")
|
||||||
color: root.theme.colors.textSecondary
|
color: root.theme.colors.textSecondary
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
objectName: "swapPayAmount"
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("%1 %2")
|
text: qsTr("%1 %2")
|
||||||
.arg(root.snapshot.sellAmount || "")
|
.arg(root.snapshot.swapMode === "swap-exact-output"
|
||||||
|
? root.snapshot.maxSent || ""
|
||||||
|
: root.snapshot.sellAmount || "")
|
||||||
.arg(root.snapshot.sellToken || "")
|
.arg(root.snapshot.sellToken || "")
|
||||||
color: root.theme.colors.textPrimary
|
color: root.theme.colors.textPrimary
|
||||||
font.bold: true
|
font.bold: true
|
||||||
@ -54,16 +60,22 @@ ColumnLayout {
|
|||||||
spacing: 4
|
spacing: 4
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
objectName: "swapReceiveLabel"
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("You receive at least")
|
text: root.snapshot.swapMode === "swap-exact-output"
|
||||||
|
? qsTr("You receive")
|
||||||
|
: qsTr("You receive at least")
|
||||||
color: root.theme.colors.textSecondary
|
color: root.theme.colors.textSecondary
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
objectName: "swapReceiveAmount"
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("%1 %2")
|
text: qsTr("%1 %2")
|
||||||
.arg(root.snapshot.minReceived || "")
|
.arg(root.snapshot.swapMode === "swap-exact-output"
|
||||||
|
? root.snapshot.buyAmount || ""
|
||||||
|
: root.snapshot.minReceived || "")
|
||||||
.arg(root.snapshot.buyToken || "")
|
.arg(root.snapshot.buyToken || "")
|
||||||
color: root.theme.colors.textPrimary
|
color: root.theme.colors.textPrimary
|
||||||
font.bold: true
|
font.bold: true
|
||||||
@ -81,8 +93,11 @@ ColumnLayout {
|
|||||||
priceImpactText: root.snapshot.priceImpactPercent || ""
|
priceImpactText: root.snapshot.priceImpactPercent || ""
|
||||||
priceImpactPercent: Number(root.snapshot.priceImpactPercentValue) || 0
|
priceImpactPercent: Number(root.snapshot.priceImpactPercentValue) || 0
|
||||||
slippageText: root.snapshot.slippageTolerance || ""
|
slippageText: root.snapshot.slippageTolerance || ""
|
||||||
minReceivedText: qsTr("%1 %2")
|
limitLabel: root.snapshot.swapMode === "swap-exact-output"
|
||||||
.arg(root.snapshot.minReceived || "")
|
? qsTr("Max sent")
|
||||||
.arg(root.snapshot.buyToken || "")
|
: qsTr("Min received")
|
||||||
|
limitText: root.snapshot.swapMode === "swap-exact-output"
|
||||||
|
? qsTr("%1 %2").arg(root.snapshot.maxSent || "").arg(root.snapshot.sellToken || "")
|
||||||
|
: qsTr("%1 %2").arg(root.snapshot.minReceived || "").arg(root.snapshot.buyToken || "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,8 @@ Item {
|
|||||||
property string priceImpactText: ""
|
property string priceImpactText: ""
|
||||||
property real priceImpactPercent: 0
|
property real priceImpactPercent: 0
|
||||||
property string slippageText: ""
|
property string slippageText: ""
|
||||||
property string minReceivedText: ""
|
property string limitLabel: qsTr("Min received")
|
||||||
|
property string limitText: ""
|
||||||
|
|
||||||
readonly property color priceImpactColor: {
|
readonly property color priceImpactColor: {
|
||||||
if (root.priceImpactPercent > 5) return "#F08A76";
|
if (root.priceImpactPercent > 5) return "#F08A76";
|
||||||
@ -126,20 +127,22 @@ Item {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
objectName: "swapLimitLabel"
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
color: root.theme.colors.textSecondary
|
color: root.theme.colors.textSecondary
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
text: qsTr("Min received")
|
text: root.limitLabel
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
objectName: "swapLimitValue"
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
color: root.theme.colors.textPrimary
|
color: root.theme.colors.textPrimary
|
||||||
font.bold: true
|
font.bold: true
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
text: root.minReceivedText
|
text: root.limitText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,5 +53,59 @@ Item {
|
|||||||
tryCompare(dialog, "opened", false)
|
tryCompare(dialog, "opened", false)
|
||||||
compare(card.sellInput, "1")
|
compare(card.sellInput, "1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_exactOutputUsesMaximumInputLimit() {
|
||||||
|
const page = createTemporaryObject(pageComponent, root)
|
||||||
|
verify(page)
|
||||||
|
|
||||||
|
const card = findChild(page, "swapCard")
|
||||||
|
const dialog = findChild(page, "swapPreviewDialog")
|
||||||
|
verify(card)
|
||||||
|
verify(dialog)
|
||||||
|
|
||||||
|
card.setToken("sell", page.tokens[0])
|
||||||
|
card.setToken("buy", page.tokens[1])
|
||||||
|
card.slippageTolerancePercent = 10
|
||||||
|
card.buyInput = "1000"
|
||||||
|
card.editingSide = "buy"
|
||||||
|
tryCompare(card, "canSubmit", true)
|
||||||
|
|
||||||
|
const snapshot = card.buildSnapshot()
|
||||||
|
compare(snapshot.swapMode, "swap-exact-output")
|
||||||
|
compare(snapshot.buyAmount, "1000.00")
|
||||||
|
compare(snapshot.minReceived, "")
|
||||||
|
verify(snapshot.maxSent.length > 0)
|
||||||
|
verify(Number(snapshot.maxSent) > Number(snapshot.sellAmount))
|
||||||
|
|
||||||
|
dialog.openWithSnapshot(snapshot)
|
||||||
|
tryCompare(dialog, "opened", true)
|
||||||
|
tryCompare(findChild(dialog, "swapPayLabel"), "text", "You pay at most")
|
||||||
|
compare(findChild(dialog, "swapPayAmount").text, snapshot.maxSent + " " + snapshot.sellToken)
|
||||||
|
compare(findChild(dialog, "swapReceiveLabel").text, "You receive")
|
||||||
|
compare(findChild(dialog, "swapReceiveAmount").text, snapshot.buyAmount + " " + snapshot.buyToken)
|
||||||
|
compare(findChild(dialog, "swapLimitLabel").text, "Max sent")
|
||||||
|
compare(findChild(dialog, "swapLimitValue").text, snapshot.maxSent + " " + snapshot.sellToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_exactInputUsesMinimumOutputLimit() {
|
||||||
|
const page = createTemporaryObject(pageComponent, root)
|
||||||
|
verify(page)
|
||||||
|
|
||||||
|
const card = findChild(page, "swapCard")
|
||||||
|
verify(card)
|
||||||
|
card.setToken("sell", page.tokens[0])
|
||||||
|
card.setToken("buy", page.tokens[1])
|
||||||
|
card.slippageTolerancePercent = 10
|
||||||
|
card.sellInput = "1"
|
||||||
|
card.editingSide = "sell"
|
||||||
|
tryCompare(card, "canSubmit", true)
|
||||||
|
|
||||||
|
const snapshot = card.buildSnapshot()
|
||||||
|
compare(snapshot.swapMode, "swap-exact-input")
|
||||||
|
compare(snapshot.sellAmount, "1.00")
|
||||||
|
compare(snapshot.maxSent, "")
|
||||||
|
verify(snapshot.minReceived.length > 0)
|
||||||
|
verify(Number(snapshot.minReceived) < Number(snapshot.buyAmount))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user