Skip to content

feat(server): add read-only Soroban RPC ledger adapter - #86

Merged
TOMOKI977 merged 9 commits into
mainfrom
fix/server-soroban-rpc-adapter
Oct 5, 2026
Merged

TOMOKI977 merged 9 commits into
mainfrom
fix/server-soroban-rpc-adapter

Conversation

@moises-cisneros

Copy link
Copy Markdown
Contributor

Closes #85

Stacked on #84 (base is that PR's branch; retarget to main after #84 merges).

Summary

Adds a read-only Soroban RPC adapter in puls3_server/lib/src/ledger/ that implements the domain LedgerPort (agentWallet, findPayment) and exposes registry reads (agentExists, agentUri) and the escrow get_job read. It talks plain JSON-RPC over an injected http.Client, builds unsigned invoke envelopes with a small in-repo XDR encoder, and decodes xdrFormat: "json" results. No signing, no broadcast, and it is not wired into server.dart yet.

Acceptance criteria

  • Read-only adapter (simulateTransaction, getTransaction) implementing LedgerPort.
  • Registry reads and escrow get_job against the deployed testnet contracts (recorded as fixtures).
  • Config from PULS3_STELLAR_* env vars with a testnet default, plus a drift test against contracts/deployments/testnet.json (contract ids).
  • Offline unit tests from recorded fixtures; not wired into server.dart.

Verification evidence

cd puls3_server
dart test test/unit              -> 98 passed
dart analyze --fatal-infos       -> No issues found
  • The encoder output is compared byte for byte with stellar contract invoke --send=no --build-only.
  • Fixtures were recorded read-only from soroban-testnet; simulateTransaction of agent_exists(7) returns {"bool":true} and getTransaction for the direct payment 652a575b…31ab returns SUCCESS with the expected transfer event (to_muxed_id 8, amount 5000000).

Notes for reviewers

  • Size is above the 400-line budget (fixtures and tests included). Requesting size:exception; the adapter is one self-contained unit and the commits are ordered for review.
  • The adapter only checks status, the configured SAC id, the transfer topic, and the muxed id and amount ranges. Comparing wallet, amount and hire id against the hire happens in the domain (Payment.settles).
  • LedgerUnavailable is thrown on transport/RPC errors and archived state; NOT_FOUND returns null. The RPC keeps transactions for about 7 days, so the hire flow must persist the verified Payment.
  • Root pubspec.lock is untouched (http is already locked transitively). A local Dart older than the lock's SDK rewrites it, so revert it before committing.
  • The RPC timeout is a required constructor argument; whoever wires the adapter in picks the value.

@moises-cisneros moises-cisneros added area: backend Serverpod endpoints and persistence type: feat New functionality labels Oct 4, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Deploying puls3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: b4fe552
Status:⚡️  Build in progress...

View logs

@TOMOKI977 TOMOKI977 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Buen adapter: los lectores de sc_val_json.dart fallan de forma explícita con LedgerUnavailable y la cobertura de casos de error es sólida. Dejo algunos ajustes antes de mergear:

  • StellarConfig (stellar_config.dart:41-56) usa valores de testnet cuando falta una variable PULS3_STELLAR_*. Un deploy a otra red con una variable olvidada verificaría pagos contra contratos de testnet sin ningún error. Sugiero fallar al iniciar (o al menos loguear la red activa) cuando falten variables fuera de desarrollo.
  • networkPassphrase se lee pero nunca se usa. Un getNetwork al arrancar permitiría confirmar que el RPC sirve la red esperada.
  • SorobanRpcClient no tiene reintentos ni backoff, y _result descarta el código y mensaje del error JSON-RPC. Con rate limiting del RPC público, el catálogo completo falla por una sola llamada (eagerError: true). Con un reintento simple para 429/5xx y conservar el error para los logs alcanza.
  • El criterio "las lecturas funcionan contra los contratos de testnet" solo está cubierto con fixtures. Un smoke test opcional (con tag) contra testnet cerraría ese criterio.

Nota general del stack: como este PR apunta a la rama de #84 y no a main, el CI nunca corrió aquí (#86 a #93). Conviene ir re-apuntando cada PR a main cuando se mergee el anterior, para que pasen gate y scan.

@TOMOKI977 TOMOKI977 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. The adapter is solid and the failure-path coverage is good. None of the points from my earlier review block the Stellar Elite demo on testnet, so they can land as follow-ups:

  • StellarConfig silently falls back to testnet values when a PULS3_STELLAR_* variable is missing. Before any non-testnet deploy, fail at startup instead, or at least log the active network.
  • networkPassphrase is parsed but never used. A getNetwork check at startup would confirm the RPC serves the expected network.
  • SorobanRpcClient has no retry or backoff, and _result drops the JSON-RPC error code and message. A simple retry on 429/5xx would make the catalog build more resilient on the public RPC.

Merge note: this PR targets the #84 branch, so CI hasn't run here yet. Once #84 merges, retarget this to main and let gate and scan pass before merging.

@TOMOKI977
TOMOKI977 changed the base branch from fix/onchain-evidence-escrow-deploy to main October 5, 2026 21:45
@TOMOKI977
TOMOKI977 merged commit 853d24b into main Oct 5, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: backend Serverpod endpoints and persistence type: feat New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(server): read-only Soroban RPC adapter implementing LedgerPort

2 participants