Dedupe anchors returning the same quote#284
Conversation
…o-dismiss bottom sheet functionality
…tion and automatic retry logic
…based on earliest timestamp
|
@githoboman is attempting to deploy a commit to the ezedikeevan's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@githoboman Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
ezedike-evan
left a comment
There was a problem hiding this comment.
Thanks @githoboman — the dedupe primitive (dedupeByQuoteId in lib/stellar/rates-engine.ts) and its 8 tests in tests/rates-dedupe.spec.ts) are exactly right for #175: map-keyed by quoteId, earliest-received wins on collision, quoteId-less rates pass through, order preserved. The logic and tests are solid.
I cannot merge this PR as-is because it bundles changes that belong to different tickets.
What's in scope for #175 (2–3 files):
lib/stellar/rates-engine.ts— the dedupe functiontests/rates-dedupe.spec.ts— the collision teststypes/index.ts(quoteId?: stringonAnchorRate) — the field the dedupe keys on (acceptable here)
What's bundled in that doesn't belong:
app/globals.css— mobile bottom-sheet swipe-to-dismiss styles. Not related to rate deduplication.components/offramp/ExecuteDrawer.tsx— swipe-to-dismiss touch handlers + scroll-lockuseEffect. Unrelated to rates.tests/sep38-auth.spec.ts— SEP-38 JWT auth/re-auth test suite. Not scoped to #175.
The PR description itself notes the contributor hasn't wired dedupeByQuoteId into computeRateComparison yet — that's fine for this ticket, the primitive + test is the stated scope.
How to fix:
- Strip
app/globals.css,components/offramp/ExecuteDrawer.tsx, andtests/sep38-auth.spec.tsout of this branch. - Keep
lib/stellar/rates-engine.ts,tests/rates-dedupe.spec.ts, and thetypes/index.tschange. - Push the cleaned branch — this will be ready to merge immediately.
(The swipe-to-dismiss and sep38-auth work should live in their own focused PRs.)
…based on earliest timestamp
…github.com/githoboman/stellar-intel into dedupe-anchors-returning-the-same-quote-id
Result lib/stellar/rates-engine.ts — the dedupe primitive How: Each concern was already its own commit, so this was clean — I reset the branch to main and cherry-picked only the dedupe commit (58b9e12). No content changed; the in-scope commit applied verbatim (new SHA 4072a60 from the rebase onto main). Nothing lost: the full original branch is preserved at backup/dedupe-anchors-full (all 3 commits), so the SEP-38 auth work (b2657a2) and the ExecuteDrawer swipe-to-dismiss work (0a3ecca) are intact and ready to be lifted into their own focused PRs. |
|
Still bundling three unrelated changesets. The dedupe primitive ( |
Summary
The ticket named lib/stellar/rates-engine.ts, but that file didn't exist — the actual rate aggregation lives in computeRateComparison (sep24.ts:359), and AnchorRate had no quote-id field to dedupe on. So I created the module the ticket assumed, plus the field needed to carry SEP-38 quote ids.
Changes (3 files):
Closes #175
types/index.ts — added optional quoteId?: string to AnchorRate, populated from SEP-38 firm quotes. Optional, so no existing AnchorRate construction breaks.
lib/stellar/rates-engine.ts (new) — dedupeByQuoteId(rates):
Map-based dedupe keyed by quoteId.
On collision, earliest-received wins (smallest updatedAt); updatedAt ties keep the incumbent, so input order breaks them.
Rates without a quoteId (SEP-24 fees, unavailable placeholders) can't collide and always pass through.
Original order preserved; a collapsed group is emitted at its first appearance.
tests/rates-dedupe.spec.ts (new) — 8 tests with synthetic collisions: two-anchor collapse, order-independence of earliest-received, distinct ids preserved, three-way collision, quoteId-less passthrough, order preservation, tie-breaking, empty input.
Verification:
New test: 8/8 passing.
Related suites (rate-ranking, compute-total, types): 22/22 passing.
ESLint clean on both new files.
One note: the pre-existing tsc --noEmit errors in sep10-state, sep24-asset-format, and sep24-withdraw test files are unrelated to this change (they're about Networks properties, argument counts, and Sep1TomlData shape) and were already failing before I touched anything.
I haven't wired dedupeByQuoteId into computeRateComparison yet — the ticket scoped this to the dedupe primitive + test. If you want it applied in the live aggregation path (dedupe before picking bestRateId), say the word and I'll hook it in.