Skip to content

💰 Currency / Bootstrap

🎯 Purpose

The Bootstrap layer composes and publishes a Currency service stack for resolution.

It defines how a service is:

  • Discovered (scene-local)
  • Composed (decorators)
  • Published (resolver override)

This layer controls wiring and lifecycle, not behaviour.


🧠 Usage Guidance

Bootstrap is responsible for:

  • Composing a currency service stack from building blocks
  • Publishing the composed service via CurrencyResolve
  • Managing scoped lifecycle for resolver overrides
  • Providing a default composition pipeline

🧩 What Lives Here

CurrencyBootstrap

Low-level publishing helper.

public static IDisposable Publish(ICurrencyService service)
  • Sets the active resolver override
  • Returns a scope that clears it on Dispose()

CurrencyServiceBootstrap

Scene component that builds and publishes the service stack.

Execution order:

[DefaultExecutionOrder(-499)]

Behaviour:

  • On Awake():

  • Finds a SceneCurrencyService

  • Warns if no ICurrencyAuthority is present
  • Composes the service stack
  • Publishes via CurrencyBootstrap

  • On OnDisable / OnDestroy:

  • Disposes the scope (clears override)


⚠️ Important Notes

  • Bootstrap does not implement business or mutation logic
  • Behaviour is defined by the composed service stack
  • Authority must be present when authority decorators are composed
  • Resolver overrides are global and should be scoped carefully
  • Multiple bootstraps require intentional ordering

🧠 Usage Guidance

Resolver override

Currency resolution is performed via CurrencyResolve.

Publishing a service ensures that all consumers resolve the same active instance.

The override remains active until the returned scope is disposed.


Scoped publishing

var scope = CurrencyBootstrap.Publish(service);
  • The service becomes the active resolver override
  • Disposing the scope clears the override

Default composition pipeline

The built-in bootstrap composes:

SceneCurrencyService
→ Caps + Audit + Authority
→ Idempotency
→ BatchEvents

RequireEscrow may also be included depending on policy.

Order is intentional:

  • Caps run before audit
  • Authority gates mutations
  • Idempotency wraps outer mutations
  • Batch emits grouped events

Custom bootstrap example

public class MyBootstrap : MonoBehaviour
{
    private IDisposable _scope;

    void Awake()
    {
        var inner = FindFirstObjectByType<SceneCurrencyService>();
        if (!inner) return;

        ICurrencyService svc = inner;

        svc = CurrencyFactories.WithAudit(svc);
        svc = CurrencyFactories.WithCaps(svc, policy);
        svc = CurrencyFactories.WithAuthority(svc, this);

        _scope?.Dispose();
        _scope = CurrencyBootstrap.Publish(svc);
    }

    void OnDisable()
    {
        _scope?.Dispose();
        _scope = null;
    }
}

Always compose from the inner service, not from CurrencyResolve, to avoid stacking decorators multiple times.


🚫 Internal Use Only

This folder handles composition and publishing only.

Do not:

  • Add gameplay logic
  • Implement mutation rules here
  • Depend on resolver overrides for application logic

🧹 Safe to Remove

This folder may be replaced if a custom bootstrap solution is used.

Removing it requires providing an alternative service composition and publishing strategy.


  • Abstractions — core contracts
  • Internal — decorator implementations
  • Authority — mutation gating
  • Policies — caps and transfer rules
  • UnityIntegration — SceneCurrencyService