Skip to content

fix(web): handle archived bindings gracefully and add restore workflow (#186) - #344

Merged
blockchain-maxis merged 3 commits into
blockchain-maxis:mainfrom
Lazyartist1:fix/handle-bindings-archive-restore-186
Sep 2, 2026
Merged

fix(web): handle archived bindings gracefully and add restore workflow (#186)#344
blockchain-maxis merged 3 commits into
blockchain-maxis:mainfrom
Lazyartist1:fix/handle-bindings-archive-restore-186

Conversation

@Lazyartist1

Copy link
Copy Markdown
Contributor

Closes #186

Summary of Changes

Prevents handle profile 404s caused by Soroban persistent storage entry archival (~30 days of inactivity) by detecting restorePreamble, providing graceful archival state handling, adding client restoration helpers, and supplying an operator keep-alive sweep tool.

Key Changes

  1. Archival Detection & Read Handling:

    • apps/web/lib/server/registry-read.ts:
      • Added simulateReadDetailed and resolveHandleDetailed to detect cold storage restorePreamble in RPC simulation responses.
    • apps/web/lib/profiles.ts:
      • Enhanced safeChainProfile to return an archived profile state rather than null when an entry is in cold storage, preventing /p/{handle} from returning a 404.
  2. On-Chain Restoration Workflow:

    • apps/web/lib/registry.ts:
      • Added restoreHandleBinding(handle, walletAddress) helper to simulate, build, and submit a RestoreFootprint transaction signed by the user's wallet.
  3. Operator Tooling & Keep-Alive Sweep:

    • scripts/keepalive-contract.mjs:
      • Automated sweep tool to simulate view calls across known handles, refreshing contract instance and persistent storage TTL before reaching the archival threshold.
  4. Documentation & Runbook:

    • docs/ARCHIVAL_AND_RESTORATION.md:
      • Complete documentation of Soroban's ~30-day TTL storage lifecycle, simulation responses, client/CLI restoration commands, and keep-alive cron usage.
    • docs/TROUBLESHOOTING.md:
      • Added Section 8 covering troubleshooting for archived bindings.

Verification Status

  • Unit Tests: 23/23 tests in apps/web/lib/server/registry-read.test.ts passing (including live, archived, unbound, and unconfigured checks).
  • Docs Check: node scripts/check-docs.mjs passed cleanly (23 markdown files, 27 env vars, no drift).
  • Contract Error Check: node scripts/check-contract-errors.mjs passed.

@drips-wave

drips-wave Bot commented Aug 30, 2026

Copy link
Copy Markdown

@Lazyartist1 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

@vercel

vercel Bot commented Aug 30, 2026

Copy link
Copy Markdown

@Ipramking is attempting to deploy a commit to the blockchainmaxis-8449's projects Team on Vercel.

A member of the Team first needs to authorize it.

@netlify

netlify Bot commented Aug 30, 2026

Copy link
Copy Markdown

Deploy Preview for stellar-signet ready!

Name Link
🔨 Latest commit bb407ec
🔍 Latest deploy log https://app.netlify.com/projects/stellar-signet/deploys/6a980edb7532160008c56d99
😎 Deploy Preview https://deploy-preview-344--stellar-signet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@Lazyartist1
Lazyartist1 force-pushed the fix/handle-bindings-archive-restore-186 branch from 2b3cdce to 09cd458 Compare August 30, 2026 16:10
Three problems, the first two of which stopped this from building or working.

1. rpc.Api.isSimulationRestorePreamble does not exist. The SDK's guard is
   isSimulationRestore. `pnpm typecheck` failed on it:

     lib/profiles.ts(368,15): error TS2551: Property
     'isSimulationRestorePreamble' does not exist on type 'typeof Api'.

   It was called in three places (profiles.ts, registry.ts,
   scripts/keepalive-contract.mjs), each with a hand-rolled
   `'restorePreamble' in sim` fallback beside it, so the mistake was masked
   rather than surfaced. The SDK guard is stricter in the way that matters —
   it also requires the preamble to carry `transactionData`, and a preamble
   without that names nothing to restore. Dropped the fallbacks and the
   `as any` casts with them.

2. restoreHandleBinding submitted a restore that restores nothing. It built
   `Operation.restoreFootprint({})` and never touched `sim.restorePreamble`,
   so the transaction carried an empty footprint. The preamble is exactly
   where the network reports what to restore: its `transactionData` is the
   footprint and `minResourceFee` the cost. The transaction now adopts both
   via setSorobanData, and pays BASE_FEE + minResourceFee. Also replaced
   `const sdk: any = await import(...)` with a typed destructured import.

3. The archived-detection test used a fixture the RPC never returns — only a
   `restorePreamble`, with no top-level `transactionData`. An archived read
   is a *successful* simulation (the network answers as if the entry were
   live) that additionally carries the preamble, which is why the correct
   guard rejected the stub. Fixture corrected, plus an inverse test asserting
   a healthy read is never reported as archived.

Also stopped putting a user-facing sentence in the archived profile's `bio`;
the `archived` flag is the signal, and `bio` is a developer's own text.

256/256 web tests pass; typecheck, lint, build and check-docs clean.

Note: the restore path itself is not exercised against a genuinely archived
entry — that needs an entry left untouched past the ~30 day TTL — so it is
verified by construction against the SDK's types, not end to end.
@blockchain-maxis
blockchain-maxis merged commit da0646e into blockchain-maxis:main Sep 2, 2026
10 of 11 checks passed
blockchain-maxis added a commit to kaylachi/signet that referenced this pull request Sep 2, 2026
…essage

Merge resolution: main reformatted the TROUBLESHOOTING table (prettier, via
blockchain-maxis#344), so took main's formatting and reapplied this branch's wording change to
the one affected cell.

The PR changed the status message and its e2e assertion, but the same false
claim was left in four other places, which is the thing issue blockchain-maxis#218 is actually
about — the copy asserting the contract is not deployed when it is:

- docs/TROUBLESHOOTING.md §6 still said 'the Phase 2 message is intentional'
  and 'unset → Phase 2 copy';
- docs/DEPLOYMENT.md's verification table said 'UI shows Phase 2';
- README.md said the UI 'shows an honest "Phase 2" message';
- the e2e test was still named '…shows the honest Phase 2 state'.

All now describe the real condition: the deployment is not configured against a
registry. The genuine roadmap uses of 'Phase 2' (README's 'What's coming next',
the docs page) are untouched — those are about project phases, not this error.

check-docs and the web build pass. Locally the unconfigured e2e case cannot run
— my .env bakes NEXT_PUBLIC_IDENTITY_REGISTRY_ID into the build, so the
not-configured path never renders; that is the 'build and shell disagree' case
the test's own comment describes, and it skips correctly once the shell env
matches. CI builds without the id, so it exercises the real path there.
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.

Handle bindings archive after ~30 days of no access and the profile 404s

2 participants