Skip to content

Economy – Services

This folder contains the internal implementations of the Economy flows.
These classes are not part of the public API — always use them through their interfaces (IShopService, ICraftingService, IRewardService) and wire them via EconomyBootstrap.

Although the concrete implementations may evolve, the behavioural guarantees are stable:

  • All-or-nothing semantics (except where explicitly documented)
  • Deterministic rollback on failure
  • Consistent telemetry (reason + sourceId where supported)
  • Policy-aware money handling

Services


ShopService

Implements IShopService (buy / sell flows).

Buy flow

  1. Debit money via IValueLedger.
  2. Add delivered items via IItemStore.
  3. If anything fails:
  4. Undo prior item adds.
  5. Refund money.

Sell flow

  1. Remove items via IItemStore.
  2. Credit money via IValueLedger.
  3. If payout fails:
  4. Add removed items back.

Telemetry

  • All currency operations propagate sourceId.
  • Item rollbacks never propagate sourceId (limitation of IItemStore).

Example

var result = shop.Buy(
    player,
    ledger,
    store,
    priceBundle,
    deliverItems,
    "VendorA",
    "req123"
);

if (!result.Success)
    Debug.LogWarning(result);

CraftingService

Implements ICraftingService.

Flow

  1. Debit money (money-only bundle).
  2. Remove ingredient items.
  3. Add the crafted result item.
  4. On any failure:
  5. Roll back removed ingredients.
  6. Refund money (if any was charged).

Telemetry

  • Currency operations propagate sourceId.
  • Item operations do not propagate sourceId.

Example

var cost = new PriceBundle(moneyLines, ingredientLines);
var output = new ItemLine("crafted_sword", 1);

var result = crafting.Craft(
    player,
    ledger,
    store,
    in cost,
    in output
);

RewardService

Implements IRewardService.

Flow

  1. Credit money first.
  2. Attempt to add reward items (optional).

Important — asymmetric by design

  • Money is granted first and is never rolled back if item delivery fails.
  • Rewards are intentionally money-favouring.
  • If you need fully reversible flows, use Shop or Crafting instead of Reward.

Telemetry

  • Currency operations propagate sourceId.
  • Item operations do not propagate sourceId.

Example

var payout = PriceBundle.MoneyOnly(
    new[] { new ChargeLine("gold", 100) }
);

var result = rewards.Grant(player, ledger, store, in payout);

Usage guidelines

  • Always access services via EconomyBootstrap.BuildForPlayer.
  • Depend only on the interfaces:
  • IShopService
  • ICraftingService
  • IRewardService
  • Do not instantiate concrete services directly.
  • Services are stateless — it is safe for the facade to create fresh instances.
  • Teaching panels and demo scenes unroll these flows step-by-step for inspection.

Best practices

  • Treat each service call as a transaction:
  • Success → fully applied
  • Failure → clean rollback
  • Always check EcoOpResult.Success before applying gameplay consequences.
  • Use canonical telemetry (EcoReasons.* + sourceId) for auditability and analytics.
  • Prefer preflight via ledger.CanPay() to drive UI enable/disable states.

Stability

  • Service behaviour is stable within a major version.
  • Internal implementation details may change without notice.
  • Public contracts are defined exclusively by the interfaces.

See Also