Skip to content

Soroban contract integration health checks and Stellar provider dependency graph - #1074

Merged
mijinummi merged 1 commit into
MDTechLabs:mainfrom
Cybermaxi7:feat/contract-health-and-provider-dependency-graph
Aug 28, 2026
Merged

Soroban contract integration health checks and Stellar provider dependency graph#1074
mijinummi merged 1 commit into
MDTechLabs:mainfrom
Cybermaxi7:feat/contract-health-and-provider-dependency-graph

Conversation

@Cybermaxi7

Copy link
Copy Markdown
Contributor

Closes #1067
Closes #1068

60 new tests, all passing. pnpm run build green. Both features are new directories — no existing source file is touched.


#1067 — Soroban contract integration health

src/contracts/health/soroban/ runs four checks in order, because each is only meaningful if the previous one passed:

Check Question
Availability Is the contract there at all?
Network Did the expected network answer?
Interface Are the methods the integration calls actually present?
Read Do safe reads succeed, and return something sensible?

Three decisions worth a reviewer's eye:

When the contract is absent, the later checks are skipped rather than failed. Reporting "interface check failed" for a contract that doesn't exist buries the one fact that matters. Each skip records why it was skipped, so nothing looks silently unrun.

A wrong network is unhealthy, not a warning. A contract answering from testnet when the integration is configured for mainnet is worse than one that doesn't answer — the integration looks fine while reading someone else's state, and everything downstream trusts it.

Severity is graded, not binary. A missing method or a wrong network means the integration cannot work → unhealthy. A failing read on an otherwise correct contract → degraded: the wiring is right and the fault may well be transient. Those warrant different responses, and collapsing them loses the distinction.

Every probe is bounded by a timeout. An integration that never answers is not healthy, and without a bound the health check would hang along with it — there are tests for a hanging availability probe and a hanging read.

readProbes accept an optional expect assertion, because a read that returns something is weaker evidence than a read that returns something sensible — a contract can answer while being wired to the wrong asset.

Monitoring

src/monitoring/contracts/ aggregates results and keeps a short history. History matters: a single failing check cannot tell an RPC blip from an integration that's been broken since deploy, and isPersistentlyFailing is exactly that distinction.

  • A sweep where one contract throws yields unknown for that one rather than failing the sweep — one unreachable integration must not hide the status of the others.
  • An empty monitor reports unknown, not healthy. Saying "healthy" when nothing is registered would hide a misconfiguration where the contracts were never wired up.

#1068 — Stellar bridge provider dependency graph

src/providers/dependencies/stellar/ models what each provider needs — RPC, Horizon, contracts, liquidity sources, APIs — and derives provider health from it.

The problem is attribution. The symptom is "provider X is down"; the cause is usually one shared RPC endpoint or price API sitting underneath several providers. The graph turns that from an investigation into a lookup: record the dependency unhealthy once, and every dependent provider reports the reason rather than a bare failure.

The grading is the substance of the model:

  • a critical dependency unhealthy → provider unhealthy; it cannot serve
  • a critical dependency degraded, or a non-critical one unhealthy → provider degraded; it serves, worse
  • a critical dependency that has never reportedunknown

That last case is deliberate. Claiming health for something never checked is how a dashboard ends up lying, so healthyProviderIds excludes unknown providers rather than handing them traffic.

"Critical" here means the provider cannot serve without it — not merely "important". A price API going down degrades quote quality; an RPC endpoint going down stops the provider dead, and reporting those identically makes the signal useless.

Two things that fall out of the model:

  • A provider declaring an unregistered dependency is rejected at registration. It would otherwise have nothing to check and silently report healthy — the worst possible failure for a health system.
  • impactOf answers "is this endpoint safe to take out of rotation?" without recording a failure first.

src/providers/health/ rolls this into a fleet view. rootCauses groups failures by the dependency responsible, widest blast radius first: five providers failing for one reason is one problem, not five, and that's the view an operator actually wants at 3am.


Verification

pnpm exec jest tests/contracts tests/providers    60 passed
pnpm run build                                    green  (this is CI's gate)
eslint on every new src file                      clean
tsc --noEmit                                      clean

Two notes for the maintainers

node_modules is tracked in this repository — 13,336 files. Installing dependencies locally modifies or restructures thousands of them, which makes git add -A actively dangerous here. Only the 13 source and test files are in this commit; nothing under node_modules is included. Worth .gitignore-ing separately, but that's a large, disruptive change and not mine to make inside a feature PR.

CI doesn't run the TypeScript tests. The workflow does pnpm install, pnpm run build, then cargo test — so jest never runs on a PR, and neither these 60 tests nor any existing suite gates a merge. Adding pnpm test to that job would be a one-line change; happy to open it separately.

Separately, and unrelated to this PR: the root pnpm-lock.yaml is lockfileVersion: 6.0 (pnpm 8 format) while packageManager pins pnpm@10.30.2. Locally, pnpm 10 refuses it with ERR_PNPM_LOCKFILE_BREAKING_CHANGE under --frozen-lockfile; CI resolves a version that accepts it, so this isn't breaking your pipeline today, but a contributor following packageManager will hit it. I left the lockfile untouched rather than regenerate it into this PR.

…graph

Closes MDTechLabs#1067 and MDTechLabs#1068.

60 new tests, all passing. Both features are new directories — no existing
source file is touched.

## MDTechLabs#1067 — Soroban contract integration health

`src/contracts/health/soroban/` runs four checks in order, because each is
only meaningful if the previous one passed:

1. **Availability** — is the contract there?
2. **Network** — did the *expected* network answer?
3. **Interface** — are the methods the integration calls actually present?
4. **Read** — do safe reads succeed, and return something sensible?

Three decisions worth review:

**When the contract is absent, the later checks are skipped rather than
failed.** Reporting "interface check failed" for a contract that does not
exist buries the one fact that matters, and each skip records why.

**A wrong network is `unhealthy`, not a warning.** A contract answering from
testnet when the integration is configured for mainnet is worse than one that
does not answer at all — the integration looks fine while reading someone
else's state.

**Severity is graded rather than binary.** A missing method or a wrong network
means the integration cannot work, so `unhealthy`. A failing read on an
otherwise correct contract is `degraded` — the wiring is right and the fault
may be transient, and those warrant different responses.

Every probe is bounded by a timeout. An integration that never answers is not
healthy, and without a bound the health check would hang along with it.

`src/monitoring/contracts/` aggregates results across integrations and keeps a
short history, because one failing check cannot distinguish an RPC blip from
an integration broken since deploy. `isPersistentlyFailing` is that
distinction. A sweep that throws for one contract yields `unknown` for that
one rather than failing the sweep — one unreachable integration must not hide
the status of the others. An empty monitor reports `unknown`, not `healthy`:
saying "healthy" when nothing is registered would hide a misconfiguration.

## MDTechLabs#1068 — Stellar bridge provider dependency graph

`src/providers/dependencies/stellar/` models what each provider needs — RPC,
Horizon, contracts, liquidity sources, APIs — and derives provider health from
it.

The problem is attribution. The symptom is "provider X is down"; the cause is
usually one shared RPC endpoint or price API sitting underneath several
providers. The graph makes that a lookup rather than an investigation: record
the dependency unhealthy once and every dependent provider reports the reason
rather than a bare failure.

Grading, which is the point of the model:

- a **critical** dependency unhealthy → provider **unhealthy**; it cannot serve
- a critical dependency degraded, or a **non-critical** one unhealthy →
  provider **degraded**; it serves, worse
- a critical dependency that has never reported → **unknown**

That last one is deliberate. Claiming health for something never checked is
how a dashboard ends up lying, so `healthyProviderIds` excludes unknown
providers rather than handing them traffic.

A provider declaring a dependency that is not registered is rejected at
registration — it would otherwise have nothing to check and silently report
healthy.

`impactOf` answers "is this endpoint safe to take out of rotation?" without
recording a failure first.

`src/providers/health/` rolls this into a fleet view whose `rootCauses` groups
failures by the dependency responsible, widest blast radius first: five
providers failing for one reason is one problem, not five.

## Verification

    pnpm exec jest tests/contracts tests/providers    60 passed
    pnpm run build                                    green (CI's gate)
    eslint on every new src file                      clean
    tsc --noEmit                                      clean

Note on staging: `node_modules` is tracked in this repository (13,336 files),
and installing dependencies locally modifies thousands of them. Only the 13
files above are staged; nothing under `node_modules` is included.
@drips-wave

drips-wave Bot commented Aug 28, 2026

Copy link
Copy Markdown

@Cybermaxi7 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! 🚀

Learn more about application limits

@mijinummi
mijinummi merged commit dbe1b31 into MDTechLabs:main Aug 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Stellar Bridge Provider Dependency Graph Implement Soroban Contract Integration Health Check

2 participants