mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-08-26 22:51:14 +00:00
feat(amm): expose supported fee tiers via feeTiers() op
The liquidity form's fee-tier selector was fed from the module's
newPositionContext, which hardcoded an empty list — leaving the selector
blank. Source the tiers from the program instead so the UI can never
drift from what the guest accepts.
Add amm_core::SUPPORTED_FEE_TIERS: the canonical ascending list of raw
bps ([1, 5, 30, 100]), built from the existing FEE_TIER_BPS_* constants.
is_supported_fee_tier's match is left unchanged and the new const is
unused on-chain, so the guest ImageID is unaffected; a drift-guard test
locks the list to the check (every entry accepted, neighbours rejected,
ascending/deduped).
Wire it through the stack:
- FFI: amm_fee_tiers op reading SUPPORTED_FEE_TIERS -> { feeTiers: [...] }
(empty FeeTiersRequest, cbindgen header regenerated).
- Module: LogosList feeTiers() unwrapping the list, like tokenHoldings.
- Backend: QVariantList feeTiers() QtRO slot forwarding to the module.
- QML: LiquidityPage fetches backend.feeTiers() once (wallet-independent)
and injects it into NewPositionForm, which wraps each int into a
{ feeBps } row for the existing delegate. Drop the now-dead feeTiers
key from the flow's loadingContext().
This commit is contained in:
@@ -67,8 +67,13 @@ AmmActionCard {
|
||||
})
|
||||
readonly property var tokens: root.newPositionContext && root.newPositionContext.tokens
|
||||
? root.newPositionContext.tokens : []
|
||||
readonly property var feeTiers: root.newPositionContext && root.newPositionContext.feeTiers
|
||||
? root.newPositionContext.feeTiers : []
|
||||
// Supported fee tiers as raw bps, injected from backend.feeTiers() (amm_core's
|
||||
// SUPPORTED_FEE_TIERS). The selector's delegate wants { feeBps } rows, so wrap
|
||||
// each int; labels are derived locally via feeLabel().
|
||||
property var feeTiers: []
|
||||
readonly property var feeTierModel: (root.feeTiers || []).map(function(bps) {
|
||||
return { "feeBps": Number(bps) }
|
||||
})
|
||||
readonly property var tokenA: root.tokenById(root.selectedTokenAId)
|
||||
readonly property var tokenB: root.tokenById(root.selectedTokenBId)
|
||||
readonly property int decimalsA: 0
|
||||
@@ -407,7 +412,7 @@ AmmActionCard {
|
||||
rowSpacing: 8
|
||||
|
||||
Repeater {
|
||||
model: root.feeTiers
|
||||
model: root.feeTierModel
|
||||
|
||||
Item {
|
||||
id: feeTierOption
|
||||
|
||||
@@ -21,6 +21,11 @@ Item {
|
||||
// account selectors; refetched when the wallet opens.
|
||||
property var holdings: []
|
||||
|
||||
// The AMM's supported fee tiers (backend.feeTiers()) feeding the fee selector.
|
||||
// Program-derived and wallet-independent, so it's fetched once when the backend
|
||||
// becomes available.
|
||||
property var feeTiers: []
|
||||
|
||||
function refreshHoldings() {
|
||||
if (!root.backend || root.runtime === null)
|
||||
return
|
||||
@@ -29,9 +34,17 @@ Item {
|
||||
function(err) { console.warn("tokenHoldings error:", err) })
|
||||
}
|
||||
|
||||
onBackendChanged: root.refreshHoldings()
|
||||
onRuntimeChanged: root.refreshHoldings()
|
||||
Component.onCompleted: root.refreshHoldings()
|
||||
function refreshFeeTiers() {
|
||||
if (!root.backend || root.runtime === null || root.feeTiers.length > 0)
|
||||
return
|
||||
root.runtime.watch(root.backend.feeTiers(),
|
||||
function(list) { root.feeTiers = list },
|
||||
function(err) { console.warn("feeTiers error:", err) })
|
||||
}
|
||||
|
||||
onBackendChanged: { root.refreshHoldings(); root.refreshFeeTiers() }
|
||||
onRuntimeChanged: { root.refreshHoldings(); root.refreshFeeTiers() }
|
||||
Component.onCompleted: { root.refreshHoldings(); root.refreshFeeTiers() }
|
||||
|
||||
Connections {
|
||||
target: root.backend
|
||||
@@ -237,6 +250,7 @@ onBackendChanged: root.refreshHoldings()
|
||||
: qsTr("Choose two tokens and a fee tier for this position.")
|
||||
showRefreshAction: false
|
||||
holdings: root.holdings
|
||||
feeTiers: root.feeTiers
|
||||
newPositionContext: newPositionFlow.newPositionContext
|
||||
flowState: newPositionFlow.viewState
|
||||
|
||||
|
||||
@@ -466,8 +466,7 @@ QtObject {
|
||||
function loadingContext() {
|
||||
return {
|
||||
"status": "loading",
|
||||
"tokens": [],
|
||||
"feeTiers": []
|
||||
"tokens": []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -315,6 +315,14 @@ QVariantList AmmUiBackend::poolList()
|
||||
return readPoolsConfig();
|
||||
}
|
||||
|
||||
QVariantList AmmUiBackend::feeTiers()
|
||||
{
|
||||
// Pure, input-free enumeration of the AMM's supported fee tiers (raw bps) —
|
||||
// no wallet or module connection state involved.
|
||||
return m_logos->amm_module.feeTiers();
|
||||
}
|
||||
|
||||
|
||||
QVariantMap AmmUiBackend::createPool(QVariantMap request)
|
||||
{
|
||||
// Same connected-state submit guard as the swaps — this app's lock is
|
||||
|
||||
@@ -85,6 +85,8 @@ public slots:
|
||||
// Reads the known-pools list from AMM_POOLS_CONFIG (app config JSON, read
|
||||
// here rather than in the amm_module — pool discovery is an app detail).
|
||||
QVariantList poolList() override;
|
||||
// The AMM's supported fee tiers (raw bps) for the fee selector.
|
||||
QVariantList feeTiers() override;
|
||||
|
||||
private:
|
||||
void syncWalletState();
|
||||
|
||||
@@ -144,4 +144,10 @@ class AmmUiBackend
|
||||
// list if AMM_POOLS_CONFIG is unset/unreadable/invalid. This is app config, not
|
||||
// an on-chain read, so it lives in the backend rather than the amm_module.
|
||||
SLOT(QVariantList poolList())
|
||||
|
||||
// The AMM's supported fee tiers as raw basis points, ascending: [1, 5, 30,
|
||||
// 100]. Input-free — sourced from amm_core's SUPPORTED_FEE_TIERS (the set the
|
||||
// guest enforces), so the fee selector never hardcodes or drifts. The QML
|
||||
// formats labels and decides selectability.
|
||||
SLOT(QVariantList feeTiers())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user