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¶
- Enter Play Mode.
- Open the CurrencyEscrowPanel (
F8). - Select a currency and enter an amount.
- (Optional) Set a TTL (seconds) for auto-expiry.
- Press Try Hold to debit the wallet and create a hold token.
- Observe active holds listed in the panel with Token, Amount, and Age/TTL.
- Press:
- Commit → Finalise the hold (currency is permanently deducted).
- Release → Refund the held funds immediately.
- Enable Expiry Pump to automatically expire stale holds.
- 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:
CurrencyAuthorityBinderalwaysTrue = 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()andCommit()are idempotent — safe to call multiple times.- If this scene is running the bootstrapped service stack, removing
CurrencyAuthorityBinderwill cause all currency mutations to fail withUnauthorized.
📚 Related¶
- 03_Currency_Persistence — Saving and restoring wallet data.
- 06_Currency_Idempotency — Safe duplicate handling for networked transactions.
- Decorators — Escrow and related decorator internals.
- Core —
CurrencyEscrowExpiryPump,CurrencyTxn, and utility classes. - Samples Index — Overview of all sample scenes.
Teaching Panel: CurrencyEscrowPanel
Scene Path:
Assets/RevFramework/Runtime/Systems/Currency/Samples/Scenes/05_Currency_Escrow/