mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-08-25 06:01:11 +00:00
refactor(amm): drop the new-position schema version tag
The add-liquidity flow stamped a `new-position.v1` schema tag on every request and response and validated it across all three layers — the QML plugin, the amm_module core module, and the amm_client Rust crate. It was a cross-version compatibility guard, but these artifacts always ship together, so the contract is honored implicitly, and the swap view already works fine without one. Dropping it makes the liquidity view consistent with swap and removes a layer of ceremony. - amm_client: remove PositionRequest.schema and the unsupported_schema check in compute_quote; drop QuoteCommitment.schema (changes quoteHash, which is internal-only) and every "schema" response stamp; delete the SCHEMA / NEW_POSITION_SCHEMA constants and the public export. - amm_module: remove the SCHEMA constant and its four response stamps. - AmmUiBackend: remove its local NEW_POSITION_SCHEMA and the stamps in loadingContext() / newPositionError(). - QML: drop the "schema" fields from the request/envelope builders and relax the validity gates to check status / canSubmit instead (the sole check in NewPositionFlow now guards on a missing `status`); strip the now-dead schema fields from the liquidity QML test fixtures. - Also removes the last stale comment references to the deleted *Runtime classes.
This commit is contained in:
@@ -29,7 +29,6 @@ pub(super) struct FundingCommitment {
|
||||
|
||||
#[derive(BorshSerialize)]
|
||||
pub(super) struct QuoteCommitment {
|
||||
pub(super) schema: String,
|
||||
pub(super) network_id: String,
|
||||
pub(super) network_fingerprint: String,
|
||||
pub(super) amm_program_id: [u8; 32],
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::{
|
||||
config::load_config,
|
||||
holding::{select_holding, wallet_holdings, SelectedHolding},
|
||||
quote_error::issue,
|
||||
ContextRequest, TokenIdsRequest, SCHEMA,
|
||||
ContextRequest, TokenIdsRequest,
|
||||
};
|
||||
use crate::account::{
|
||||
account_id_from_hex, account_id_hex, decode_account, parse_base58_id, parse_program_id,
|
||||
@@ -117,7 +117,6 @@ pub(super) fn context(request: ContextRequest) -> Result<Value, String> {
|
||||
});
|
||||
|
||||
Ok(json!({
|
||||
"schema": SCHEMA,
|
||||
"status": if request.wallet_available { "ready" } else { "no_wallet" },
|
||||
"networkId": request.network_id,
|
||||
"networkFingerprint": request.network_fingerprint,
|
||||
@@ -136,7 +135,6 @@ pub(super) fn context(request: ContextRequest) -> Result<Value, String> {
|
||||
|
||||
fn context_error(request: &ContextRequest, code: &str) -> Value {
|
||||
json!({
|
||||
"schema": SCHEMA,
|
||||
"status": "error",
|
||||
"code": code,
|
||||
"networkId": request.network_id,
|
||||
|
||||
@@ -29,11 +29,6 @@ use serde_json::Value;
|
||||
|
||||
pub use crate::account::{AccountRead, WalletAccount};
|
||||
|
||||
/// Schema identifier expected by position quote and plan requests.
|
||||
pub const NEW_POSITION_SCHEMA: &str = "new-position.v1";
|
||||
|
||||
pub(crate) const SCHEMA: &str = NEW_POSITION_SCHEMA;
|
||||
|
||||
/// JSON response shared by direct Rust callers and transport adapters.
|
||||
pub type AmmResponse = Value;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use super::{
|
||||
clock::decode_clock,
|
||||
position::{NewPositionPlan, QuoteBranch, QuoteComputation},
|
||||
quote::compute_quote,
|
||||
PlanRequest, QuoteRequest, SCHEMA,
|
||||
PlanRequest, QuoteRequest,
|
||||
};
|
||||
use crate::account::{account_id_hex, decode_account, AccountRead};
|
||||
|
||||
@@ -22,7 +22,6 @@ pub(super) fn plan(input: PlanRequest) -> Result<Value, String> {
|
||||
let quote = compute_quote("e_input)?;
|
||||
if quote.quote_hash() != Some(input.quote_hash.as_str()) {
|
||||
return Ok(json!({
|
||||
"schema": SCHEMA,
|
||||
"status": "error",
|
||||
"code": "quote_changed",
|
||||
"recoverable": true,
|
||||
@@ -33,7 +32,6 @@ pub(super) fn plan(input: PlanRequest) -> Result<Value, String> {
|
||||
QuoteComputation::Evaluated(evaluated) => evaluated,
|
||||
QuoteComputation::Failed(failure) => {
|
||||
return Ok(json!({
|
||||
"schema": SCHEMA,
|
||||
"status": "error",
|
||||
"code": "quote_not_submittable",
|
||||
"recoverable": true,
|
||||
@@ -43,7 +41,6 @@ pub(super) fn plan(input: PlanRequest) -> Result<Value, String> {
|
||||
};
|
||||
let Some(plan) = evaluated.plan else {
|
||||
return Ok(json!({
|
||||
"schema": SCHEMA,
|
||||
"status": "error",
|
||||
"code": "quote_not_submittable",
|
||||
"recoverable": true,
|
||||
@@ -53,7 +50,6 @@ pub(super) fn plan(input: PlanRequest) -> Result<Value, String> {
|
||||
let fresh_lp = if plan.requires_fresh_lp() {
|
||||
let Some(read) = input.fresh_lp.as_ref() else {
|
||||
return Ok(json!({
|
||||
"schema": SCHEMA,
|
||||
"status": "needs_fresh_lp",
|
||||
"code": "fresh_lp_required",
|
||||
}));
|
||||
@@ -112,7 +108,6 @@ pub(super) fn plan(input: PlanRequest) -> Result<Value, String> {
|
||||
};
|
||||
|
||||
Ok(json!({
|
||||
"schema": SCHEMA,
|
||||
"status": "ready",
|
||||
"programId": input.amm_program_id,
|
||||
"accountIds": account_ids.into_iter().map(account_id_hex).collect::<Vec<_>>(),
|
||||
@@ -124,7 +119,6 @@ pub(super) fn plan(input: PlanRequest) -> Result<Value, String> {
|
||||
|
||||
fn plan_error(code: &str) -> Value {
|
||||
json!({
|
||||
"schema": SCHEMA,
|
||||
"status": "error",
|
||||
"code": code,
|
||||
"recoverable": true,
|
||||
|
||||
@@ -3,7 +3,7 @@ use serde_json::{json, Value};
|
||||
|
||||
use super::{
|
||||
commitment::SourceCommitment, holding::SelectedHolding, pair::PairIds, quote_error::issue,
|
||||
PairSnapshot, PositionRequest, SCHEMA,
|
||||
PairSnapshot, PositionRequest,
|
||||
};
|
||||
use crate::account::{account_id_from_hex, program_id_base58};
|
||||
|
||||
@@ -82,7 +82,6 @@ impl QuoteComputation {
|
||||
impl QuoteFailure {
|
||||
pub(super) fn into_value(self, request: &PositionRequest) -> Value {
|
||||
json!({
|
||||
"schema": SCHEMA,
|
||||
"status": "error",
|
||||
"canSubmit": false,
|
||||
"code": self.code,
|
||||
|
||||
@@ -24,7 +24,7 @@ use super::{
|
||||
QuoteComputation,
|
||||
},
|
||||
quote_error::{fatal_quote, issue},
|
||||
QuoteRequest, SCHEMA,
|
||||
QuoteRequest,
|
||||
};
|
||||
use crate::account::{
|
||||
decode_account, parse_base58_id, parse_program_id, program_id_bytes, AccountRead,
|
||||
@@ -40,13 +40,6 @@ pub(super) fn quote(request: QuoteRequest) -> Result<Value, String> {
|
||||
}
|
||||
|
||||
pub(super) fn compute_quote(input: &QuoteRequest) -> Result<QuoteComputation, String> {
|
||||
if input.request.schema != SCHEMA {
|
||||
return Ok(fatal_quote(
|
||||
"unsupported_schema",
|
||||
&["schema"],
|
||||
json!({ "received": input.request.schema }),
|
||||
));
|
||||
}
|
||||
let amm_program = parse_program_id(&input.amm_program_id)?;
|
||||
let token_a = match parse_base58_id(&input.request.token_a_id, "token A id") {
|
||||
Ok(id) => id,
|
||||
@@ -238,7 +231,6 @@ fn compute_missing_quote(
|
||||
let sources = account_plan.take_sources();
|
||||
let funding_commitment = funding_commitments(pair, &holding_a, amount_a, &holding_b, amount_b);
|
||||
let commitment = QuoteCommitment {
|
||||
schema: String::from(SCHEMA),
|
||||
network_id: input.network_id.clone(),
|
||||
network_fingerprint: input.network_fingerprint.clone(),
|
||||
amm_program_id: program_id_bytes(amm_program),
|
||||
@@ -261,7 +253,6 @@ fn compute_missing_quote(
|
||||
let quote_hash = hash_quote(&commitment)?;
|
||||
let preview = account_plan.preview();
|
||||
let value = json!({
|
||||
"schema": SCHEMA,
|
||||
"status": "ok",
|
||||
"canSubmit": can_submit,
|
||||
"code": if can_submit { "ready" } else { "funding_required" },
|
||||
@@ -482,7 +473,6 @@ fn compute_active_quote(
|
||||
)?;
|
||||
let sources = account_plan.take_sources();
|
||||
let commitment = QuoteCommitment {
|
||||
schema: String::from(SCHEMA),
|
||||
network_id: input.network_id.clone(),
|
||||
network_fingerprint: input.network_fingerprint.clone(),
|
||||
amm_program_id: program_id_bytes(amm_program),
|
||||
@@ -509,7 +499,6 @@ fn compute_active_quote(
|
||||
let quote_hash = hash_quote(&commitment)?;
|
||||
let preview = account_plan.preview();
|
||||
let value = json!({
|
||||
"schema": SCHEMA,
|
||||
"status": "ok",
|
||||
"canSubmit": can_submit,
|
||||
"code": if can_submit { "ready" } else { "funding_required" },
|
||||
|
||||
@@ -90,7 +90,6 @@ pub struct ProgramIdRequest {
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PositionRequest {
|
||||
pub schema: String,
|
||||
pub token_a_id: String,
|
||||
pub token_b_id: String,
|
||||
pub fee_bps: u32,
|
||||
|
||||
@@ -104,8 +104,8 @@ pub(super) fn swap_plan(request: SwapPlanRequest) -> Result<Value, String> {
|
||||
let token_out = account_id_from_hex(&request.token_out_id, "token out id")?;
|
||||
// Domain errors (a bad pair, an unavailable config) mirror `swap_pair`'s
|
||||
// `{ status: "error", code }` shape rather than `Err`, which is reserved for
|
||||
// malformed inputs. `SwapRuntime::swap` treats any non-"ready" status as a
|
||||
// failed plan, so both map to the same UI outcome.
|
||||
// malformed inputs. Callers treat any non-"ready" status as a failed plan,
|
||||
// so both map to the same outcome.
|
||||
if token_in == token_out {
|
||||
return Ok(json!({ "status": "error", "code": "same_token_pair" }));
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ use super::{
|
||||
position::AccountPlanHoldings,
|
||||
quote::{div_ceil_u256, minimum_opening_pair, quote, Q64},
|
||||
ContextRequest, PairIdsRequest, PairSnapshot, PlanRequest, PositionRequest, QuoteRequest,
|
||||
TokenIdsRequest, SCHEMA,
|
||||
TokenIdsRequest,
|
||||
};
|
||||
use crate::{
|
||||
account::{account_id_hex, account_read, decode_account, parse_base58_id, program_id_bytes},
|
||||
@@ -140,7 +140,6 @@ fn base_snapshot(pair: PairIds) -> PairSnapshot {
|
||||
fn request(pair: PairIds) -> PositionRequest {
|
||||
assert!(is_canonical_pair(pair.token_a, pair.token_b));
|
||||
PositionRequest {
|
||||
schema: String::from(SCHEMA),
|
||||
token_a_id: pair.token_a.to_string(),
|
||||
token_b_id: pair.token_b.to_string(),
|
||||
fee_bps: 30,
|
||||
|
||||
@@ -10,5 +10,4 @@ pub use api::{
|
||||
token_ids, AccountRead, AmmApiError, AmmResponse, AmmResult, ConfigIdRequest, ContextRequest,
|
||||
PairIdsRequest, PairSnapshot, PlanRequest, PositionRequest, ProgramIdRequest, QuoteRequest,
|
||||
ResolvePoolRequest, SwapPairRequest, SwapPlanRequest, TokenIdsRequest, WalletAccount,
|
||||
NEW_POSITION_SCHEMA,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use amm_client::{config_id, ConfigIdRequest, NEW_POSITION_SCHEMA};
|
||||
use amm_client::{config_id, ConfigIdRequest};
|
||||
|
||||
#[test]
|
||||
fn direct_rust_api_does_not_require_ffi() {
|
||||
@@ -9,5 +9,4 @@ fn direct_rust_api_does_not_require_ffi() {
|
||||
|
||||
assert_eq!(response["status"], "ok");
|
||||
assert!(response["configId"].is_string());
|
||||
assert_eq!(NEW_POSITION_SCHEMA, "new-position.v1");
|
||||
}
|
||||
|
||||
@@ -87,8 +87,7 @@ AmmActionCard {
|
||||
&& root.selectedTokenBId.length > 0
|
||||
&& root.selectedTokenAId !== root.selectedTokenBId
|
||||
readonly property bool resolvingToken: root.resolvingTokenId.length > 0
|
||||
readonly property bool canConfirm: root.quotePayload.schema === "new-position.v1"
|
||||
&& root.quotePayload.status === "ok"
|
||||
readonly property bool canConfirm: root.quotePayload.status === "ok"
|
||||
&& root.quotePayload.canSubmit === true
|
||||
&& root.quoteMatchesPair()
|
||||
&& String(root.quotePayload.quoteHash || "").length > 0
|
||||
@@ -858,8 +857,7 @@ AmmActionCard {
|
||||
}
|
||||
|
||||
function acceptPoolActivation(quote) {
|
||||
if (!quote || quote.schema !== "new-position.v1"
|
||||
|| quote.status !== "ok"
|
||||
if (!quote || quote.status !== "ok"
|
||||
|| quote.poolStatus !== "active_pool"
|
||||
|| !root.quoteMatchesSelectedPair(quote)) {
|
||||
return false
|
||||
@@ -1077,7 +1075,6 @@ AmmActionCard {
|
||||
|
||||
function pairRequest() {
|
||||
return {
|
||||
"schema": "new-position.v1",
|
||||
"tokenAId": root.displayIsCanonical
|
||||
? root.selectedTokenAId : root.selectedTokenBId,
|
||||
"tokenBId": root.displayIsCanonical
|
||||
|
||||
@@ -182,8 +182,8 @@ QtObject {
|
||||
root.quoteLoading = false
|
||||
root.quoteStale = false
|
||||
root.quoteErrorCode = ""
|
||||
if (!quote || quote.schema !== "new-position.v1")
|
||||
root.newPositionQuote = root.quoteError("unsupported_schema")
|
||||
if (!quote || !quote.status)
|
||||
root.newPositionQuote = root.quoteError("backend_error")
|
||||
else
|
||||
root.newPositionQuote = quote
|
||||
},
|
||||
@@ -209,8 +209,7 @@ QtObject {
|
||||
|
||||
root.runtime.watch(root.backend.submitNewPosition(snapshot.request, snapshot.quoteHash),
|
||||
function(result) {
|
||||
if (result && result.schema === "new-position.v1"
|
||||
&& result.status === "submitted"
|
||||
if (result && result.status === "submitted"
|
||||
&& /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(
|
||||
String(result.transactionId || ""))) {
|
||||
if (snapshot.request.initialPriceRealRaw !== undefined)
|
||||
@@ -234,7 +233,7 @@ QtObject {
|
||||
function finishSubmitFailure(result) {
|
||||
root.submitting = false
|
||||
const hasFreshQuote = result && result.quote
|
||||
&& result.quote.schema === "new-position.v1"
|
||||
&& result.quote.status
|
||||
if (hasFreshQuote) {
|
||||
root.newPositionQuote = result.quote
|
||||
root.quoteLoading = false
|
||||
@@ -283,8 +282,7 @@ QtObject {
|
||||
|
||||
function finishPoolProbe(pending, quote) {
|
||||
root.poolProbeInFlight = false
|
||||
if (quote && quote.schema === "new-position.v1"
|
||||
&& quote.poolStatus === "active_pool") {
|
||||
if (quote && quote.poolStatus === "active_pool") {
|
||||
root.removePendingPool(pending.key)
|
||||
if (root.matchesSelectedPair(pending.request)) {
|
||||
root.poolActivated(quote)
|
||||
@@ -349,7 +347,6 @@ QtObject {
|
||||
|
||||
function loadingContext() {
|
||||
return {
|
||||
"schema": "new-position.v1",
|
||||
"status": "loading",
|
||||
"tokens": [],
|
||||
"feeTiers": []
|
||||
@@ -358,7 +355,6 @@ QtObject {
|
||||
|
||||
function quoteError(code) {
|
||||
return {
|
||||
"schema": "new-position.v1",
|
||||
"status": "error",
|
||||
"canSubmit": false,
|
||||
"code": code,
|
||||
|
||||
@@ -9,14 +9,11 @@
|
||||
#include "logos_sdk.h"
|
||||
|
||||
namespace {
|
||||
const char NEW_POSITION_SCHEMA[] = "new-position.v1";
|
||||
|
||||
// The new-position context placeholder published before the module
|
||||
// connection is up (matches the module's "loading" contextState).
|
||||
QVariantMap loadingContext()
|
||||
{
|
||||
return QVariantMap {
|
||||
{ QStringLiteral("schema"), QString::fromLatin1(NEW_POSITION_SCHEMA) },
|
||||
{ QStringLiteral("status"), QStringLiteral("loading") },
|
||||
{ QStringLiteral("networkId"), QStringLiteral("lez") },
|
||||
{ QStringLiteral("networkFingerprint"), QString() },
|
||||
@@ -26,12 +23,11 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
// A new-position.v1 error envelope (matches the module's publicError), for
|
||||
// A new-position error envelope (matches the module's publicError), for
|
||||
// the backend-side failure paths (e.g. LP-account creation failing).
|
||||
QVariantMap newPositionError(const QString& code)
|
||||
{
|
||||
return QVariantMap {
|
||||
{ QStringLiteral("schema"), QString::fromLatin1(NEW_POSITION_SCHEMA) },
|
||||
{ QStringLiteral("status"), QStringLiteral("error") },
|
||||
{ QStringLiteral("canSubmit"), false },
|
||||
{ QStringLiteral("code"), code },
|
||||
@@ -223,7 +219,7 @@ QString AmmUiBackend::swapExactInput(QString defAHex, QString defBHex, QString u
|
||||
// only locks this UI and leaves the shared logos_execution_zone wallet open (another
|
||||
// app may keep it open, or this app opened-then-disconnected), and the QML submit path
|
||||
// doesn't check isWalletOpen — so without this a swap could sign/submit while the UI
|
||||
// shows "Connect". Mirrors the guard the old SwapRuntime::swap() enforced.
|
||||
// shows "Connect".
|
||||
if (!isWalletOpen())
|
||||
return {};
|
||||
|
||||
|
||||
@@ -19,12 +19,10 @@ TestCase {
|
||||
property bool walletStateReady: false
|
||||
property var submitResult: ({})
|
||||
property var quoteResult: ({
|
||||
"schema": "new-position.v1",
|
||||
"status": "ok",
|
||||
"poolStatus": "missing_pool"
|
||||
})
|
||||
property var newPositionContext: ({
|
||||
"schema": "new-position.v1",
|
||||
"status": "ready",
|
||||
"tokens": [],
|
||||
"feeTiers": []
|
||||
@@ -151,11 +149,9 @@ TestCase {
|
||||
|
||||
page.flow.quoteSerial = 7
|
||||
page.flow.finishSubmitFailure({
|
||||
"schema": "new-position.v1",
|
||||
"status": "error",
|
||||
"code": "quote_not_submittable",
|
||||
"quote": {
|
||||
"schema": "new-position.v1",
|
||||
"status": "ok",
|
||||
"canSubmit": false,
|
||||
"quoteHash": "sha256:fresh"
|
||||
@@ -171,7 +167,6 @@ TestCase {
|
||||
var backend = createTemporaryObject(backendComponent, testCase, {
|
||||
"walletStateReady": true,
|
||||
"submitResult": {
|
||||
"schema": "new-position.v1",
|
||||
"status": "submitted",
|
||||
"transactionId": submittedTransactionId,
|
||||
"deadlineMs": String(Date.now() + 60000)
|
||||
@@ -200,7 +195,6 @@ TestCase {
|
||||
var backend = createTemporaryObject(backendComponent, testCase, {
|
||||
"walletStateReady": true,
|
||||
"submitResult": {
|
||||
"schema": "new-position.v1",
|
||||
"status": "submitted",
|
||||
"transactionId": submittedTransactionId,
|
||||
"deadlineMs": String(Date.now() + 60000)
|
||||
@@ -239,7 +233,6 @@ TestCase {
|
||||
var backend = createTemporaryObject(backendComponent, testCase, {
|
||||
"walletStateReady": true,
|
||||
"submitResult": {
|
||||
"schema": "new-position.v1",
|
||||
"status": "submitted",
|
||||
"transactionId": "000102030405060708090a0b0c0d0e0f"
|
||||
+ "101112131415161718191a1b1c1d1e1f"
|
||||
@@ -282,7 +275,6 @@ TestCase {
|
||||
page.flow.pendingQuoteRequest = { "ok": true, "request": request }
|
||||
page.flow.pendingPoolProbes = [pending]
|
||||
page.flow.newPositionQuote = {
|
||||
"schema": "new-position.v1",
|
||||
"status": "ok",
|
||||
"poolStatus": "missing_pool",
|
||||
"tokenAId": request.tokenAId,
|
||||
@@ -291,7 +283,6 @@ TestCase {
|
||||
page.flow.quoteStale = false
|
||||
|
||||
page.flow.finishPoolProbe(pending, {
|
||||
"schema": "new-position.v1",
|
||||
"status": "ok",
|
||||
"poolStatus": "active_pool",
|
||||
"tokenAId": request.tokenAId,
|
||||
|
||||
@@ -354,7 +354,6 @@ TestCase {
|
||||
form.minimumAmountBRaw = "2000000"
|
||||
|
||||
verify(form.acceptPoolActivation({
|
||||
"schema": "new-position.v1",
|
||||
"status": "ok",
|
||||
"tokenAId": tokenHigh,
|
||||
"tokenBId": tokenLow,
|
||||
@@ -378,7 +377,6 @@ TestCase {
|
||||
|
||||
function test_staleQuoteErrorsDoNotMarkCurrentDraft() {
|
||||
var quote = {
|
||||
"schema": "new-position.v1",
|
||||
"status": "ok",
|
||||
"tokenAId": tokenHigh,
|
||||
"tokenBId": tokenLow,
|
||||
|
||||
@@ -28,7 +28,7 @@ methods (the module API is generated from the header) are:
|
||||
`definitionId`/`holding` normalized to hex.
|
||||
- `newPositionContext(request, walletOpen, refreshWalletAccounts)` — the
|
||||
add-liquidity view state (available tokens, fee tiers, warnings) as a
|
||||
`new-position.v1` map.
|
||||
context map.
|
||||
- `quoteNewPosition(request, walletOpen)` — prices an add-liquidity request
|
||||
against current on-chain state (read-only).
|
||||
- `submitNewPosition(request, quoteHash, walletOpen, freshLpId)` — submits an
|
||||
|
||||
@@ -47,10 +47,6 @@ constexpr char AMM_PROGRAM_BIN_ENV[] = "AMM_PROGRAM_BIN";
|
||||
// Absolute path to the JSON token-list config consumed by tokenList().
|
||||
constexpr char TOKENS_CONFIG_ENV[] = "TOKENS_CONFIG";
|
||||
|
||||
// new-position.v1 response schema tag (matches the app-side NewPositionRuntime
|
||||
// and the Rust client's NEW_POSITION_SCHEMA).
|
||||
constexpr char SCHEMA[] = "new-position.v1";
|
||||
|
||||
int hexVal(char c) {
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||
@@ -233,7 +229,7 @@ FfiResult call(char* (*op)(const char*), const json& request) {
|
||||
return {true, *it};
|
||||
}
|
||||
|
||||
// new-position.v1 envelope builders (ported from NewPositionRuntime).
|
||||
// new-position response envelope builders.
|
||||
json issue(const std::string& code, const json& blockingFields = json::array()) {
|
||||
return {
|
||||
{"code", code},
|
||||
@@ -249,7 +245,6 @@ json publicError(const std::string& code,
|
||||
json error = issue(code, blockingFields);
|
||||
error["details"] = details;
|
||||
return {
|
||||
{"schema", SCHEMA},
|
||||
{"status", "error"},
|
||||
{"canSubmit", false},
|
||||
{"code", code},
|
||||
@@ -264,7 +259,6 @@ json contextState(const std::string& status,
|
||||
const std::string& network_fingerprint,
|
||||
const std::string& code = {}) {
|
||||
json state = {
|
||||
{"schema", SCHEMA},
|
||||
{"status", status},
|
||||
{"networkId", network_id},
|
||||
{"networkFingerprint", network_fingerprint},
|
||||
@@ -750,7 +744,6 @@ LogosMap AmmModuleImpl::submitNewPosition(const LogosMap& request,
|
||||
if (quote.value("requiresFreshLp", false)) {
|
||||
if (fresh_lp_id.empty()) {
|
||||
return json{
|
||||
{"schema", SCHEMA},
|
||||
{"status", "requires_fresh_lp"},
|
||||
{"quote", quote},
|
||||
};
|
||||
@@ -794,7 +787,6 @@ LogosMap AmmModuleImpl::submitNewPosition(const LogosMap& request,
|
||||
if (transaction_id.empty()) return publicError("wallet_submission_failed");
|
||||
|
||||
return {
|
||||
{"schema", SCHEMA},
|
||||
{"status", "submitted"},
|
||||
{"transactionId", transaction_id},
|
||||
{"deadlineMs", plan.value("deadlineMs", json())},
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
// `logos_execution_zone` wallet module (reached via modules().logos_execution_zone).
|
||||
//
|
||||
// The same surface is consumed by the QML UI (via modules().amm_module) and
|
||||
// headlessly (logoscore call amm_module ...). Ported from the app-side
|
||||
// SwapRuntime / NewPositionRuntime orchestration (apps/amm/src) plus the
|
||||
// backend's network-context derivation, made Qt-free (std::string / LogosMap /
|
||||
// LogosList / nlohmann::json) as the universal authoring model requires.
|
||||
// headlessly (logoscore call amm_module ...). The swap / add-liquidity
|
||||
// orchestration and the backend's network-context derivation are made Qt-free
|
||||
// (std::string / LogosMap / LogosList / nlohmann::json) as the universal
|
||||
// authoring model requires.
|
||||
//
|
||||
// Public methods ARE the module's API; the Qt plugin glue is generated from
|
||||
// this header because metadata.json sets "interface": "universal". Keep the
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
LogosList tokenList();
|
||||
|
||||
/// New-position (add-liquidity) view state: reads the AMM config + the
|
||||
/// user's wallet accounts and returns the `new-position.v1` context map the
|
||||
/// user's wallet accounts and returns the new-position context map the
|
||||
/// UI renders (available tokens, fee tiers, warnings). `wallet_open` gates
|
||||
/// whether wallet accounts are included; `refresh_wallet_accounts` forces a
|
||||
/// fresh read rather than a cached one.
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
bool refresh_wallet_accounts);
|
||||
|
||||
/// Prices an add-liquidity request against current on-chain state and
|
||||
/// returns the `new-position.v1` quote map (quoteHash, canSubmit,
|
||||
/// returns the new-position quote map (quoteHash, canSubmit,
|
||||
/// requiresFreshLp, amounts, warnings). Read-only — no submission.
|
||||
LogosMap quoteNewPosition(const LogosMap& request, bool wallet_open);
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
/// WITHOUT submitting — the caller (the app backend, which owns the wallet
|
||||
/// keyset) creates the account and calls again with its id. Otherwise builds
|
||||
/// the plan (injecting the fresh LP account when given) and submits, then
|
||||
/// returns the `new-position.v1` submitted/error map.
|
||||
/// returns the new-position submitted/error map.
|
||||
LogosMap submitNewPosition(const LogosMap& request,
|
||||
const std::string& quote_hash,
|
||||
bool wallet_open,
|
||||
@@ -138,7 +138,7 @@ private:
|
||||
|
||||
// Builds the { networkId, networkFingerprint, ammProgramId, request,
|
||||
// snapshot } input shared by quoteNewPosition / submitNewPosition. On a
|
||||
// recoverable precondition failure, sets *error to a new-position.v1 error
|
||||
// recoverable precondition failure, sets *error to a new-position error
|
||||
// map and returns a null json.
|
||||
nlohmann::json buildQuoteInput(const LogosMap& request,
|
||||
const Network& net,
|
||||
|
||||
Reference in New Issue
Block a user