Repository navigation
fix(app): ledger-time expiry, sequential epoch reads, strict network config - #429
luchobonatti wants to merge 5 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Note
Copilot was unable to complete this review at the selected tier due to model policy or plan restrictions.
🟡 Changes recommended
Changes are needed because review findings identify a critical runtime schema-validation bug in networkEnv.ts (incorrect z.enum(Networks) usage) and a time-aging edge case in useAttest.ts where negative elapsed time can corrupt the cached ledger expiry calculation.
2 open issues
What changed in this PR
This pull request fixes three frontend/runtime reliability issues: attestation expiry now derives from ledger time (instead of local wall clock), epoch/epoch-request reads are serialized to avoid RPC bursting, and non-local builds/dev runs fail fast when PUBLIC_STELLAR_* network configuration is missing or invalid.
Changes:
- Compute
expires_atfrom cached/queried ledger time (wall clock only as a last resort). - Fetch epoch and epoch-request
getLedgerEntrieschunks sequentially (max one in flight). - Centralize and enforce strict non-local
PUBLIC_STELLAR_*validation (while preserving localhost fallback for local/unset network) and update.env.example.
| File | Summary |
|---|---|
app/vite.config.ts |
Validates PUBLIC_ network env during Vite config evaluation to fail fast on bad non-local config. |
app/src/hooks/useAttest.ts |
Derives attestation expiry from ledger time (cached + aged, or ledger-time read; wall-clock fallback). Unresolved: cached aging can go negative if system clock moves backward; clamp elapsed ≥ 0 (moderate). |
app/src/hooks/useAttest.test.ts |
Adds tests for cached-ledger-time expiry, aging behavior, and fallback ledger-time read. |
app/.env.example |
Updates mainnet sample network name to PUBLIC. |
app-lib/readContract.ts |
Changes epoch and epoch-request reads to process ledger-entry chunks sequentially instead of in parallel. |
app-lib/readContract.test.ts |
Adds tests asserting chunk serialization (max 1 in-flight) while still returning all epochs. |
app-lib/networkEnv.ts |
Adds shared env parsing/validation for Stellar network configuration with local fallback. Unresolved: z.enum(Networks) is invalid for @stellar/stellar-sdk Networks object; should use z.nativeEnum(Networks) or explicit Object.values(Networks) (critical). |
app-lib/networkEnv.test.ts |
Tests local fallback and non-local failure that names invalid/missing variables. |
app-lib/env.ts |
Switches env handling to the shared parseNetworkEnv implementation. |
This pull request requires changes.
Review effort: Balanced
| "LOCAL", | ||
| "STANDALONE", // deprecated in favor of LOCAL | ||
| ] as const), | ||
| PUBLIC_STELLAR_NETWORK_PASSPHRASE: z.enum(Networks), |
There was a problem hiding this comment.
zod 4 accepts enum-like objects in z.enum; z.nativeEnum is deprecated there. Same line as env.ts on feedback.
| const ledgerTime = | ||
| cached && cachedLedgerTime != null | ||
| ? cachedLedgerTime + | ||
| BigInt(Math.floor((Date.now() - cached.dataUpdatedAt) / 1000)) | ||
| : await readLedgerTime() |


Summary
Closes #416
Closes #417
Closes #418
Three small app fixes: an attestation expiry that depended on the local clock, epoch reads that burst every RPC call at once, and a build that silently pointed testnet or mainnet at localhost.
Changes
expires_atcomes from ledger time: the cached cycle read, aged by the time since it was read, or onegetHealthwhen nothing is cached. Wall clock only if both fail.getLedgerEntrieschunk at a time. Every epoch is still read.PUBLIC_STELLAR_*variables fails and names them. Local, or no network set, still falls back to localhost.Acceptance criteria
useAttestderivesexpires_atfrom ledger time plus the freshness durationexpires_atis still in the futurereadEpochsandreadEpochRequestssend one chunk at a timeTest plan
Automated tests
npx vitest run: 2,280 passed.npm run lint,npm run format:check,npm run typecheck -w app: clean.Manual verification
PUBLIC_STELLAR_NETWORK=TESTNET npm run build -w app: fails withInvalid Stellar network configuration: PUBLIC_STELLAR_NETWORK_PASSPHRASE, PUBLIC_STELLAR_RPC_URL, PUBLIC_STELLAR_HORIZON_URL.npm run build -w appwith no variables: passes.Breaking changes
A non-local build with an incomplete config now fails instead of running against localhost.
.env.example's mainnet sample now saysPUBLIC, the accepted value.Checklist
Screenshots
None.