RevFramework – Currency FAQ¶
This FAQ answers decision questions about using the Currency system: how to integrate it, which extension point to use, and what is supported vs. discouraged.
It does not repeat the README content. If you’re looking for APIs, examples, or behaviour details, see the Currency READMEs.
How do I integrate Currency into my project?¶
Minimal runtime setup:
1. Add SceneCurrencyService to the scene.
2. (Recommended) Add CurrencyServiceBootstrap and configure Caps / Audit / Authority as needed.
3. Resolve the service via CurrencyResolve.ServiceFrom(this) wherever you need it.
Inventory-backed setup (optional):
- Use CurrencyInventoryFactories.* helpers (requires REV_INVENTORY_PRESENT).
- Wrap with Caps / Audit / Authority using CurrencyFactories.
Rule of thumb: resolve services; don’t reference concrete implementations.
Is this the right extension point?¶
I want to change balances¶
Use: ICurrencyService (resolved via CurrencyResolve).
Avoid: calling SceneCurrencyService.Instance directly in gameplay unless you explicitly want the raw inner service and accept bypassing decorators.
I want to enforce min/max limits¶
Use: CurrencyPolicy + CurrencyFactories.WithCaps(...).
Avoid: clamping values manually in gameplay or UI code.
I want audit logs (who changed what and why)¶
Use: CurrencyFactories.WithAudit(...) and query via CurrencyAudit.Get(...).
Avoid: custom logging wrapped around currency calls.
I want atomic multi-step operations (shops, trades)¶
Use: CurrencyTxn or CurrencyPurchase helpers.
Avoid: chaining multiple Credit / Debit calls without orchestration.
Transactions orchestrate multi-step operations with best-effort rollback. Depending on the composed stack (policy, authority, escrow, idempotency), rollback may be blocked by outer decorators.
When supported, a single batch event is emitted after a successful commit.
I want escrow / holds¶
Use: CurrencyFactories.WithEscrow(...) (capability).
If you need to enforce escrow usage:
- Enable CurrencyPolicy.RequireEscrow (adds a guard that blocks debits/transfers when escrow is not present).
Avoid: assuming RequireEscrow adds escrow automatically — it does not.
I want multiplayer-safe retries¶
Use: CurrencyFactories.WithIdempotency(...) and include |rid:<token> in sourceId.
Avoid: relying on non-audit overloads — idempotency applies only to audit-aware calls.
I want authority (server / host only)¶
Use: CurrencyFactories.WithAuthority(...) with an ICurrencyAuthority implementation.
Single-player: CurrencyAuthorityBinder (alwaysTrue = true) is sufficient.
Avoid: calling mutations from non-authoritative contexts.
Can I do X with Y?¶
Can I use Currency without Inventory?¶
Yes. Inventory adapters are optional. Currency works with SceneCurrencyService alone.
Can I use Inventory items as currency?¶
Yes. Use CurrencyInventoryFactories.* (requires REV_INVENTORY_PRESENT).
Can I save / load balances?¶
Yes. Use CurrencyPersistence (per-owner) or CurrencyJsonSave (scene-wide).
Can I show balances in UI?¶
Yes. Use optional UI components:
- CurrencyBar (UGUI)
- CurrencyBarTMP
- CurrencyBarUITK
Or build your own UI by subscribing to OnWalletChanged.
Can I exchange currencies?¶
Yes. Use CurrencyExchangeTable + CurrencyFactories.BuildExchange(...).
Always TryQuote before TryExchange.
Can I change balances directly from UI code?¶
No.
UI should observe currency state, not mutate it. All balance changes must go through ICurrencyService.
Can I call SetBalance in multiplayer?¶
Yes, but only from the authoritative side.
SetBalance bypasses debit/credit semantics and writes an absolute value.
It still flows through policy, authority, and other decorators in the stack.
Do not use SetBalance on clients unless your authority model explicitly allows it.
What should I avoid?¶
- ❌ Newing decorator classes directly
- ❌ Bypassing
CurrencyFactories - ❌ Hardcoding currency logic in UI
- ❌ Polling for balance changes
- ❌ Treating
CurrencyDefinitionas logic data - ❌ Assuming escrow is automatic
What guarantees does Currency provide?¶
- Deterministic, allocation-light operations
- Orchestrated multi-step operations with best-effort rollback
- Decorator order is explicit and predictable
- Persistence restore is orchestrated with rollback and batch emission when supported
- Public API surface is small and stable
When should I contact support?¶
Before contacting support, please check:
- Are you resolving the service via
CurrencyResolve? - Is your decorator order intentional?
- Are you using audit-aware overloads when expecting idempotency?
- Is
RequireEscrowenabled without composing escrow? - Are all wallet owners assigned a valid
StableId(for persistence)?
If you still believe something is wrong, include:
- Unity version
- Active decorators
- Repro steps
- Relevant CurOpResult codes / messages
Summary¶
Currency is designed to be: - Modular - Explicit - Authority-aware - Transaction-safe - UI-agnostic
If you stick to the factories, resolve via the resolver, and keep logic out of UI, you’re using it correctly.