ProtocolScope

interface ProtocolScope

The builder scope of a MidnightSdk.runProtocol saga — an ordered list of idempotent, ledger-anchored steps (#253 + #254).

The engineering pattern: the blockchain is the durable execution journal. Each step declares a doneWhen predicate that reads the CHAIN; before running a step the engine asks the chain, and if the effect is already there it SKIPS. So:

  • re-running a saga (after process death, or on app resume) skips every already-landed step → resume-for-free, no fragile local workflow store, and

  • no double-submit — re-running is always safe.

The whole saga runs as ONE foreground operation (the Layer-1 framework keeps the process alive + shows one notification + fires one finalization push); the inner contract.calls coalesce under it via the registry's nesting guard.

Because this is a plain suspend block, real control flow between steps — if, while, inline waits — is native Kotlin (a fluent .then() chain can't express it).

Functions

Link copied to clipboard
abstract suspend fun awaitCounterparty(name: String, doneWhen: suspend () -> Boolean)

Boundary for an UNBOUNDED wait on a counterparty (e.g. the opponent's move). No foreground service may span it, so if doneWhen isn't yet true the engine ENDS this segment — releasing the foreground service — and the saga resumes (re-run via MidnightSdk.runProtocol with the same id) when the counterparty acts. Ledger- anchored doneWhens carry the resumed run forward past the already-done steps.

Link copied to clipboard
abstract suspend fun step(name: String, doneWhen: suspend () -> Boolean, action: suspend () -> Unit)

Run one idempotent step. If doneWhen is already true on-ledger the step is SKIPPED (resume/idempotency); otherwise action runs and the engine waits until doneWhen flips true (confirmation) before returning, so the next step sees a consistent ledger. name is for progress/logging.