mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-07-26 16:53: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
|
property real slippageTolerancePercent: 0.5
|
||||||
|
|
||||||
// ── Pool resolution (backend.resolvePool) ───────────────────────────────
|
// ── Pool resolution (backend.resolvePool) ───────────────────────────────
|
||||||
// sellToken is always passed as defA and buyToken as defB, so reserveA
|
// A pool's PoolDefinition stores def_a/def_b in the pool CREATOR's order
|
||||||
// always corresponds to sellToken and reserveB to buyToken — no separate
|
// (from NewDefinition), not sorted, and not necessarily in (sellToken,
|
||||||
// "direction" bookkeeping is needed (unlike a generic A/B picker): the
|
// buyToken) order. reserveA/reserveB mirror that same canonical order, so
|
||||||
// sell/buy assignment *is* the direction.
|
// they must be mapped to sell/buy via poolDefAHex below — never assumed.
|
||||||
property bool poolLoading: false
|
property bool poolLoading: false
|
||||||
property bool poolResolved: false
|
property bool poolResolved: false
|
||||||
property bool poolExists: false
|
property bool poolExists: false
|
||||||
property string poolReserveA: "0"
|
property string poolReserveA: "0"
|
||||||
property string poolReserveB: "0"
|
property string poolReserveB: "0"
|
||||||
|
property string poolDefAHex: ""
|
||||||
property int poolFeeBps: 30
|
property int poolFeeBps: 30
|
||||||
property string poolError: ""
|
property string poolError: ""
|
||||||
|
|
||||||
@ -95,6 +96,7 @@ Rectangle {
|
|||||||
root.poolExists = !!(pool && pool.exists)
|
root.poolExists = !!(pool && pool.exists)
|
||||||
root.poolReserveA = (pool && pool.reserveA) || "0"
|
root.poolReserveA = (pool && pool.reserveA) || "0"
|
||||||
root.poolReserveB = (pool && pool.reserveB) || "0"
|
root.poolReserveB = (pool && pool.reserveB) || "0"
|
||||||
|
root.poolDefAHex = (pool && pool.defAHex) || ""
|
||||||
root.poolFeeBps = (pool && pool.feeBps) || 30
|
root.poolFeeBps = (pool && pool.feeBps) || 30
|
||||||
root.poolError = ""
|
root.poolError = ""
|
||||||
},
|
},
|
||||||
@ -111,8 +113,12 @@ Rectangle {
|
|||||||
// drive the *estimate* (expected output / min received / price impact),
|
// drive the *estimate* (expected output / min received / price impact),
|
||||||
// never the actual swap amount — the sell amount sent to the backend is
|
// never the actual swap amount — the sell amount sent to the backend is
|
||||||
// the user's raw input text, passed through verbatim.
|
// the user's raw input text, passed through verbatim.
|
||||||
readonly property real sellReserveNum: Number(root.poolReserveA) || 0
|
// The pool's reserveA/reserveB follow the pool's canonical def_a/def_b
|
||||||
readonly property real buyReserveNum: Number(root.poolReserveB) || 0
|
// 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: {
|
readonly property real parsedSellInput: {
|
||||||
var amt = parseFloat(sellInput)
|
var amt = parseFloat(sellInput)
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
#include "AmmUiBackend.h"
|
#include "AmmUiBackend.h"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@ -484,6 +487,26 @@ void AmmUiBackend::copyToClipboard(QString text)
|
|||||||
QGuiApplication::clipboard()->setText(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 AmmUiBackend::resolvePool(QString defAHex, QString defBHex)
|
||||||
{
|
{
|
||||||
QVariantMap out;
|
QVariantMap out;
|
||||||
@ -574,6 +597,8 @@ QVariantMap AmmUiBackend::resolvePool(QString defAHex, QString defBHex)
|
|||||||
out[QStringLiteral("exists")] = true;
|
out[QStringLiteral("exists")] = true;
|
||||||
out[QStringLiteral("configHex")] = configHex;
|
out[QStringLiteral("configHex")] = configHex;
|
||||||
out[QStringLiteral("poolIdHex")] = poolHex;
|
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("vaultAHex")] = bytes32ToHex(poolView.vault_a);
|
||||||
out[QStringLiteral("vaultBHex")] = bytes32ToHex(poolView.vault_b);
|
out[QStringLiteral("vaultBHex")] = bytes32ToHex(poolView.vault_b);
|
||||||
out[QStringLiteral("currentTickHex")] = bytes32ToHex(currentTickPda);
|
out[QStringLiteral("currentTickHex")] = bytes32ToHex(currentTickPda);
|
||||||
@ -713,11 +738,26 @@ QVariantList AmmUiBackend::tokenList()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const QJsonObject obj = entry.toObject();
|
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;
|
QVariantMap token;
|
||||||
token[QStringLiteral("symbol")] = obj.value(QStringLiteral("symbol")).toString();
|
token[QStringLiteral("symbol")] = symbol;
|
||||||
token[QStringLiteral("name")] = obj.value(QStringLiteral("name")).toString();
|
token[QStringLiteral("name")] = obj.value(QStringLiteral("name")).toString();
|
||||||
token[QStringLiteral("definitionId")] = obj.value(QStringLiteral("definitionId")).toString();
|
token[QStringLiteral("definitionId")] = definitionId;
|
||||||
token[QStringLiteral("holding")] = obj.value(QStringLiteral("holding")).toString();
|
token[QStringLiteral("holding")] = holding;
|
||||||
token[QStringLiteral("decimals")] = obj.value(QStringLiteral("decimals")).toInt();
|
token[QStringLiteral("decimals")] = obj.value(QStringLiteral("decimals")).toInt();
|
||||||
out.append(token);
|
out.append(token);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,6 +68,10 @@ private:
|
|||||||
|
|
||||||
void persistConfigPath(const QString& path);
|
void persistConfigPath(const QString& path);
|
||||||
void persistStoragePath(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();
|
void openOrAdoptWallet();
|
||||||
// True when the shared core already has a wallet open — including a freshly
|
// 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()
|
// created one with zero accounts. See the definition for why list_accounts()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user