Repository navigation
feat: subgraph retry with backoff, split validation, immutable query cache & safe event parsing (Closes #277, #278, #279, #280) - #476
Merged
Cjay-Cyber-2 merged 1 commit intoOct 22, 2026
Conversation
… safe event parsing Implements the four assigned Stellar Wave issues in one change: - ASTROIDX556#280: exponential backoff retry helper with configurable attempts and jitter (retryWithBackoff), transient-error classification (isTransientNetworkError: 5xx/network timeouts retryable, 4xx and GraphQL errors fail fast), and executeSubgraphQuery wrapping subgraph reads with the retry policy. - ASTROIDX556#277: split configuration validation (split-configuration.schema) rejecting empty splits, duplicate receivers, malformed addresses and weight totals beyond the precision limit, with descriptive ValidationException details. - ASTROIDX556#278: bounded in-memory TtlCache (TTL + LRU eviction, bypass option, hit/miss stats) wired into executeSubgraphQuery as an opt-in cache for immutable metadata reads. - ASTROIDX556#279: defensive parseContractEventLogs skipping malformed contract event logs with warnings, integrated into both simulation services so one bad log never aborts batch processing. Closes ASTROIDX556#277, closes ASTROIDX556#278, closes ASTROIDX556#279, closes ASTROIDX556#280 Generated with Codebuff 🤖 Co-Authored-By: Codebuff <noreply@codebuff.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Single PR delivering all four issues assigned to @graceshaba93 for the Stellar Wave (10th wave). Each issue is described and verified below; the change set is utility-first, follows the repo's module conventions, and ships unit tests for every new behaviour.
#277 — Add input validation for split configurations and receiver weights
Malformed split configurations with invalid receiver weights or duplicate addresses can lead to unexpected transaction reverts on-chain. Validation now runs before any split payload is built so invalid configurations never reach the submission stage.
Implemented
src/common/validators/split-configuration.schema.tssplitReceiverSchema— Stellar account address (G…/M…, full checksum validation via the existingstellarPublicKeySchema) + integer weight (> 0, ≤ precision limit).splitConfigurationSchema— rejects empty splits; flags duplicate receiver addresses with a descriptive message including the offending address and its index; rejects weight totals aboveMAX_SPLIT_WEIGHT_TOTAL(10⁷, so a full split maps onto Stellar's 7-decimal stroop precision).validateSplitConfiguration(input)— dedicated validation function returning typed data or throwing the canonicalValidationExceptionwith structuredValidationErrorDetail[].src/common/validators/index.ts.Acceptance criteria
#278 — Implement caching layer for immutable stream metadata queries
Repeatedly querying immutable metadata strains external subgraph endpoints. An in-memory, bounded cache now serves immutable reads directly from the query layer.
Implemented
src/utils/ttl-cache.util.ts—TtlCachewith per-entry TTL, size-bounded LRU eviction (maxEntries, least-recently-used evicted first, so memory can never leak), hit/miss stats for observability, injectable clock for deterministic tests, andgetOrSet(key, loader, { bypass, ttlMs }).bypass: trueskips the cache read and refreshes the entry with fresh data.src/utils/subgraph-query.util.ts): opt-in viacacheTtlMs(only for immutable reads), keyed byurl + query + variables, withbypassCacheto force fresh data. Only successful responses are cached; the cache is bounded (250 entries shared, or inject a customTtlCache).Acceptance criteria
executeSubgraphQuery)#279 — Refactor event parsing utilities to handle malformed log payloads safely
A single malformed contract event log (missing
topic, null payload, corrupted object) could throw during parsing and abort batch processing of otherwise valid events.Implemented
src/integrations/stellar/contract-event.parser.ts—parseContractEventLogs(logs, logger?)warnper entry (index+ reason) and continues parsing the rest of the batch.eventsfield) yields[]; valid entries are returned unchanged, in order, with the exactSorobanContractEventtype.SorobanSimulationService,StellarSimulationService): events are parsed defensively before risk scoring and before being returned, soeventCountonly counts well-formed logs and the response keeps its exact shape.Acceptance criteria
#280 — Add retry mechanism with exponential backoff for transient subgraph queries
Temporary subgraph outages or rate limits caused queries to fail unnecessarily.
Implemented
src/utils/retry.util.tsisTransientNetworkError(error)— classifies failures by walking thecausechain: 5xx responses and transport errors (ECONNRESET,ETIMEDOUT,ECONNABORTED, undici timeouts, …) are retryable; 4xx responses, GraphQL execution errors (retryable: false) and deterministic failures fail immediately without retrying.retryWithBackoff(fn, options)— configurablemaxAttempts,baseDelayMs,maxDelayMscap,isRetryablepredicate,onRetryhook; exponential backoff with jitter via the existingexponentialBackoffWithJitter(src/utils/backoff.util.ts); no sleep after the final attempt.src/utils/subgraph-query.util.ts—executeSubgraphQueryapplies the retry wrapper to subgraph executions (injectablefetchImplfor tests); idempotent reads only.Acceptance criteria
Testing & Validation
All run locally against this branch:
npm run typechecknpm run lintnpm testnpm run docs:checknpm run db:verifyNew/updated test files:
split-configuration.schema.spec.ts,ttl-cache.util.spec.ts,subgraph-query.util.spec.ts,retry.util.spec.ts,contract-event.parser.spec.ts,soroban-simulation.service.spec.ts,stellar-simulation.service.spec.ts.No database migrations, no new endpoints, no dependency changes. Branch is rebased on the latest
main— no conflicts.Closes #277
Closes #278
Closes #279
Closes #280