mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-08-25 06:01:11 +00:00
fix(apps/amm): disable the already-selected token in the swap token picker
The token selector let you pick the same token on both sides of a swap.
That drove resolvePool into amm_client_pool_pda with def_a == def_b, which
hits `panic!("Definitions match")` in amm_core (a pool needs two distinct
tokens). Because that panic crosses the `#[no_mangle]` FFI boundary — which
can't unwind — it aborts, taking the whole UI process down.
Guard it at the source: the picker now disables (dims, no hover/click, tags
"Selected") whichever token is already chosen on the opposite side, so the
two sides can never match.
- TokenListItem: add a `disabled` state (opacity, inert MouseArea, tag)
- TokenSelectorModal: add `disabledDefinitionId`; gate both the popular-token
pills and the list rows on it
- SwapPage: on open, set it to the opposite side's selected token
This commit is contained in:
@@ -9,15 +9,20 @@ Item {
|
||||
property string tokenName: ""
|
||||
property string tokenSymbol: ""
|
||||
property string tokenDefinitionId: ""
|
||||
// When true, the token is already selected on the other side of the swap,
|
||||
// so it's shown dimmed and can't be picked (a pool needs two distinct
|
||||
// tokens — picking the same one both sides panics amm_core's pool PDA).
|
||||
property bool disabled: false
|
||||
|
||||
signal clicked()
|
||||
|
||||
implicitHeight: 56
|
||||
opacity: root.disabled ? 0.35 : 1.0
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 12
|
||||
color: hoverArea.containsMouse ? theme.colors.panelBg : "transparent"
|
||||
color: (!root.disabled && hoverArea.containsMouse) ? theme.colors.panelBg : "transparent"
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
|
||||
RowLayout {
|
||||
@@ -62,13 +67,21 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
visible: root.disabled
|
||||
text: qsTr("Selected")
|
||||
color: theme.colors.textSecondary
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: hoverArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: !root.disabled
|
||||
hoverEnabled: !root.disabled
|
||||
cursorShape: root.disabled ? Qt.ArrowCursor : Qt.PointingHandCursor
|
||||
onClicked: root.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ Item {
|
||||
property var theme
|
||||
property var tokens: []
|
||||
property string searchText: ""
|
||||
// definitionId of the token already chosen on the other side of the swap.
|
||||
// That token is shown disabled here so the two sides can never match (a
|
||||
// same-token pool has no PDA — it panics amm_core).
|
||||
property string disabledDefinitionId: ""
|
||||
|
||||
signal tokenSelected(var token)
|
||||
|
||||
@@ -118,12 +122,17 @@ Item {
|
||||
Repeater {
|
||||
model: root.tokens.slice(0, 5)
|
||||
delegate: Rectangle {
|
||||
id: pill
|
||||
readonly property bool isDisabled:
|
||||
root.disabledDefinitionId !== "" &&
|
||||
modelData.definitionId === root.disabledDefinitionId
|
||||
height: 40
|
||||
radius: 20
|
||||
color: pillHover.containsMouse ? theme.colors.panelHoverBg : theme.colors.panelBg
|
||||
color: (!pill.isDisabled && pillHover.containsMouse) ? theme.colors.panelHoverBg : theme.colors.panelBg
|
||||
border.color: theme.colors.border
|
||||
border.width: 1
|
||||
width: pillRow.implicitWidth + 24
|
||||
opacity: pill.isDisabled ? 0.35 : 1.0
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
RowLayout {
|
||||
id: pillRow
|
||||
@@ -139,8 +148,9 @@ Item {
|
||||
MouseArea {
|
||||
id: pillHover
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: !pill.isDisabled
|
||||
hoverEnabled: !pill.isDisabled
|
||||
cursorShape: pill.isDisabled ? Qt.ArrowCursor : Qt.PointingHandCursor
|
||||
onClicked: root.tokenSelected(modelData)
|
||||
}
|
||||
}
|
||||
@@ -170,6 +180,8 @@ Item {
|
||||
tokenName: modelData.name
|
||||
tokenSymbol: modelData.symbol
|
||||
tokenDefinitionId: modelData.definitionId
|
||||
disabled: root.disabledDefinitionId !== "" &&
|
||||
modelData.definitionId === root.disabledDefinitionId
|
||||
onClicked: root.tokenSelected(modelData)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +144,10 @@ Item {
|
||||
|
||||
onRequestTokenSelect: function(side) {
|
||||
tokenModal.targetSide = side
|
||||
// Disable the token already picked on the opposite side so the
|
||||
// two sides can't match (a same-token pool panics amm_core).
|
||||
var other = side === "sell" ? swapCard.buyToken : swapCard.sellToken
|
||||
tokenModal.disabledDefinitionId = other ? other.definitionId : ""
|
||||
tokenModal.open()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user