💱 Currency System — Public API¶
This page defines the supported, stable public API for the RevFramework Currency System.
If something is not listed here, it is not supported as a public integration point — even if it appears accessible in code.
Audience: Developers integrating Currency into gameplay, UI, or persistence
Scope: Runtime public API only (Editor / Teaching helpers excluded)
Stability: Breaking changes to items listed here are avoided or clearly versioned
📌 Core Concepts¶
- Currency is service-first and stack-composed.
- All interaction happens via
ICurrencyServiceand related capability interfaces. - Currency values are stored as integer minor units (
long), never floats. - Cross-cutting behaviour (caps, audit, escrow, authority, idempotency, batching) is added via composition, not inheritance.
- All mutations return a
CurOpResultwith an explicit outcome code.
🧱 Service Entry Points¶
ICurrencyService¶
The canonical runtime interface for all currency interaction.
Supported operations:
EnsureWallet(owner)GetBalance(owner, currencyId)Credit(owner, currencyId, amount)Debit(owner, currencyId, amount)SetBalance(owner, currencyId, absoluteAmount)Transfer(from, to, currencyId, amount)
All amounts are minor units (long).
Resolution¶
Currency services are resolved via:
ICurrencyService svc = CurrencyResolve.ServiceFrom(context);
Resolution order:
1. Published override (bootstrappers / tests / teachables)
2. Scene-local SceneCurrencyService
SceneCurrencyServiceis a required scene component for the default runtime setup,
but gameplay code should never depend on it directly. Always resolve viaCurrencyResolve.
🧩 Composition & Factories (Supported)¶
CurrencyFactories¶
The supported way to build and extend a currency stack without referencing internal types.
Common decorators:
WithCaps(inner, policy)WithAudit(inner)WithAuthority(inner, context)WithEscrow(inner)WithIdempotency(inner)WithBatchEvents(inner)
Recommended multiplayer stack:
svc = CurrencyFactories.WithCapsAuditAuthority(
baseSvc,
policy,
context
);
Order matters. Combined factory helpers enforce a safe, recommended ordering. If composing manually, you are responsible for maintaining correct decorator order.
📦 Batching (Public Wrapper)¶
CurrencyBatching¶
Public batching API that allows multi-operation work to emit a single batch event without exposing internal batching types.
using var batch = CurrencyBatching.BeginBatch(svc);
// perform multiple operations...
batch.Emit(); // or batch.Cancel();
- Safe no-op when the service does not support batching
- Guarantees event unsubscription via
Dispose()
📏 Policies & Caps¶
CurrencyPolicy¶
Authoritative asset defining per-currency caps and global rules.
Supported runtime surface:
TryGetCapRule(CurrencyId, out CurrencyCapRule)RequireEscrow(global toggle)
CurrencyCapRule¶
Stable primitive returned by policies:
minmax(0 = no max)mode(ClamporFail)
No runtime code should depend on authoring rule shapes.
🔍 Operation Results¶
CurOpResult¶
Returned by all currency mutations.
Fields:
- Success
- Code
- Message (optional, best-effort)
CurOpCode¶
Stable outcome codes, including:
OkInvalidArgsInsufficientFundsBelowMinimumAboveMaximumUnauthorizedServiceMissingNotFound
These codes are intended for: - UI feedback - analytics - deterministic branching
📊 Events & Observation¶
CurrencyDelta¶
Emitted after a successful mutation.
Contains:
- owner
- currency
- before
- after
Events¶
Supported event surfaces:
ICurrencyService.OnWalletChangedICurrencyBatchEvents.OnWalletBatchChanged(when batching is enabled)
Batch events emit once per successful multi-op commit when batching is enabled and a batch scope is emitted.
🧾 Audit (Optional Capability)¶
CurrencyAudit (Helpers)¶
Safe helper API for reading audit history when supported:
CurrencyAudit.Get(svc, owner, lastN);
If auditing is not present, helpers return empty results.
Live Audit¶
using var sub = CurrencyAuditLive.Subscribe(svc, entry => { ... });
Only active when the service stack supports audit events.
⏱ Awaiters & Async Helpers¶
CurrencyAwaiters¶
Supported async / coroutine helpers that subscribe to events instead of polling:
WaitForBalanceAtLeastAsyncWaitForAnyChangeAsyncWaitForDeltaAsync- Predicate-based waits
Async continuations may resume off the Unity main thread.
Coroutine variants always resume on the Unity thread.
🔄 Transactions¶
CurrencyTxn¶
Fluent transaction builder for orchestrated atomic multi-operation commits.
var r = CurrencyTxn.Begin(svc, "ShopPurchase", sourceId)
.Debit(player, gold, 250)
.Credit(player, gems, 5)
.Commit();
Guarantees: - Orchestrated multi-operation commit - Best-effort rollback on first failure - Single batch event when supported
Note: True transactional atomicity across all decorator stacks is not guaranteed. Authority, RequireEscrow, idempotency, or policy rules may block rollback operations.
🔐 Escrow (Optional Capability)¶
ICurrencyEscrow¶
Hard-hold escrow for debits and transfers.
Supported operations:
- TryHold
- Commit
- Release
- ExpireStale
When CurrencyPolicy.RequireEscrow is enabled and the RequireEscrow guard is composed,
direct Debit and Transfer operations fail unless the service stack includes escrow.
ICurrencyEscrowReadOnly¶
Read-only inspection surface for UI/debug tooling.
🔁 Exchange¶
ICurrencyExchange¶
Stable interface for currency conversion.
Built via:
ICurrencyExchange ex = CurrencyFactories.BuildExchange(table);
Supports:
- TryQuote
- TryExchange (orchestrated debit + credit)
TransferPolicyProviders¶
Helper for building ITransferPolicyProvider instances without exposing authoring types.
ITransferPolicyProvider provider = TransferPolicyProviders.FromPolicy(policy);
💾 Persistence¶
ICurrencyPersistence¶
Abstract persistence contract.
Supported helpers:
- CurrencyPersistence.Capture
- CurrencyPersistence.Restore
Scene tools (JSON save, etc.) implement this interface but are not required for gameplay.
🧱 Value Types (Stable)¶
CurrencyIdMoneyCurrencyDeltaWalletSnapshotWalletSnapshotLine
These types are safe to store, serialize, and compare.
🧰 Supported Convenience Extensions¶
CurrencyServiceExtensions¶
Public extension helpers that do not expand the core service interface:
- Credit / Debit / Transfer overloads with
reasonandsourceId - Deficit and affordability helpers
- Transfer preview helpers
- Formatting helpers for UI
These extensions are part of the supported public API.
❌ Explicitly Not Supported¶
The following are not part of the supported public API:
- Concrete service implementations (
SceneCurrencyService, decorators) - Internal decorators or helpers
- Internal namespaces (
RevGaming.RevFramework.Currency.Internal.*) - Casting to internal capability interfaces
- Authoring rule containers
- Direct access to audit buffers or escrow internals
Runtime Guarantees¶
- Single currency operations are atomic.
- All mutations return a deterministic
CurOpResult. - Successful mutations emit
OnWalletChanged. - Optional capabilities (audit, escrow, idempotency, batching) activate only when composed.
Not Guaranteed¶
- Cross-operation transactional atomicity across arbitrary decorator stacks.
- Network replication or prediction.
- Implicit escrow usage.
- Automatic rollback under authority or policy denial.
TL;DR¶
If it’s not on this page, it’s not part of the supported Currency API.