#476 B043: [ENHANCEMENT] [ANCHORS] Per-anchor timeout + retry tuning …#616
Conversation
|
@madisonsc52-del is attempting to deploy a commit to the ezedikeevan's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@madisonsc52-del 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.
This PR includes package-lock.json in the diff. Lockfile changes are not allowed from contributors — the lockfile is owned by CI. Please close this PR, start fresh from a clean branch off main (without running npm install in a way that modifies the lockfile), and resubmit with only the intended changes.
…etry tuning in server-rates FIXED
3d10957 to
8d2a764
Compare
|
Please review |
ezedike-evan
left a comment
There was a problem hiding this comment.
Thanks for the update @madisonsc52-del — but the latest commit still includes package-lock.json with 12903 line deletions. The lockfile must not be modified by contributors; please remove it from this branch. Start from a clean branch off main without running npm operations that touch the lockfile, and push only the intended source files (lib/stellar/server-rates.ts, tests/server-rates.timeout.spec.ts, .env.example).
…odule Extract KNOWN_STATUSES and normalizeStatus from sep24.ts and sep6.ts into the shared sep24-status-map module. Both consumers now import the shared helpers, eliminating the duplicate status sets. Closes ezedike-evan#450 Co-authored-by: Chidimj <chidimj@users.noreply.github.com>
SEP-31 detection and the per-anchor capabilities.sep31 flag already land in resolveAnchor output (PR ezedike-evan#575) and the SEP compliance matrix doc, but the AnchorCard DISPLAYED_SEPS list still omitted sep31, so the detected per-anchor flag never showed in the anchor grid. Add sep31 to the displayed SEP set and its label, plus an AnchorCard test covering the badge. Co-authored-by: chizzy0011 <chisomnteh@gmail.com>
* feat(sep6): wire SEP-6 as Tier-3 fallback in fetchCorridorRates * fix: add USDC_ASSET import and handle sep6-fee in QuotePill --------- Co-authored-by: Johnalex-hub <johnalex-hub@users.noreply.github.com>
* feat(sep6): dynamic KYC field-form schema from withdraw fields (B015) Maps Sep6WithdrawNeedsInfo field descriptors to typed form fields with zod validators. Text inputs for plain strings, select for fields with choices, optional flag drives whether z.string().optional() or z.string().min(1) is used. buildSep6FormSchema returns field metadata and a combined ZodObject for client-side validation. 10 tests cover field type mapping, required vs optional, enum validation, and full schema parse. * style: fix Prettier formatting in sep6-form.ts --------- Co-authored-by: Johnalex-hub <johnalex-hub@users.noreply.github.com>
* feat: display 'Firm quotes' badge for SEP-38 capable anchors - Update AnchorCard UI to show 'Firm quotes' instead of 'SEP-38' - SEP-38 capability detection already implemented in lib/stellar/sep1.ts - Detection reads ANCHOR_QUOTE_SERVER from anchor stellar.toml - Capability automatically appears in anchor.seps array when quote server present Resolves ezedike-evan#480 * chore: trigger CI workflows * chore: re-trigger CI workflows after enabling Actions * test(ui): expect Firm quotes label for sep38 capability badge --------- Co-authored-by: ezedike-evan <210902543@live.unilag.edu.ng>
…#631) * feat(sep6): implement SEP-6 withdraw flow state machine Pure reducer modelling the SEP-6 withdraw lifecycle with typed states and events. No side effects inside the reducer. Table-driven tests cover all valid transitions and illegal no-op transitions. Closes ezedike-evan#451 * style: apply Prettier formatting to sep6-machine.ts and sep6-machine.spec.ts --------- Co-authored-by: Chidimj <chidimj@users.noreply.github.com>
4342ac4 to
76af3c6
Compare
|
@ezedike-evan |
Here is the completed PR template for the fix.
Summary
Replaced the coarse fixed 8 s per-anchor timeout in the server-side rate path with config-driven per-tier timeouts and retries. Each idempotent read (TOML resolution, SEP-38
/price, SEP-24/info) now has its own timeout budget and is retried once on transient network errors, while deterministic 4xx responses are not retried.Linked issue
Fixes B043
Changes
lib/stellar/server-rates.ts:30— AddedServerRatesConfigand exportedserverRatesConfig, reading per-tier timeouts and retry counts from environment variables with safe fallback parsing.lib/stellar/server-rates.ts:72— AddedisNetworkErrorto classify transient failures (5xx, 408, network-level errors, timeouts) and exclude deterministic 4xx.lib/stellar/server-rates.ts:97— AddedwithTimeoutRetry, which enforces a hard per-attempt deadline and retries only on network errors.lib/stellar/server-rates.ts:149— WrappedgetSep38Pricecalls inwithTimeoutRetryusingserverRatesConfig.sep38.lib/stellar/server-rates.ts:190— WrappedgetSep24InfoinwithTimeoutRetryusingserverRatesConfig.sep24Info.lib/stellar/server-rates.ts:320— WrappedresolveAnchorinwithTimeoutRetryusingserverRatesConfig.toml..env.example— Documented the newRATES_*environment variables.tests/server-rates.timeout.spec.ts— Added 12 tests covering tiered config, network-error retry, 4xx no-retry, 5xx retry, and timeout behavior.Findings
A single fixed timeout (8s) was used across all server-side rate fetch operations.
Applied uniformly to:
No retry mechanism existed—any transient failure caused immediate failure.
The
withTimeouthelper only enforced deadlines:Result: fragile rate fetching, especially under network instability or temporary anchor issues.
Root Cause
Fix Features
Config-Driven Tiered Timeouts
Introduced
ServerRatesConfigwith per-tier settings:toml,sep38,sep24InfoEach tier has:
timeoutMsretryAttemptsConfigurable via environment variables with safe fallbacks
Retry-on-Transient-Error Wrapper
Added
withTimeoutRetry:Error Classification
Implemented
isNetworkError:Retries:
No retries for:
Applied Across All Tiers
Retry + timeout logic added to:
/price/infoBackward Compatibility
Defaults preserve prior behavior:
No breaking changes for existing deployments
Per-Attempt Timeout Model
Behavioral Improvements
Additional Findings
Retry is applied per SEP context, preserving fallback efficiency
Existing per-anchor isolation remains intact (failures don’t cascade)
Change is server-side only, with:
Final Summary
Testing notes
Automated
npm run typecheck· ✅ greennpm run lint· ✅ greennpm run format:check· ✅ greennpm run test· ✅ green —952 passed,1 skippednpm run build· ✅ green (with required env vars)New / modified tests
tests/server-rates.timeout.spec.ts— 12 new tests:/inforecovers after one network-error retry and does not retry 4xx.tests/server-rates.degrade.spec.ts— existing 3 tests still pass; no regression in per-anchor degradation.Manual verification
N/A — pure backend change; all anchor interactions are mocked in tests.
Screenshots / recordings
N/A — no user-visible change.
Checklist
Correctness
npm run typecheckpassesnpm run lintpasses with zero new warnings (we run--max-warnings 0in CI)npm run testpasses; new behaviour has a testnpm run buildpassesData integrity
isMock,// MOCK,// TODO: replace with real data, or commented-out real codestellar.tomlis publicly resolvable — N/A, no anchor metadata changedAbortControllertimeout is intact on anchor fetches — N/A,sep24.tsunchangedSecurity & non-custody
.env.localis unchanged; new env vars are added to.env.exampleDocs
CHANGELOG.mdentry under[Unreleased]— N/A, internal timeout policy onlydocs/*.mdupdated — N/A, no API/schema changedocs/ARCHITECTURE.mdupdated — N/A, no architecture change.env.exampleupdatedRelease hygiene
[ ]indocs/ROADMAP.mdis updated — N/A, not a wave deliverableBreaking changes
None.
For reviewers
CLOSE #476