perf(liquidity): refresh context accounts after inclusion

This commit is contained in:
Ricardo Guilherme Schmidt
2026-07-18 19:56:38 -03:00
parent 88e2ef2b0a
commit fab26b58c9
6 changed files with 64 additions and 4 deletions
+5
View File
@@ -78,6 +78,7 @@ pub(super) fn plan(input: PlanRequest) -> Result<Value, String> {
}
let NewPositionPlan { accounts, branch } = plan;
let affected_account_ids = accounts.writable_account_ids(fresh_lp)?;
let context_affected_account_ids = accounts.context_affected_account_ids(fresh_lp)?;
let (account_ids, signing_requirements) = accounts.wallet_args(fresh_lp)?;
let instruction = match branch {
QuoteBranch::Missing { amount_a, amount_b } => {
@@ -121,6 +122,10 @@ pub(super) fn plan(input: PlanRequest) -> Result<Value, String> {
.into_iter()
.map(account_id_hex)
.collect::<Vec<_>>(),
"contextAffectedAccountIds": context_affected_account_ids
.into_iter()
.map(account_id_hex)
.collect::<Vec<_>>(),
"signingRequirements": signing_requirements,
"instruction": instruction,
"deadlineMs": deadline.to_string(),
+20
View File
@@ -210,6 +210,26 @@ impl AccountPlan {
})
.collect()
}
pub(super) fn context_affected_account_ids(
&self,
fresh_lp: Option<AccountId>,
) -> Result<Vec<AccountId>, String> {
self.rows
.iter()
.filter(|row| {
row.action != "read"
&& (row.role == "lp_definition" || row.role.starts_with("user_holding_"))
})
.map(|row| match row.account_id {
Some(account_id) => Ok(account_id),
None if row.role == "user_holding_lp" => {
fresh_lp.ok_or_else(|| String::from("transaction plan has no LP holding"))
}
None => Err(String::from("transaction plan has an unresolved account")),
})
.collect()
}
}
impl AccountPlanRow {
+18
View File
@@ -594,6 +594,15 @@ fn missing_pool_quote_and_plan_use_current_account_order() {
assert_eq!(affected.len(), 9);
assert!(!affected.contains(&json!(account_id_hex(config_id))));
assert!(!affected.contains(&json!(account_id_hex(clock_id))));
assert_eq!(
plan_value["contextAffectedAccountIds"].as_array().unwrap(),
&vec![
plan_value["accountIds"][4].clone(),
plan_value["accountIds"][6].clone(),
plan_value["accountIds"][7].clone(),
plan_value["accountIds"][8].clone(),
]
);
assert_preview_matches_plan(&quote_value, &plan_value, Some(fresh_lp));
}
@@ -741,6 +750,15 @@ fn active_pool_quote_uses_ratio_and_existing_lp_holding() {
assert_eq!(plan_value["accountIds"].as_array().unwrap().len(), 10);
assert_eq!(plan_value["accountIds"][7], account_id_hex(lp_holding));
assert_eq!(plan_value["signingRequirements"][7], false);
assert_eq!(
plan_value["contextAffectedAccountIds"].as_array().unwrap(),
&vec![
plan_value["accountIds"][4].clone(),
plan_value["accountIds"][5].clone(),
plan_value["accountIds"][6].clone(),
plan_value["accountIds"][7].clone(),
]
);
assert_preview_matches_plan(&quote_value, &plan_value, None);
}
+5 -2
View File
@@ -432,9 +432,12 @@ void AmmUiBackend::watchTransaction(const QVariantMap& result)
bool deadlineValid = false;
const qint64 deadline = result.value(QStringLiteral("deadlineMs"))
.toString().toLongLong(&deadlineValid);
const QVariantList affectedValues = result.contains(
QStringLiteral("contextAffectedAccountIds"))
? result.value(QStringLiteral("contextAffectedAccountIds")).toList()
: result.value(QStringLiteral("affectedAccountIds")).toList();
QStringList affected;
for (const QVariant& value : result.value(
QStringLiteral("affectedAccountIds")).toList()) {
for (const QVariant& value : affectedValues) {
affected.append(value.toString());
}
if (nativeHash.isEmpty() || !deadlineValid || affected.isEmpty())
+7 -1
View File
@@ -929,7 +929,9 @@ void NewPositionRuntime::submitPlanAsync(QJsonObject input,
[guard, submitGeneration, walletGeneration,
freshLpAccountId = std::move(freshLpAccountId), deadlineMs =
plan.value(QStringLiteral("deadlineMs")), affectedAccountIds =
plan.value(QStringLiteral("affectedAccountIds"))](
plan.value(QStringLiteral("affectedAccountIds")),
contextAffectedAccountIds =
plan.value(QStringLiteral("contextAffectedAccountIds"))](
WalletSubmission submission) mutable {
if (!guard)
return;
@@ -962,6 +964,8 @@ void NewPositionRuntime::submitPlanAsync(QJsonObject input,
{ QStringLiteral("deadlineMs"), deadlineMs },
{ QStringLiteral("affectedAccountIds"),
affectedAccountIds },
{ QStringLiteral("contextAffectedAccountIds"),
contextAffectedAccountIds },
}.toVariantMap());
});
}
@@ -1172,5 +1176,7 @@ QVariantMap NewPositionRuntime::submit(const QVariantMap& request,
{ QStringLiteral("transactionId"), transactionId },
{ QStringLiteral("nativeTransactionHash"), submission.nativeHash },
{ QStringLiteral("deadlineMs"), plan.value(QStringLiteral("deadlineMs")) },
{ QStringLiteral("contextAffectedAccountIds"),
plan.value(QStringLiteral("contextAffectedAccountIds")) },
}.toVariantMap();
}
@@ -360,6 +360,8 @@ namespace {
{ QStringLiteral("accountIds"), QJsonArray { QStringLiteral("account") } },
{ QStringLiteral("affectedAccountIds"),
QJsonArray { QStringLiteral("account") } },
{ QStringLiteral("contextAffectedAccountIds"),
QJsonArray { QStringLiteral("account") } },
{ QStringLiteral("signingRequirements"), QJsonArray { true } },
{ QStringLiteral("instruction"), QJsonArray { 1 } },
{ QStringLiteral("programId"), QStringLiteral("program") },
@@ -487,6 +489,10 @@ int main(int argc, char** argv)
== wallet.transactionHash,
"submitted result should preserve the native hash for polling"))
return 1;
if (!expect(result.value(QStringLiteral("contextAffectedAccountIds")).toList()
== QVariantList { QStringLiteral("account") },
"submitted result should preserve context refresh account IDs"))
return 1;
if (!expect(wallet.createdAccounts == 1 && client.sawFreshLp,
"fresh LP account should enter the plan"))
return 1;
@@ -1205,7 +1211,9 @@ int main(int argc, char** argv)
asyncWallet.finishSubmission();
if (!expect(asyncCallbackCount == 1
&& asyncResult.value(QStringLiteral("status")).toString()
== QStringLiteral("submitted"),
== QStringLiteral("submitted")
&& asyncResult.value(QStringLiteral("contextAffectedAccountIds"))
.toList() == QVariantList { QStringLiteral("account") },
"async wallet completion should finish exactly once"))
return 1;