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+sourceIdwhere supported) - Policy-aware money handling
Services¶
ShopService¶
Implements IShopService (buy / sell flows).
Buy flow¶
- Debit money via
IValueLedger. - Add delivered items via
IItemStore. - If anything fails:
- Undo prior item adds.
- Refund money.
Sell flow¶
- Remove items via
IItemStore. - Credit money via
IValueLedger. - If payout fails:
- Add removed items back.
Telemetry¶
- All currency operations propagate
sourceId. - Item rollbacks never propagate
sourceId(limitation ofIItemStore).
Example¶
var result = shop.Buy(
player,
ledger,
store,
priceBundle,
deliverItems,
"VendorA",
"req123"
);
if (!result.Success)
Debug.LogWarning(result);
CraftingService¶
Implements ICraftingService.
Flow¶
- Debit money (money-only bundle).
- Remove ingredient items.
- Add the crafted result item.
- On any failure:
- Roll back removed ingredients.
- 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¶
- Credit money first.
- 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:
IShopServiceICraftingServiceIRewardService- 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.Successbefore 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.