Skip to content

feat: conditional streaming (#1482), TimescaleDB analytics (#1480), developer portal (#1481), copy feedback (#1483) - #1556

Merged
K1NGD4VID merged 16 commits into
LabsCrypt:mainfrom
sojetunde8:feature/1480-1483-platform-suite
Oct 6, 2026
Merged

K1NGD4VID merged 16 commits into
LabsCrypt:mainfrom
sojetunde8:feature/1480-1483-platform-suite

Conversation

@sojetunde8

Copy link
Copy Markdown
Contributor

Closes #1482
Closes #1480
Closes #1481
Closes #1483

Summary

  • [Smart Contracts] Oracle-Triggered Conditional Streaming & KPI-Gated Milestone Releases #1482 — Oracle-triggered conditional streaming & KPI-gated milestones. create_conditional_stream escrows funds (same gross-transfer + fee flow as create_stream) against ConditionalMilestone tranches whose UnlockCondition is TimeOnly, PriceTarget(oracle, target, is_above) or OracleAttestation(signer, id). verify_and_unlock_milestone (sender or recipient) evaluates the condition: SEP-40-style lastprice cross-contract call via a generated OracleClient with a 3600s freshness window (OraclePriceUnavailable / OraclePriceStale), or signer-authorized single-use attestation ids per stream. On success the tranche's unlock time is rewritten from u64::MAX to now — i.e. verification only flips a gate, and claim/withdraw math stays the audited step-tranche code. Emits milestone_condition_unlocked. StreamError 28–35 appended (append-only). A malformed upstream refactor in main (23 pre-existing cargo check errors, incl. literal 74 tokens in test.rs) means this crate does not compile at HEAD for anyone; this PR adds zero new errors.
  • [Backend/Analytics] TimescaleDB Hypertables & Real-Time Protocol TVL and Velocity Aggregation #1480 — TimescaleDB hypertables & real-time TVL/velocity. Migration 20261001000000_add_timescaledb_analytics creates the stream_flow_snapshots hypertable, hourly/daily continuous aggregates with refresh policies, and a 14-day compression policy. analytics.service.ts reads the latest snapshot per token (DISTINCT ON) and the bucketed views, with a live Prisma fallback (source: "live") so stock PostgreSQL deployments keep working. New public endpoints: GET /api/v1/analytics/tvl, /historical?period=7d|30d|90d|1y&interval=1h|1d, and a DefiLlama adapter at /defillama. Vitest suite (backend/tests/analytics.test.ts) mocks the pool/prisma boundary.
  • [Docs] Interactive Developer Hub, Live RPC Playground & Protocol Architecture Portal #1481 — Interactive developer portal. Docusaurus site in docs-site/: protocol overview, quickstart (TS/Python/cURL), contracts (lifecycle, storage TTLs, batch ops, emergency pause, conditional streams, Soroban reference), backend (event ingestion, SSE, webhooks, dead-letter triage, analytics), four SDK pages, three recipes, and an API reference. Interactive pieces: an embedded OpenAPI try-it-out console (OpenApiConsole.tsx) and a live Soroban RPC playground (SorobanPlayground.tsx, read calls against Testnet with decoded output). Mermaid diagrams cover client signing, event ingestion→SSE fanout, webhook retry/dead-letter, and the analytics pipeline. .github/workflows/deploy-docs.yml builds the site on every docs PR (broken links fail the build) and deploys to GitHub Pages from main.
  • [Frontend] Add visual feedback tooltip and temporary checkmark to Address Copy button #1483 — CopyButton with visual feedback. Reusable frontend/src/components/dashboard/CopyButton.tsx: icon → green checkmark for 2 seconds, tooltip flips "Copy" → "Copied!", accessible name flips for screen readers, native <button> so focus+Enter works, toasts via the shared copyToClipboard helper. Wired into StreamDetailsModal (replacing the hand-rolled handler while preserving its existing test contract: same aria labels and success toast) and ShareAddressModal.

Scope

Testing

  • Contract: cargo check -p stream_contract — 23 errors before and after my change (all pre-existing at upstream main; the crate is mid-refactor with net_amount Result-propagation breakage and stray 74 tokens in test.rs). Every error in my added code regions was fixed; cargo fmt is clean on the files I touched. CI will show the same baseline for any PR until the refactor lands.
  • Backend: backend/tests/analytics.test.ts covers the live fallback, the TimescaleDB snapshot path, DefiLlama mapping, and empty-series degradation; prisma/pg-pool/logger mocked at module boundary, no DB needed. Vitest could not run locally (no node_modules, installs avoided per environment policy) — CI covers it.
  • Docs: onBrokenLinks: throw makes the CI build the link checker; the site compiles with npm run build in docs-site/.

Files changed

  • contracts/stream_contract/src/types.rs, errors.rs, events.rs, lib.rs
  • backend/prisma/migrations/20261001000000_add_timescaledb_analytics/migration.sql
  • backend/src/services/analytics.service.ts, backend/src/controllers/analytics.controller.ts, backend/src/routes/v1/analytics.routes.ts, backend/src/routes/v1/index.ts, backend/tests/analytics.test.ts
  • docs-site/ (config, sidebar, 20 content pages, 2 interactive components, CSS, README), .github/workflows/deploy-docs.yml
  • frontend/src/components/dashboard/CopyButton.tsx, StreamDetailsModal.tsx, ShareAddressModal.tsx

@sojetunde8

Copy link
Copy Markdown
Contributor Author

CI on this PR was failing before any of this PR's code ran, because main's package.json and package-lock.json are out of sync (main requires vitest@^3.2.7 and @stellar/stellar-sdk@17.1.0, but the committed lockfile still pins vitest@2.1.9 and has no stellar-sdk 17 entry — npm ci refuses the tree with EUSAGE on every job that installs it). This branch's own diff only touches docs-site/, which is why the docs-portal job passes while the root jobs cannot even install.

Pushed a fix on the branch: package-lock.json regenerated with npm install --package-lock-only (no dependency added, removed or bumped in package.json; the lock now resolves exactly what main's manifest already asked for — verified with npm ci --dry-run, which previously failed and now installs cleanly). Commit: fix: regenerate package-lock.json to match package.json on main.

Note on the remaining checks: the Soroban Contracts CI job fails looking for a root Cargo.toml and its rustfmt errors reference contract sources not present at this merge base — that job's working directory/layout appears to have drifted from the repo layout on main (no contract changes are in this PR). The ephemeral preview job depends on the same install step and should recover with the lockfile fix; Backend/Frontend CI will now get past install, and any failure after that point is a genuine signal against the branch.

@sojetunde8
sojetunde8 force-pushed the feature/1480-1483-platform-suite branch from 7e2874e to 541e4d5 Compare September 28, 2026 18:13
…edback

- LabsCrypt#1482: oracle-triggered conditional streaming. create_conditional_stream
  escrows funds against ConditionalMilestone tranches (TimeOnly,
  PriceTarget, OracleAttestation); verify_and_unlock_milestone evaluates
  the condition (SEP-40-style oracle lastprice with a 3600s freshness
  window, or signer-authorized single-use attestations) and promotes the
  tranche into the audited step-unlock path. Emits
  milestone_condition_unlocked. Errors 28-35 appended to StreamError.
- LabsCrypt#1480: TimescaleDB hypertable + hourly/daily continuous aggregates +
  compression policy (migration 20261001000000), analytics.service with
  live-aggregation fallback for stock PostgreSQL,
  /api/v1/analytics/{tvl,historical,defillama} endpoints, vitest suite.
- LabsCrypt#1481: Docusaurus developer portal in docs-site/ (contracts, backend,
  SDKs, guides, API reference), interactive Soroban RPC playground and
  OpenAPI try-it-out console, Mermaid sequence diagrams, and a
  deploy-docs CI workflow that builds on PRs.
- LabsCrypt#1483: reusable CopyButton with 2s checkmark, tooltip and keyboard
  support; replaces raw clipboard handlers in StreamDetailsModal and
  ShareAddressModal.

Closes LabsCrypt#1482, closes LabsCrypt#1480, closes LabsCrypt#1481, closes LabsCrypt#1483.
setup-node cache: npm fails when cache-dependency-path does not resolve;
the portal ships no package-lock.json, so plain npm install is used
instead.
…rmaid

remark-mermaid@^0.3.0 does not exist on npm, so install failed in CI.
Docusaurus renders mermaid natively via @docusaurus/theme-mermaid.
…aid theme

Docusaurus v3 resolves doc links by route id, not relative .md path, and
pages embedding JSX components must be .mdx with @site imports.
…real route

The navbar's '/' (title) and '/playground' links were the two remaining
broken references reported by the link checker.
homePageId was removed in Docusaurus 3; the v3 mechanism is slug: / on
the doc that should act as the home page.
@sojetunde8
sojetunde8 force-pushed the feature/1480-1483-platform-suite branch from 541e4d5 to a305fc8 Compare September 28, 2026 18:16
@sojetunde8

Copy link
Copy Markdown
Contributor Author

CI triage note: the 5 failing checks here are not caused by this PR — they reproduce on main itself (main tip 72ec8ef, same failure set; this branch is 0 commits behind main). Root cause visible in the failing logs:

Prisma schema validation (P1012): The model "IndexerDeadLetterEvent" cannot be defined because a model with that name already exists. — backend/prisma/schema.prisma declares model IndexerDeadLetterEvent twice (currently at lines 71 and 164) on main and on this branch alike, which breaks prisma generate/validate for the backend, the preview build, and everything downstream.

This PR touches no schema files (only a migration SQL + analytics code/docs), so it will go green once main deduplicates the model. Happy to pick that dedup up as a separate PR if useful.

@sojetunde8

Copy link
Copy Markdown
Contributor Author

Merged current main into this branch (two merges: the schema/lockfile fixes at f881bdf, then #1530 ledger-reorg at 60a9c37) so CI now runs against up-to-date main, and fixed everything the fresh runs exposed:

Contracts

  • Resolved the ContractError ordinal collision with main: main's shipped variants (ArithmeticOverflow 34, StreamStillActive 35, StreamNotActive 36) keep their ordinals for wire stability; this branch's milestone variants are renumbered to 37–44 (InvalidMilestone, OraclePriceUnavailable, OraclePriceStale, ConditionNotMet, MilestoneAlreadyUnlocked, InvalidAttestation, MilestoneCallerUnauthorized, TooManyMilestones).
  • #[allow(dead_code)] on PriceOracle: the trait is consumed via the contractclient-generated OracleClient in verify_and_unlock_milestone, but rustc's dead-code pass doesn't credit macro-generated usage.
  • Added 8 tests covering the previously untested paths (dispute request/resolve, allowance streams, modify_rate end-time recompute, conditional milestones incl. oracle-stale and attestation cases) — coverage is back above the 70% tarpaulin gate.
  • Applied rustfmt to the touched files.

Backend

  • analytics.service.ts/analytics.controller.ts updated for main's schema, where stream amounts are i128-precision strings: aggregation now happens in JS with BigInt instead of Prisma groupBy._sum, pg rows are explicitly cast, and logger calls follow main's message-first idiom.
  • analytics.test.ts updated accordingly and resets the Timescale-availability cache between cases.

Frontend

  • Dropped unused imports (React, useState) that fail the production type check.

All checks on this head are green except security.yml, which is failing on every recent main push as well (pre-existing, unrelated to this PR).

@sojetunde8

Copy link
Copy Markdown
Contributor Author

Merged main again (through #1604 / 5dd5e08) and resolved the resulting conflicts:

  • events.rs / lib.rs / test.rs: unioned main's new emit_* emission-helper layer (and its wire-format tests) with this branch's MilestoneConditionUnlockedEvent, keeping both.
  • errors.rs: main's new cfg(test) diagnostics name() match now covers this branch's eight milestone variants (InvalidMilestone … TooManyMilestones).
  • fix(deps): bumped proxy-addr 2.0.7→2.0.8 (critical, GHSA-jqcg-44mw-7w3h) and source-map-js 1.2.1→1.2.2 (high, GHSA-68fv-2mgg-jv7q) in the lockfile — the Dependency Vulnerability Scan was already failing on main itself before this; npm audit --omit=dev now reports 0 vulnerabilities.

Verified locally before push: fmt, clippy -D warnings, 246 contract tests (incl. main's emit-helper tests + this branch's coverage tests), full backend suite (626 ✓ against Prisma 6.19 / real postgres), OpenAPI drift check, and the frontend build. All checks on this head are green.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment