mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-07-25 08:13:12 +00:00
fix(amm): order swap holdings/reserves by pool token order; accept base58 ids
This commit is contained in:
parent
906aa65b4f
commit
caf53d0409
@ -24,15 +24,16 @@ Rectangle {
|
||||
property real slippageTolerancePercent: 0.5
|
||||
|
||||
// ── Pool resolution (backend.resolvePool) ───────────────────────────────
|
||||
// sellToken is always passed as defA and buyToken as defB, so reserveA
|
||||
// always corresponds to sellToken and reserveB to buyToken — no separate
|
||||
// "direction" bookkeeping is needed (unlike a generic A/B picker): the
|
||||
// sell/buy assignment *is* the direction.
|
||||
// A pool's PoolDefinition stores def_a/def_b in the pool CREATOR's order
|
||||
// (from NewDefinition), not sorted, and not necessarily in (sellToken,
|
||||
// buyToken) order. reserveA/reserveB mirror that same canonical order, so
|
||||
// they must be mapped to sell/buy via poolDefAHex below — never assumed.
|
||||
property bool poolLoading: false
|
||||
property bool poolResolved: false
|
||||
property bool poolExists: false
|
||||
property string poolReserveA: "0"
|
||||
property string poolReserveB: "0"
|
||||
property string poolDefAHex: ""
|
||||
property int poolFeeBps: 30
|
||||
property string poolError: ""
|
||||
|
||||
@ -95,6 +96,7 @@ Rectangle {
|
||||
root.poolExists = !!(pool && pool.exists)
|
||||
root.poolReserveA = (pool && pool.reserveA) || "0"
|
||||
root.poolReserveB = (pool && pool.reserveB) || "0"
|
||||
root.poolDefAHex = (pool && pool.defAHex) || ""
|
||||
root.poolFeeBps = (pool && pool.feeBps) || 30
|
||||
root.poolError = ""
|
||||
},
|
||||
@ -111,8 +113,12 @@ Rectangle {
|
||||
// drive the *estimate* (expected output / min received / price impact),
|
||||
// never the actual swap amount — the sell amount sent to the backend is
|
||||
// the user's raw input text, passed through verbatim.
|
||||
readonly property real sellReserveNum: Number(root.poolReserveA) || 0
|
||||
readonly property real buyReserveNum: Number(root.poolReserveB) || 0
|
||||
// The pool's reserveA/reserveB follow the pool's canonical def_a/def_b
|
||||
// order (see poolDefAHex above), which may or may not match sell/buy —
|
||||
// map them explicitly rather than assuming reserveA == sell.
|
||||
readonly property bool sellIsPoolA: !!root.sellToken && root.sellToken.definitionId === root.poolDefAHex
|
||||
readonly property real sellReserveNum: Number(sellIsPoolA ? root.poolReserveA : root.poolReserveB) || 0
|
||||
readonly property real buyReserveNum: Number(sellIsPoolA ? root.poolReserveB : root.poolReserveA) || 0
|
||||
|
||||
readonly property real parsedSellInput: {
|
||||
var amt = parseFloat(sellInput)
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#include "AmmUiBackend.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
@ -484,6 +487,26 @@ void AmmUiBackend::copyToClipboard(QString text)
|
||||
QGuiApplication::clipboard()->setText(text);
|
||||
}
|
||||
|
||||
QString AmmUiBackend::normalizeAccountId(const QString& id)
|
||||
{
|
||||
const QString t = id.trimmed();
|
||||
// Already 64 hex chars?
|
||||
if (t.size() == 64) {
|
||||
bool allHex = true;
|
||||
for (const QChar c : t) {
|
||||
if (!std::isxdigit(static_cast<unsigned char>(c.toLatin1()))) {
|
||||
allHex = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allHex)
|
||||
return t.toLower();
|
||||
}
|
||||
// Try base58 -> hex via the wallet module.
|
||||
const QString hex = m_logos->logos_execution_zone.account_id_from_base58(t);
|
||||
return hex.toLower(); // account_id_from_base58 returns "" on failure
|
||||
}
|
||||
|
||||
QVariantMap AmmUiBackend::resolvePool(QString defAHex, QString defBHex)
|
||||
{
|
||||
QVariantMap out;
|
||||
@ -574,6 +597,8 @@ QVariantMap AmmUiBackend::resolvePool(QString defAHex, QString defBHex)
|
||||
out[QStringLiteral("exists")] = true;
|
||||
out[QStringLiteral("configHex")] = configHex;
|
||||
out[QStringLiteral("poolIdHex")] = poolHex;
|
||||
out[QStringLiteral("defAHex")] = bytes32ToHex(poolView.def_a);
|
||||
out[QStringLiteral("defBHex")] = bytes32ToHex(poolView.def_b);
|
||||
out[QStringLiteral("vaultAHex")] = bytes32ToHex(poolView.vault_a);
|
||||
out[QStringLiteral("vaultBHex")] = bytes32ToHex(poolView.vault_b);
|
||||
out[QStringLiteral("currentTickHex")] = bytes32ToHex(currentTickPda);
|
||||
@ -713,11 +738,26 @@ QVariantList AmmUiBackend::tokenList()
|
||||
continue;
|
||||
}
|
||||
const QJsonObject obj = entry.toObject();
|
||||
const QString symbol = obj.value(QStringLiteral("symbol")).toString();
|
||||
|
||||
// TOKENS_CONFIG entries may give definitionId/holding as hex or
|
||||
// base58 (the wallet/runbook display base58) — normalize both to
|
||||
// lowercase hex here so every downstream consumer (resolvePool,
|
||||
// swapExactInput, and the QML's hex comparisons) can assume hex.
|
||||
const QString definitionId =
|
||||
normalizeAccountId(obj.value(QStringLiteral("definitionId")).toString());
|
||||
const QString holding = normalizeAccountId(obj.value(QStringLiteral("holding")).toString());
|
||||
if (definitionId.isEmpty() || holding.isEmpty()) {
|
||||
qWarning() << "AmmUiBackend::tokenList: skipping token" << symbol
|
||||
<< "— cannot normalize definitionId/holding to hex (not valid hex or base58)";
|
||||
continue;
|
||||
}
|
||||
|
||||
QVariantMap token;
|
||||
token[QStringLiteral("symbol")] = obj.value(QStringLiteral("symbol")).toString();
|
||||
token[QStringLiteral("symbol")] = symbol;
|
||||
token[QStringLiteral("name")] = obj.value(QStringLiteral("name")).toString();
|
||||
token[QStringLiteral("definitionId")] = obj.value(QStringLiteral("definitionId")).toString();
|
||||
token[QStringLiteral("holding")] = obj.value(QStringLiteral("holding")).toString();
|
||||
token[QStringLiteral("definitionId")] = definitionId;
|
||||
token[QStringLiteral("holding")] = holding;
|
||||
token[QStringLiteral("decimals")] = obj.value(QStringLiteral("decimals")).toInt();
|
||||
out.append(token);
|
||||
}
|
||||
|
||||
@ -68,6 +68,10 @@ private:
|
||||
|
||||
void persistConfigPath(const QString& path);
|
||||
void persistStoragePath(const QString& path);
|
||||
// Normalizes an account id given as either 64-char lowercase/uppercase hex
|
||||
// or base58 to lowercase hex. Returns an empty QString if `id` is neither
|
||||
// (or the base58 decode fails), so callers can detect and skip it.
|
||||
QString normalizeAccountId(const QString& id);
|
||||
void openOrAdoptWallet();
|
||||
// True when the shared core already has a wallet open — including a freshly
|
||||
// created one with zero accounts. See the definition for why list_accounts()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user