mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-08-25 06:01:11 +00:00
feat(apps/amm): drive add-liquidity quoting from addLiquidityQuote in the UI
Wire the liquidity view's active-pool preview onto the lean addLiquidityQuote + resolvePool, off the legacy quoteNewPosition. Create-pool quoting stays legacy for now. - Expose addLiquidityQuote as a QtRO slot + backend forwarding. - NewPositionFlow.requestQuoteNow routes on resolvePool.exists (existence, like the swap card — no quote-derived poolStatus): active -> addLiquidityQuote, assembled into the shape the form consumes (reserves/fee from resolvePool, minimumLpRaw from the quote); missing -> legacy quoteNewPosition. - Drop the obsolete quoteHash gate from canConfirm (the lean quotes are stateless).
This commit is contained in:
@@ -106,7 +106,6 @@ AmmActionCard {
|
||||
readonly property bool canConfirm: root.quotePayload.status === "ok"
|
||||
&& root.quotePayload.canSubmit === true
|
||||
&& root.quoteMatchesPair()
|
||||
&& String(root.quotePayload.quoteHash || "").length > 0
|
||||
&& root.holdingsReady
|
||||
&& root.hasDepositAmounts
|
||||
&& !root.contextLoading
|
||||
|
||||
@@ -164,6 +164,73 @@ QtObject {
|
||||
return
|
||||
}
|
||||
|
||||
// Route on pool existence (read the pool account), like the swap card. resolvePool
|
||||
// returns the reserves oriented to our requested token order (reserveA is tokenAId's).
|
||||
root.runtime.watch(root.backend.resolvePool(built.request.tokenAId, built.request.tokenBId),
|
||||
function(pool) {
|
||||
if (serial !== root.quoteSerial)
|
||||
return
|
||||
if (pool && pool.exists) {
|
||||
root.requestAddQuote(serial, built, pool)
|
||||
return
|
||||
}
|
||||
// resolvePool returns exists:false for BOTH the normal "no pool yet" case and
|
||||
// hard failures (no_program_bin, amm_not_initialized, bad_config). Only the
|
||||
// former — an empty error or no_pool — is a create-pool signal; surface any other
|
||||
// pool.error as a quote error instead of masking it as a create quote (which
|
||||
// would hide the backend failure and enable the wrong flow).
|
||||
var poolError = pool ? String(pool.error || "") : ""
|
||||
if (poolError.length === 0 || poolError === "no_pool") {
|
||||
root.requestCreateQuote(serial, built)
|
||||
} else {
|
||||
root.quoteLoading = false
|
||||
root.quoteStale = false
|
||||
root.quoteErrorCode = ""
|
||||
root.newPositionQuote = root.quoteError(poolError)
|
||||
}
|
||||
},
|
||||
function(error) {
|
||||
if (serial !== root.quoteSerial)
|
||||
return
|
||||
root.quoteLoading = false
|
||||
root.quoteStale = true
|
||||
root.quoteErrorCode = "backend_error"
|
||||
})
|
||||
}
|
||||
|
||||
// Add-liquidity preview via the lean addLiquidityQuote; reserves + fee come from the
|
||||
// resolvePool read. The result is assembled into the shape the form already consumes.
|
||||
function requestAddQuote(serial, built, pool) {
|
||||
root.runtime.watch(root.backend.addLiquidityQuote({
|
||||
"tokenAId": built.request.tokenAId,
|
||||
"tokenBId": built.request.tokenBId,
|
||||
"maxAmountARaw": built.request.maxAmountARaw,
|
||||
"maxAmountBRaw": built.request.maxAmountBRaw,
|
||||
"slippageBps": built.request.slippageBps
|
||||
}),
|
||||
function(quote) {
|
||||
if (serial !== root.quoteSerial)
|
||||
return
|
||||
root.quoteLoading = false
|
||||
root.quoteStale = false
|
||||
root.quoteErrorCode = ""
|
||||
if (quote && quote.status === "ok")
|
||||
root.newPositionQuote = root.assembleAddQuote(built, pool, quote)
|
||||
else
|
||||
root.newPositionQuote = root.quoteError((quote && quote.error) || "backend_error")
|
||||
},
|
||||
function(error) {
|
||||
if (serial !== root.quoteSerial)
|
||||
return
|
||||
root.quoteLoading = false
|
||||
root.quoteStale = true
|
||||
root.quoteErrorCode = "backend_error"
|
||||
})
|
||||
}
|
||||
|
||||
// Create-pool preview still on the legacy quoteNewPosition — migrated to createPoolQuote
|
||||
// (the create counterpart of addLiquidityQuote) in a later step.
|
||||
function requestCreateQuote(serial, built) {
|
||||
root.runtime.watch(root.backend.quoteNewPosition(built.request),
|
||||
function(quote) {
|
||||
if (serial !== root.quoteSerial)
|
||||
@@ -185,6 +252,31 @@ QtObject {
|
||||
})
|
||||
}
|
||||
|
||||
// Maps addLiquidityQuote + the pool read into the quote shape NewPositionForm reads for an
|
||||
// active pool. Amounts/reserves are in the request's (canonical) order, matching the form's
|
||||
// displayIsCanonical mapping; minimumLpRaw is the slippage floor the module computed.
|
||||
function assembleAddQuote(built, pool, quote) {
|
||||
return {
|
||||
"status": "ok",
|
||||
"poolStatus": "active_pool",
|
||||
"canSubmit": true,
|
||||
"tokenAId": built.request.tokenAId,
|
||||
"tokenBId": built.request.tokenBId,
|
||||
"actualAmountARaw": String(quote.amountARaw || "0"),
|
||||
"actualAmountBRaw": String(quote.amountBRaw || "0"),
|
||||
"expectedLpRaw": String(quote.expectedLpRaw || "0"),
|
||||
"minimumLpRaw": String(quote.minimumLpRaw || "0"),
|
||||
"reserveARaw": String(pool.reserveA || "0"),
|
||||
"reserveBRaw": String(pool.reserveB || "0"),
|
||||
"poolFeeBps": pool.feeBps,
|
||||
"requiresFreshLp": true,
|
||||
"initialPriceRealRaw": String(quote.priceRaw || "0"),
|
||||
"errors": [],
|
||||
"warnings": [],
|
||||
"accountPreview": []
|
||||
}
|
||||
}
|
||||
|
||||
function confirm(snapshot) {
|
||||
if (root.submitting)
|
||||
return
|
||||
@@ -199,7 +291,8 @@ QtObject {
|
||||
// Route by pool state: creation (initialPriceRealRaw is set only on the missing-pool
|
||||
// path) goes through createPool; the active-pool branch through addLiquidity. Both
|
||||
// mint a fresh LP holding then submit via the lean module ops (hex ids,
|
||||
// caller-provided accounts). Quoting stays on the legacy quoteNewPosition for now.
|
||||
// caller-provided accounts). Add quoting is now on addLiquidityQuote; create quoting
|
||||
// stays on the legacy quoteNewPosition until createPoolQuote is wired.
|
||||
if (snapshot.request.initialPriceRealRaw !== undefined)
|
||||
root.createPool(snapshot)
|
||||
else
|
||||
@@ -259,9 +352,9 @@ QtObject {
|
||||
}
|
||||
|
||||
// Add liquidity to an existing pool via the new addLiquidity op. Like createPool a fresh
|
||||
// LP holding receives the minted LP, so create one then submit. The submit is priced off
|
||||
// the legacy quote's maxAmounts + minimumLpRaw (quoting stays legacy for now; the
|
||||
// module's addLiquidityQuote is built but unwired). No confirmation poll yet.
|
||||
// LP holding receives the minted LP, so create one then submit. The submit reuses the
|
||||
// addLiquidityQuote result (maxAmounts + minimumLpRaw) carried on the snapshot. No
|
||||
// confirmation poll yet.
|
||||
function addLiquidity(snapshot) {
|
||||
root.runtime.watch(root.backend.createAccountPublic(),
|
||||
function(lpId) {
|
||||
|
||||
@@ -237,6 +237,13 @@ QVariantMap AmmUiBackend::liquidityQuote(QVariantMap request)
|
||||
return m_logos->amm_module.liquidityQuote(request);
|
||||
}
|
||||
|
||||
QVariantMap AmmUiBackend::addLiquidityQuote(QVariantMap request)
|
||||
{
|
||||
// Read-only add-liquidity preview — no wallet guard. The module reads the pool and
|
||||
// ratio-matches the deposit server-side from the two max amounts.
|
||||
return m_logos->amm_module.addLiquidityQuote(request);
|
||||
}
|
||||
|
||||
QVariantList AmmUiBackend::tokenHoldings()
|
||||
{
|
||||
// Read-only list of the wallet's token holdings for the account selector. Gated
|
||||
|
||||
@@ -75,6 +75,8 @@ public slots:
|
||||
// createAccountPublic() — so createPool forwards to the module and creates no wallet
|
||||
// accounts here.
|
||||
QVariantMap liquidityQuote(QVariantMap request) override;
|
||||
// Read-only add-liquidity preview (forwards to the module).
|
||||
QVariantMap addLiquidityQuote(QVariantMap request) override;
|
||||
QVariantMap createPool(QVariantMap request) override;
|
||||
// Add-liquidity submit. Forwards to the module; the flow supplies a fresh LP
|
||||
// holding in the request (the backend creates no wallet accounts here).
|
||||
|
||||
@@ -102,6 +102,15 @@ class AmmUiBackend
|
||||
// Read-only, no submission (the fee is not needed — it isn't part of the pool
|
||||
// PDA nor the pricing).
|
||||
SLOT(QVariantMap liquidityQuote(QVariantMap request))
|
||||
// Server-side add-liquidity preview from the two max deposit amounts. `request`
|
||||
// carries { tokenAId, tokenBId, maxAmountARaw, maxAmountBRaw, slippageBps } (ids hex or
|
||||
// base58). Reads the pool and returns { status:"ok", error:"", amountARaw, amountBRaw
|
||||
// (the actual ratio-matched deposits, display order), expectedLpRaw, minimumLpRaw (the
|
||||
// slippage floor on the LP minted — the submit's min_amount_liquidity), priceRaw }. On
|
||||
// failure { status:"error", error:<code> } — no_pool, pair_mismatch, invalid_token_id,
|
||||
// invalid_slippage, amount_too_low, minimum_lp_zero, bad_amount, backend_error.
|
||||
// Read-only, no submission.
|
||||
SLOT(QVariantMap addLiquidityQuote(QVariantMap request))
|
||||
// Submits a NewDefinition transaction creating the pool for the request's pair.
|
||||
// `request` carries { tokenAId, tokenBId, holdingAId, holdingBId, lpHoldingId,
|
||||
// amountARaw, amountBRaw, feeBps, deadlineMs } (ids hex or base58; amounts/deadline
|
||||
|
||||
Reference in New Issue
Block a user