fix: account fallback for TWAP parts aged out of /by_uids (COW-989)#89
fix: account fallback for TWAP parts aged out of /by_uids (COW-989)#89lgahdl wants to merge 3 commits into
Conversation
When /orders/by_uids returns nothing for a stale candidateDiscreteOrder
(near or past validTo), fall back to /account/{owner}/orders before
defaulting to "expired". Groups missed UIDs by owner so only one account
fetch per unique owner is needed. Prevents fulfilled TWAP parts from
being recorded as "expired" when the API has aged them out of /by_uids.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Indexer review — TWAP parts aged out of /by_uids: account fallback Good fix for the aged-out TWAP parts — the per-owner fallback pattern is exactly right. Timeout budget is too tight for paginated owners: const ownerStatuses = await withTimeout(
fetchOwnerOrderStatuses(chainId, owner),
ORDERBOOK_HTTP_TIMEOUT_MS, // 10 s
"c2:stale:accountFallback",
);
Suggest changing to: const ownerStatuses = await withTimeout(
fetchOwnerOrderStatuses(chainId, owner),
BOOTSTRAP_OWNER_FETCH_TIMEOUT_MS, // 30 s
"c2:stale:accountFallback",
);The fallback already silently swallows failures ( |
|
Missing docs: the The new logic in Suggested addition to the
|
|
The account-endpoint fallback for aged-out TWAP UIDs is a good idea, but Compare with if (newTerminal.length > 0) {
await cacheUidStatuses(context, chainId, newTerminal);
}
The fix is straightforward — One secondary point: |
|
Code review — TWAP fallback via /account/{owner}/orders (COW-989)
while (true) {
const response = await fetchWithTimeout(url, undefined, ORDERBOOK_HTTP_TIMEOUT_MS, "ob:account");
// ...
if (page.length < PAGE_LIMIT) break;
offset += page.length;
}Each individual page fetch is independently capped at The result: the outer
The real issue: the outer timeout fires mid-pagination and silently drops results If the outer Recommendation: Pass an aggregate timeout to No blocking bugs. The starvation/data accuracy concern for large owners is pre-existing; this PR does not make it worse and adds the fallback path that didn't exist before. The 10 s outer timeout is correctly chosen for a block handler context. |
Documentation / CI reviewThe This PR adds a silent, partial-failure-tolerant fallback: when This behavior is invisible at the API surface — a caller just sees
Recommended addition to
Recommended addition to
Overall: One actionable item before merge — add a short note to |
|
Review: Account fallback for TWAP parts aged out of /by_uids (COW-989)
In practice, after the stale sweep these UIDs are written to More importantly, the symmetry with No .where(inArray(conditionalOrderGenerator.eventId, generatorIds))
The label
The Logic correctness The fallback result merges into The main actionable item is the missing |
… fallback (COW-989) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
fetchOwnerOrderStatuses(chainId, owner)toorderbookClient.ts— calls/account/{owner}/ordersand returns aMap<uid, OrderStatusInfo>fetchOrderStatusByUidsruns for past-validTocandidates, identify UIDs not returned by the API, resolve the generator owner from the DB, group missed UIDs by owner, and callfetchOwnerOrderStatusesonce per unique owner (withORDERBOOK_HTTP_TIMEOUT_MStimeout)staleStatusesbefore the upsert — preventing fulfilled TWAP parts from being permanently recorded as "expired"Root cause
The CoW Orderbook API's
/orders/by_uidsendpoint has a shorter retention window than/account/{owner}/orders. TWAP parts that were filled close to theirvalidTocan age out of/by_uidsbefore C2's stale sweep processes them. Without the fallback, those parts get written asstatus = "expired"even though they were"fulfilled".Test plan
pnpm typecheckpasses (verified locally)/by_uids→ status used directly (unchanged)/by_uids→ account fallback called, fulfilled status used🤖 Generated with Claude Code