Skip to content

RevFramework – Sample Scene: 05_Currency_Escrow

Namespace: RevGaming.RevFramework.Runtime.Currency.Samples.Scenes


🎯 Purpose

Demonstrate how to hold, commit, release, and expire currency using the Escrow system, including automatic expiry pumps for time-limited holds.
This scene uses a dedicated bootstrap (CurrencyServiceBootstrap_Escrow) to show the full escrow flow in a working stack.


🧩 What This Scene Teaches

  • How to place temporary holds on wallet balances.
  • How to commit (finalise) or release (refund) held currency.
  • How to configure TTL (time-to-live) for automatic expiry.
  • How to attach a CurrencyEscrowExpiryPump to auto-expire stale holds.
  • How escrow integrates cleanly with any composed service stack (Caps, Audit, Authority, etc.).

🕹️ How to Use

  1. Enter Play Mode.
  2. Open the CurrencyEscrowPanel (F8).
  3. Select a currency and enter an amount.
  4. (Optional) Set a TTL (seconds) for auto-expiry.
  5. Press Try Hold to debit the wallet and create a hold token.
  6. Observe active holds listed in the panel with Token, Amount, and Age/TTL.
  7. Press:
  8. Commit → Finalise the hold (currency is permanently deducted).
  9. Release → Refund the held funds immediately.
  10. Enable Expiry Pump to automatically expire stale holds.
  11. Press ExpireStale (Manual) to trigger an immediate expiry sweep.

⚙️ Stack Composition

This scene uses a custom bootstrap that includes the full escrow setup:

CurrencyServiceBootstrap_Escrow

It composes the standard stack:

SceneCurrencyService
→ CappedCurrencyService
→ AuditedCurrencyService
→ AuthorityCurrencyService
→ IdempotencyCurrencyService
→ BatchEventCurrencyService
→ EscrowCurrencyService

And then attaches an expiry pump automatically:

svc = CurrencyFactories.WithEscrowAndPump(svc, this, pumpIntervalSeconds);

This ensures a working CurrencyEscrowExpiryPump is bound and ticking during play.


🔐 Authority (Important)

This sample scene includes a CurrencyAuthorityBinder configured for single-player use:

  • CurrencyAuthorityBinder
  • alwaysTrue = true

This allows all currency mutations so the demo works out of the box.

Why this exists

RevFramework currency mutations are authority-gated by default.

  • If no authority is present, all mutations are blocked.
  • This is intentional and required for multiplayer safety.

Multiplayer note

For multiplayer or server-authoritative games:

  • Do not use CurrencyAuthorityBinder
  • Implement your own ICurrencyAuthority
  • Validate all currency mutations on the server/host

This scene uses the permissive binder only to demonstrate behaviour in a local, single-player context.


💡 Key Takeaways

  • TryHold() immediately debits currency and returns a token.
  • Commit() finalises the hold — funds are permanently spent.
  • Release() refunds the held amount back to the wallet.
  • ExpireStale() prunes expired holds and cleans up destroyed owners.
  • Escrow is ideal for checkout flows, crafting systems, timed reservations, or pre-authorisations.
  • Works transparently with Audit, Caps, Authority, and Idempotency decorators.

⚠️ Gotchas

  • If the Expiry Pump is disabled, expired holds will persist until manually cleared.
  • Escrow tokens are only valid within their original service context — don’t reuse across scenes.
  • Expiry uses Time.realtimeSinceStartup — unaffected by time scaling.
  • Large TTLs can keep stale holds alive indefinitely; design with cleanup in mind.
  • Release() and Commit() are idempotent — safe to call multiple times.
  • If this scene is running the bootstrapped service stack, removing CurrencyAuthorityBinder will cause all currency mutations to fail with Unauthorized.


Teaching Panel: CurrencyEscrowPanel
Scene Path:

Assets/RevFramework/Runtime/Systems/Currency/Samples/Scenes/05_Currency_Escrow/