Skip to content

feat(server): escrow relay foundations: protocol, config, envelope codec and RPC (#96) - #126

Merged
TOMOKI977 merged 25 commits into
feat/96-escrow-relayfrom
feat/96-escrow-relay-04-rpc-client
Oct 8, 2026
Merged

TOMOKI977 merged 25 commits into
feat/96-escrow-relayfrom
feat/96-escrow-relay-04-rpc-client

Conversation

@moises-cisneros

@moises-cisneros moises-cisneros commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Refs #96

Part of the chain that replaces #119, split after its review. Tracker: #122. Regrouped from a first 12 PR split (#123, #124, #125 were folded into this one).

Summary

Everything the relay stands on, with no behavior yet: the protocol models and the escrow_preparation table (with generated code and migration), the relay configuration without defaults (ADR-0005 D3), the XDR encoder, the EnvelopeCodec contract with its stellar_dart implementation (field by field comparison and ed25519 verification, backed by a spike on recorded testnet envelopes), and the Soroban RPC calls (sequence, simulate, send, get transaction). Also the CI fixes from the review of #119: the three variables in .env.example and narrow gitleaks allowlists.

Acceptance criteria

The chain as a whole covers #96; this PR carries its slice (see Scope below).

  • The app can create and fund a hire on testnet using only prepare… and submitEscrowCall (proven in the docs PR)
  • A signed envelope that differs from its preparation in any field is rejected
  • A caller can never prepare or submit for a hire that is not theirs
  • A submit… call never throws for chain outcomes
  • Each preparation has at most one ChainSubmission

Verification evidence

dart analyze --fatal-infos
dart test test/protocol test/spike test/ledger test/unit/ledger
bash scripts/tests/env-inventory.test.sh   -> 71 passed
gitleaks over the whole tree                -> no leaks

Notes for reviewers

  • Review against the parent branch (feat/96-escrow-relay), not main. The commits are ordered to be read one by one.
  • Over the 400 line budget: 2329 authored lines, mostly tests of code that moves funds. Splitting further cuts the unit apart, so it needs size:exception.
  • Generated code, migrations and recorded fixtures are excluded from the authored count.

Chain Context

Field Value
Chain Escrow relay prepare and submit endpoints (#96)
Tracker PR #122
Position 1 of 4
Base feat/96-escrow-relay
Depends on #122 (tracker)
Follow-up #129
Review budget 2329 authored (11660 total) / 400
Starts at feat/96-escrow-relay
Ends with Protocol models, migration, HireRelayConfig, SessionWallet, XDR encoder, envelope codec, RPC calls, .env.example, .gitleaks.toml, with their tests.

Chain Overview

main
 └── #122 Tracker (draft, no merge)
      └── 📍 #126 escrow relay foundations: protocol, config, envelope codec and RPC
           └── #129 persist preparations and prepare unsigned escrow envelopes
                └── #132 submit signed escrow calls and expose the relay in the hire endpoint
                     └── #134 escrow relay API, ADRs, README, testnet e2e and OpenSpec archive

Scope

  • Includes: Protocol models, migration, HireRelayConfig, SessionWallet, XDR encoder, envelope codec, RPC calls, .env.example, .gitleaks.toml, with their tests.
  • Excludes: Stores, services and the endpoint.

Autonomy

  • CI is expected to pass for this PR branch
  • This PR has one deliverable scope
  • This PR can be rolled back without unrelated changes
  • Tests, docs, or manual verification cover this unit

Narrow rules scoped by file path and line shape for env var name constants, generated class-name lookups and recorded ledger keys. Migrates the existing allowlist to [[allowlists]], which cannot be mixed with the deprecated [allowlist].
Adds PreparedTransaction, CreateHireResult, HireDetail, Hire, Payment and Puls3ApiException, the escrow_preparation table and the requestId, input and jobId columns of hire. Part of #96.
Reads the preparation validity, inclusion fee and platform fee from the environment with no defaults (ADR-0005 D3). Documents the keys in .env.example. Part of #96.
Defines how the relay decodes, compares and re-encodes a transaction envelope. Part of #96.
…opes

Adds stellar_dart and crypto. The spike decodes recorded testnet envelopes, re-encodes them byte for byte and checks the network hash and the ed25519 signature. Part of #96.
Decodes a signed envelope, compares it field by field with its preparation (contract, function, arguments, source, time bounds) and verifies the signature. Part of #96.
Adds account sequence lookup and the simulate, send and get-transaction calls that carry an unsigned or signed envelope. Part of #96.
A new preparation supersedes the previous one, and each preparation has at most one submission, proven by a Postgres race test. Part of #96.
Gives the relay its view of a hire: idempotency key, input and escrow job id, with a hire having no status until create_job is confirmed. Part of #96.
prepareCreateJob, prepareFund, prepareComplete and prepareReject build, simulate and store an unsigned envelope. A new preparation supersedes the previous one, and the configuration has no defaults. Part of #96.
submitEscrowCall checks the signed envelope against its preparation, stores a ChainSubmission as submitted and only then sends it. Chain outcomes never throw, and a repeated submit returns the existing record. Part of #96.
HireEscrowEffects.onJobCreated binds the job id once and opens the hire. Part of #96.
createHire returns the hire with an unsigned create_job, and a repeated requestId from the same wallet returns the same hire or IdempotencyKeyReused. Part of #96.
createHire, prepareCreateJob, prepareFund, prepareComplete, prepareReject and submitEscrowCall, each behind requireLogin through an injectable SessionWallet. The production default fails closed with AuthenticationUnavailable until wallet sessions land (#25). Regenerates the endpoint and client. Part of #96.
Lists ChainDataUnavailable for submitEscrowCall, drops the TypeScript sidecar from the ADRs and documents the config keys and the end-to-end run. Part of #96.
Runs the real endpoint, services, codec, RPC client and chain tracker against testnet. The consumer key stays in the process environment. Part of #96.
@cloudflare-workers-and-pages

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

Copy link
Copy Markdown

Deploying puls3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3a9957a
Status:⚡️  Build in progress...

View logs

@moises-cisneros moises-cisneros changed the title feat(server): Soroban RPC calls for the escrow relay (#96) feat(server): escrow relay foundations: protocol, config, envelope codec and RPC (#96) Oct 8, 2026
@moises-cisneros
moises-cisneros changed the base branch from feat/96-escrow-relay-03-stellar-codec to feat/96-escrow-relay October 8, 2026 16:59

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

Approved. This slice is part of the code I reviewed in full on #119 at b0a4adc (all four lenses; see the review there). I checked that the tip of the chain matches b0a4adc except for the CI fix in .env.example and .gitleaks.toml (and main's #112). The follow-ups listed on #119 apply to the chain as a whole.

…-12-openspec

docs: escrow relay API, ADRs, README, testnet e2e and OpenSpec archive (#96)
…-10-endpoint

feat(server): submit signed escrow calls and expose the relay in the hire endpoint (#96)
…-07-prepare

feat(server): persist preparations and prepare unsigned escrow envelopes (#96)
@TOMOKI977
TOMOKI977 merged commit cb01469 into feat/96-escrow-relay Oct 8, 2026
1 check was pending
@TOMOKI977
TOMOKI977 deleted the feat/96-escrow-relay-04-rpc-client branch October 8, 2026 19:36
TOMOKI977 pushed a commit that referenced this pull request Oct 8, 2026
Closes #96. Server-side relay (api.md Decision A): HireEndpoint with idempotent createHire, prepareCreateJob/prepareFund/prepareComplete/prepareReject that build unsigned Soroban envelopes, and submitEscrowCall that verifies the signed envelope byte for byte, checks the ed25519 signature against the session wallet, stores a submitted ChainSubmission and sends it for the chain tracker. Session wallet fails closed until #25. Includes the testnet e2e tool (tool/e2e_relay_testnet.dart), docs and the OpenSpec archive. Reviewed as #119; landed through the chain #126, #129, #132, #134.
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.

2 participants