fix(amm): guard resolvePool against stale callbacks; clarify deadline-ms and program-binary docs

This commit is contained in:
Andrea Franz 2026-07-23 14:14:55 +02:00 committed by r4bbit
parent fe41baf210
commit cf92e5d111
3 changed files with 31 additions and 8 deletions

View File

@ -88,9 +88,25 @@ Rectangle {
if (!root.backend || !root.sellToken || !root.buyToken) if (!root.backend || !root.sellToken || !root.buyToken)
return return
// Capture the pair this request is for. resolvePool callbacks can arrive
// out of order: if the user switches tokens while an earlier resolve is
// still in flight, its (stale) callback must NOT overwrite the current
// pair's pool state that would corrupt the preview and the submitted
// min_out. A stale callback also leaves poolLoading alone, since the
// newer in-flight request owns it.
var reqSell = root.sellToken.definitionId
var reqBuy = root.buyToken.definitionId
function isStale() {
return !root.sellToken || !root.buyToken
|| root.sellToken.definitionId !== reqSell
|| root.buyToken.definitionId !== reqBuy
}
root.poolLoading = true root.poolLoading = true
logos.watch(root.backend.resolvePool(root.sellToken.definitionId, root.buyToken.definitionId), logos.watch(root.backend.resolvePool(reqSell, reqBuy),
function (pool) { function (pool) {
if (isStale())
return
root.poolLoading = false root.poolLoading = false
root.poolResolved = true root.poolResolved = true
root.poolExists = !!(pool && pool.exists) root.poolExists = !!(pool && pool.exists)
@ -103,6 +119,8 @@ Rectangle {
root.poolError = (pool && pool.error && pool.error !== "no_pool") ? pool.error : "" root.poolError = (pool && pool.error && pool.error !== "no_pool") ? pool.error : ""
}, },
function (error) { function (error) {
if (isStale())
return
console.warn("resolvePool error:", error) console.warn("resolvePool error:", error)
root.poolLoading = false root.poolLoading = false
root.poolResolved = true root.poolResolved = true

View File

@ -62,11 +62,14 @@ namespace {
// canonical wallet (~/.lee/wallet) used by the wallet UI and other apps. // canonical wallet (~/.lee/wallet) used by the wallet UI and other apps.
const char WALLET_HOME_ENV[] = "LEE_WALLET_HOME_DIR"; const char WALLET_HOME_ENV[] = "LEE_WALLET_HOME_DIR";
// Absolute path to the deployed AMM program's compiled ELF (amm.bin). The // Absolute path to the deployed AMM program's RISC Zero program binary
// app can't safely embed/derive this itself: the wallet module's bundled // (amm.bin — the `ProgramBinary` `.bin` from the docker guest build, decoded
// AMM program may differ from whatever is actually deployed on the target // on the Rust side via `ProgramBinary::decode`; NOT a raw ELF — pointing at
// sequencer, and the program's ELF bytes are what determine its program id // the raw guest ELF yields a different/failed program id). The app can't
// (and therefore every PDA derived from it). See apps/amm/README.md. // safely embed/derive this itself: the wallet module's bundled AMM program
// may differ from whatever is actually deployed on the target sequencer, and
// the binary's bytes are what determine its program id (and therefore every
// PDA derived from it). See apps/amm/README.md.
const char AMM_PROGRAM_BIN_ENV[] = "AMM_PROGRAM_BIN"; const char AMM_PROGRAM_BIN_ENV[] = "AMM_PROGRAM_BIN";
// Absolute path to the JSON token-list config consumed by tokenList() // Absolute path to the JSON token-list config consumed by tokenList()

View File

@ -53,8 +53,10 @@ class AmmUiBackend
SLOT(QVariantMap resolvePool(QString defAHex, QString defBHex)) SLOT(QVariantMap resolvePool(QString defAHex, QString defBHex))
// Submits a real on-chain SwapExactInput transaction against the pool for // Submits a real on-chain SwapExactInput transaction against the pool for
// (defAHex, defBHex). amountInDecimal/minOutDecimal are decimal-string // (defAHex, defBHex). amountInDecimal/minOutDecimal are decimal-string
// u128 amounts in base units; deadlineDecimal is a decimal-string u64 // u128 amounts in base units; deadlineDecimal is a decimal-string u64 unix
// unix timestamp. Returns the tx hash, or an empty string on failure // timestamp in MILLISECONDS (matches amm_core's SwapExactInput deadline —
// passing seconds would expire the swap immediately once deadline handling
// is enforced). Returns the tx hash, or an empty string on failure
// (no pool, unreadable AMM_PROGRAM_BIN, bad inputs, or a failed tx). // (no pool, unreadable AMM_PROGRAM_BIN, bad inputs, or a failed tx).
SLOT(QString swapExactInput(QString defAHex, QString defBHex, QString userInputHoldingHex, QString userOutputHoldingHex, QString amountInDecimal, QString minOutDecimal, QString deadlineDecimal)) SLOT(QString swapExactInput(QString defAHex, QString defBHex, QString userInputHoldingHex, QString userOutputHoldingHex, QString amountInDecimal, QString minOutDecimal, QString deadlineDecimal))
// Reads the token list config at TOKENS_CONFIG (absolute path, JSON array // Reads the token list config at TOKENS_CONFIG (absolute path, JSON array