Skip to content

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; do not depend on concrete implementations.


Is this the right extension point?

I want to change balances

Use: ICurrencyService (resolved via CurrencyResolve).

Avoid: referencing SceneCurrencyService.Instance.

SceneCurrencyService is the default implementation, but it is not part of the supported public API surface. Accessing it directly bypasses the composed decorator stack.


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.

For stronger guarantees with escrow-enabled stacks, use CurrencyHoldTxn.

Avoid: chaining multiple Credit / Debit calls without orchestration.

Transactions provide:

  • ordered execution
  • best-effort rollback
  • optional batch event emission

Rollback may be blocked by outer decorators such as policy, authority, escrow requirements, or idempotency.


I want escrow / holds

Use: CurrencyFactories.WithEscrow(...).

If you need to enforce escrow usage:

Enable CurrencyPolicy.RequireEscrow.

This adds a guard that blocks direct Debit / Transfer when escrow is not present.

Important

RequireEscrow does not add escrow automatically.
It only blocks operations when escrow is missing.


I want multiplayer-safe retries

Use: CurrencyFactories.WithIdempotency(...) and include:

|rid:<token>

inside the sourceId.

Avoid: relying on non-audit overloads — idempotency applies only to audit-aware overloads.

Note:

Replay short-circuits may not emit wallet events or audit entries, depending on decorator order.


I want authority (server / host only)

Use: CurrencyFactories.WithAuthority(...) with an ICurrencyAuthority implementation.

Single-player

Use CurrencyAuthorityBinder (alwaysTrue = true).

Avoid

Calling currency 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.* (when the inventory module is present).


Can I save / load balances?

Yes.

Use:

  • CurrencyPersistence helpers (per-owner)
  • CurrencyJsonSave (scene-wide utility)

Persistence restore respects the composed decorator stack (policy, authority, etc.).


Can I show balances in UI?

Yes.

Optional UI components:

  • CurrencyBar (UGUI)
  • CurrencyBarTMP
  • CurrencyBarUITK

Or subscribe to:

ICurrencyService.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 writes an absolute value and bypasses debit/credit semantics.

It still flows through policy, authority, and other decorators.

Do not call SetBalance on clients unless your authority model allows it.

Prefer debit/credit flows when modelling gameplay actions


What should I avoid?

  • ❌ Newing decorator classes directly
  • ❌ Bypassing CurrencyFactories
  • ❌ Hardcoding currency logic in UI
  • ❌ Polling for balance changes
  • ❌ Treating CurrencyDefinition as gameplay logic
  • ❌ Assuming escrow is automatic
  • ❌ Assuming decorator order does not matter

What guarantees does Currency provide?

Currency guarantees:

  • deterministic currency mutations
  • explicit decorator composition
  • orchestrated multi-operation flows
  • event-driven observation
  • a stable, minimal public API

Currency does not guarantee:

  • full transactional atomicity across arbitrary decorator stacks
  • networking replication
  • automatic escrow usage

See SystemGuaranteesMatrix.md for the formal guarantee definitions.


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 RequireEscrow enabled without composing escrow?
  • Are wallet owners assigned a valid StableId (for persistence)?

If reporting an issue, include:

  • Unity version
  • Active decorators
  • Repro steps
  • Relevant CurOpResult codes / messages

Summary

Currency is designed to be:

  • modular
  • explicit
  • authority-aware
  • transaction-capable
  • UI-agnostic

If you resolve via CurrencyResolve, compose via CurrencyFactories, and keep logic out of UI, you are using the system correctly.