diff --git a/SVSim.Database/Services/Inventory/IInventoryTransaction.cs b/SVSim.Database/Services/Inventory/IInventoryTransaction.cs
index 1ba2059..b3b70f7 100644
--- a/SVSim.Database/Services/Inventory/IInventoryTransaction.cs
+++ b/SVSim.Database/Services/Inventory/IInventoryTransaction.cs
@@ -17,11 +17,30 @@ public interface IInventoryTransaction : IAsyncDisposable
Viewer Viewer { get; }
bool IsFreeplay { get; }
+ ///
+ /// Debits one of the four scalar wallets. Freeplay-aware for Crystal/Rupee/RedEther
+ /// (returns Success with the configured freeplay amount, balance unchanged); SpotPoint
+ /// always real. Returns with current balance on
+ /// failure; viewer state is not mutated on failure.
+ ///
Task TrySpendAsync(SpendCurrency currency, long cost, CancellationToken ct = default);
+
+ ///
+ /// Type-dispatched debit. Currencies (RedEther/Crystal/Rupy/SpotCardPoint) route to
+ /// ; Item decrements OwnedItemEntry.Count. Returns
+ /// whose PostStateTotal is the new wallet balance for
+ /// currencies and the remaining item count for Item.
+ ///
Task TryDebitAsync(UserGoodsType type, long detailId, int num, CancellationToken ct = default);
+
Task> GrantAsync(UserGoodsType type, long detailId, int num, CancellationToken ct = default);
Task BackfillCardCosmeticsAsync(CancellationToken ct = default);
+ ///
+ /// Freeplay-aware balance read against the live viewer; reflects any spends queued in
+ /// this transaction. Inside a transaction, use this; outside, use
+ /// .
+ ///
long EffectiveBalance(SpendCurrency currency);
bool OwnsCard(long cardId);
bool OwnsCosmetic(CosmeticType type, int id);