Skip to content

💱 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 — even if it’s accessible in code.

Audience: Developers integrating Currency into gameplay, UI, or persistence Scope: Runtime public API only (Editor / Teaching helpers excluded)


🚀 Quick Start (Ignore everything else if you want)

var svc = CurrencyResolve.ServiceFrom(this);

svc.Credit(player, new CurrencyId("gold"), 100);

That’s it.

Everything else on this page is optional.


📌 Core Concepts

  • Currency is service-first and stack-composed.
  • All interaction happens via ICurrencyService and 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 CurOpResult with 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

SceneCurrencyService is the default scene implementation, but gameplay code must not depend on it directly.
Always resolve services via CurrencyResolve.


🧩 Composition & Factories

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 helpers enforce recommended ordering, but if composing manually you are responsible for decorator order.


📦 Batching

CurrencyBatching

Public batching wrapper that allows multi-operation work to emit a single batch event.

using var batch = CurrencyBatching.BeginBatch(svc);

// perform multiple operations

batch.Emit();

Batching:

  • captures deltas during a block
  • emits a single batch event on success
  • detaches subscriptions automatically via Dispose()

Batch emission only occurs when the service stack includes:

CurrencyFactories.WithBatchEvents(...)

Otherwise batching is a safe no-op.


📏 Policies & Caps

CurrencyPolicy

Authoritative asset defining per-currency caps and global rules.

Supported runtime surface:

  • TryGetCapRule(CurrencyId, out CurrencyCapRule)
  • RequireEscrow

CurrencyCapRule

Stable primitive returned by policies.

Fields:

  • min
  • max (0 = unlimited)
  • mode (Clamp or Fail)

Runtime code must rely on this primitive rather than authoring rule containers.


🔍 Operation Results

CurOpResult

Returned by all currency mutations.

Fields:

  • Success
  • Code
  • Message (optional)

CurOpCode

Stable outcome codes including:

  • Ok
  • InvalidArgs
  • InsufficientFunds
  • BelowMinimum
  • AboveMaximum
  • Unauthorized
  • ServiceMissing
  • NotFound

These codes are intended for:

  • UI feedback
  • analytics
  • deterministic branching

📊 Events

CurrencyDelta

Emitted after a successful mutation.

Contains:

  • owner
  • currency
  • before
  • after

Event Surfaces

Supported event surfaces:

  • ICurrencyService.OnWalletChanged
  • ICurrencyBatchEvents.OnWalletBatchChanged

Batch events emit once per successful multi-operation block when batching is enabled.


🧾 Audit (Optional Capability)

CurrencyAudit

Helpers for reading audit history when auditing is present.

CurrencyAudit.Get(svc, owner);

If auditing is not present, helpers return empty results.


Live Audit

using var sub = CurrencyAuditLive.Subscribe(svc, entry => { });

This only activates when the service stack implements ICurrencyAuditEvents.


⏱ Awaiters

CurrencyAwaiters

Async and coroutine helpers that wait for currency state changes without polling.

Examples:

  • WaitForBalanceAtLeastAsync
  • WaitForAnyChangeAsync
  • WaitForDeltaAsync
  • predicate-based waits

Async continuations may resume off the Unity thread.
Coroutine versions always resume on the Unity thread.


🔄 Transactions

CurrencyTxn

Fluent transaction builder.

var r = CurrencyTxn.Begin(svc)
    .Debit(player, gold, 250)
    .Credit(player, gems, 5)
    .Commit();

Guarantees:

  • ordered multi-operation execution
  • best-effort rollback on first failure
  • optional single batch event

Rollback may be blocked by:

  • policy
  • authority
  • escrow requirements
  • idempotency

🔐 Escrow

ICurrencyEscrow

Optional capability that enables hard-hold escrow.

Operations:

  • TryHold
  • Commit
  • Release
  • ExpireStale

Escrow behaviour:

  • TryHold debits immediately
  • Commit finalizes the hold
  • Release refunds

If CurrencyPolicy.RequireEscrow is enabled and the guard is present,
direct Debit and Transfer operations fail unless the stack includes escrow.


ICurrencyEscrowReadOnly

Inspection surface for UI and debugging.

Allows querying active holds without mutation.


🔁 Exchange

ICurrencyExchange

Stable interface for currency conversion.

Built via:

ICurrencyExchange ex = CurrencyFactories.BuildExchange(table);

Supports:

  • TryQuote
  • TryExchange

Execution performs debit then credit with best-effort rollback.


💾 Persistence

ICurrencyPersistence

Abstract persistence contract.

Helper utilities:

  • CurrencyPersistence.Capture
  • CurrencyPersistence.Restore

Scene utilities (JSON save etc.) may implement this interface but are not required.


🧱 Value Types

Stable primitives safe for storage and serialization:

  • CurrencyId
  • Money
  • CurrencyDelta
  • WalletSnapshot
  • WalletSnapshotLine

🧰 Supported Extensions

CurrencyServiceExtensions

Public extension helpers that do not expand the core interface.

Includes:

  • audit-aware overloads with reason and sourceId
  • affordability helpers
  • deficit helpers
  • transfer preview helpers

These extensions are part of the supported public API.


❌ Explicitly Not Supported

The following are not public API:

  • concrete service implementations (SceneCurrencyService, decorators)
  • internal namespaces (RevGaming.RevFramework.Currency.Internal)
  • internal batching types
  • 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 activate only when composed.

Not Guaranteed

  • Full transactional atomicity across arbitrary decorator stacks
  • Network replication
  • automatic escrow usage
  • automatic rollback when policy/authority blocks an operation

TL;DR

If it’s not on this page, it’s not part of the supported Currency API.