Skip to content

💰 Currency -- Abstractions

Namespace: RevGaming.RevFramework.Currency.Abstractions

This folder defines the entire supported public contract of the Currency system.

Everything here is: - Stable -- intended to change rarely between minor versions - Data‑oriented or capability‑based -- no implementation/runtime logic - Safe to reference from any other module (Inventory, Pickups, Health, Crafting, Economy, UI, etc.)

This is the foundation layer the rest of the Currency stack builds on.


Ownership model

Currency is tracked per owner per currency, where the owner is a Unity GameObject.

This is a deliberate design choice: - Currency services are Unity‑bound - Ownership maps cleanly to scene objects, prefabs, and runtime entities

If you need non‑Unity ownership (e.g. pure data or server models), wrap them in a GameObject owner proxy or provide an adapter layer.


Purpose

  • Provide a minimal, stable API surface (ICurrencyService, CurrencyId, Money, etc.).
  • Allow other systems to integrate with Currency without concrete dependencies.
  • Stay deterministic, allocation‑light, and netcode‑friendly.
  • Enable decorators (caps, audit, escrow, authority, idempotency, batching) to compose cleanly around a single contract.

This folder never contains wallet logic. It defines what can be done, not how it is done.


Key Files

CurrencyPrimitives.cs

Fundamental value types used throughout the Currency system:

  • CurOpKind -- High‑level intent of an audited mutation (Set, Credit, Debit, Transfer).
  • CurOpCode -- Stable, machine‑readable outcome codes (Ok, InvalidArgs, InsufficientFunds, Unauthorized, etc.).
  • CurOpResult -- Immutable operation result.
    • Branch on Code, not strings
    • Success is derived from Code (Code == Ok)
  • CurrencyId -- Canonical currency key ("gold", "gems").
    • Trimmed, lower‑cased, ordinal equality
    • Safe for dictionary keys and hashing
  • Money -- Immutable integer minor‑unit amount (long).
    • No floats
    • Checked arithmetic
    • TryAdd / TrySub helpers
  • CurrencyDelta -- Post‑commit wallet change snapshot (before → after) for one owner and currency.

Important RevFramework always stores currency in minor units. Convert floats or decimals at the boundary --- do not store floats in currency state.


ICurrencyService.cs

The core currency service contract:

public interface ICurrencyService
{
    event Action<CurrencyDelta> OnWalletChanged;

    bool EnsureWallet(GameObject owner);
    Money GetBalance(GameObject owner, CurrencyId currency);

    CurOpResult Credit(GameObject owner, CurrencyId currency, Money amount);
    CurOpResult Debit(GameObject owner, CurrencyId currency, Money amount);
    CurOpResult SetBalance(GameObject owner, CurrencyId currency, Money newBalance);
    CurOpResult Transfer(GameObject from, GameObject to, CurrencyId currency, Money amount);
}

Notes: - All operations are explicit and synchronous - Events are raised after a successful commit - Audit metadata (reason/sourceId) is intentionally not part of this interface and is exposed only by audited stacks

Everything else in the system exists to decorate, observe, or compose around this contract.


ICurrencyAuditReader.cs

Optional, read‑only access to audit history.

  • Implemented by services that record audit entries
  • Consumers must treat this capability as optional
  • Retention and persistence are implementation‑defined

ICurrencyAuditEvents.cs

Optional live audit event surface.

  • Exposes OnAuditEntry for services that emit audit entries as they occur
  • Safe to probe via is ICurrencyAuditEvents
  • Non‑audited stacks simply do not implement it

ICurrencyBatchEvents.cs

Optional batch mutation event surface.

  • Exposes OnWalletBatchChanged
  • Collapses multiple mutations into one event per commit
  • Useful for UI‑heavy or animation‑driven systems

ICurrencyEscrow.cs

Optional contract for hard‑hold escrow:

  • TryHold
  • Commit
  • Release
  • ExpireStale

Notes: - Holds return an opaque token (Guid) - TTL is optional (<= 0 means no expiry) - Commit finalizes a hold (funds are already debited at hold time) - Expiry is manual --- call ExpireStale from a pump if you rely on TTL


ICurrencyEscrowReadOnly.cs

Non‑mutating inspection surface for escrow state.

  • Check whether a token is active
  • Inspect time‑to‑expiry
  • Enumerate active holds per owner
  • Read lightweight hold info for UI/debug

This exists so UI and diagnostics can inspect escrow without mutating state.


ICurrencyExchange.cs

Public seam for currency conversion logic.

  • TryQuote --- non‑mutating preview
  • TryExchange --- debit + credit on the provided service
    • May attempt best‑effort rollback if credit fails\
    • Not guaranteed fully atomic

The Currency system does not define exchange rates. All conversion rules live in implementations of this interface.


ITransferPolicyProvider.cs

Optional contract supplying data‑only transfer bounds.

  • Source rules apply to the sender
  • Destination rules apply to the receiver
  • Returning false indicates no rule (treat as unbounded)

Used for preview‑time validation without touching live wallet state.


Usage (Abstractions‑Only Example)

This example depends only on the Abstractions layer:

using UnityEngine;
using RevGaming.RevFramework.Currency.Abstractions;

public sealed class GoldPickup : MonoBehaviour
{
    [SerializeField] private CurrencyId _id = new CurrencyId("gold");
    [SerializeField] private long _amount = 100;

    public ICurrencyService Service; // Injected or assigned by your game

    void OnTriggerEnter(Collider other)
    {
        if (Service == null)
            return;

        Service.Credit(other.gameObject, _id, new Money(_amount));
    }
}

Guidelines:

  • Depend only on ICurrencyService (or other abstractions) in cross‑system code
  • Compose behaviour via CurrencyFactories (Core layer)
  • Resolve services via CurrencyResolve (Core layer)
  • Never construct decorator classes directly

Safe to reference

Everything in this folder is:

  • Runtime‑safe
  • Editor‑safe
  • Dependency‑light
  • Intended for cross‑system use

If you are integrating Currency into another RevFramework system, this is the layer you should reference.


  • Core --- Factories, awaiters, transaction helpers, audit utilities
  • Internal --- Decorators (caps, audit, escrow, idempotency, batching)
  • Policies --- CurrencyPolicy authoring and rule definitions
  • Persistence --- Snapshot capture and restore helpers
  • UI --- Optional currency bars