Economy
View SourceAsobi provides a full virtual economy system: wallets, transactions, item definitions, a store catalog, and player inventory.
Wallets
Each player can have multiple wallets, one per currency. All balance changes are recorded as transactions for a full audit trail.
List Wallets
curl http://localhost:8080/api/v1/wallets \
-H 'Authorization: Bearer <token>'
[
{"id": "...", "currency": "gold", "balance": 1000},
{"id": "...", "currency": "gems", "balance": 50}
]Transaction History
curl http://localhost:8080/api/v1/wallets/gold/history \
-H 'Authorization: Bearer <token>'
Items
Items are defined once via asobi_item_def and granted to players as
asobi_player_item instances.
Item Definitions
Item definitions are global -- they describe what an item is:
slug-- unique identifier (e.g.,"sword_of_fire")name-- display namecategory-- weapon, armor, consumable, etc.rarity-- common, rare, epic, legendarystackable-- whether multiple instances stack into one slotmetadata-- arbitrary JSON for game-specific attributes
Player Inventory
curl http://localhost:8080/api/v1/inventory \
-H 'Authorization: Bearer <token>'
Consuming Items
curl -X POST http://localhost:8080/api/v1/inventory/consume \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"item_id": "...", "quantity": 1}'
Store
The store is a catalog of items available for purchase with in-game currency.
Browse Store
curl http://localhost:8080/api/v1/store \
-H 'Authorization: Bearer <token>'
[
{
"id": "...",
"item_def_id": "...",
"currency": "gold",
"price": 500,
"active": true
}
]Purchase
Purchases are atomic: the wallet is debited and the item is granted in a single database transaction via Kura Multi.
curl -X POST http://localhost:8080/api/v1/store/purchase \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"listing_id": "..."}'
Server-Side Operations
For admin or game logic that needs to grant/debit currency or items programmatically:
%% Grant currency
asobi_economy:grant(PlayerId, ~"gold", 100, #{reason => ~"match_reward"}).
%% Debit currency
asobi_economy:debit(PlayerId, ~"gold", 50, #{reason => ~"store_purchase"}).
%% Read a wallet (creates one with balance 0 if missing)
{ok, #{balance := Bal}} = asobi_economy:get_or_create_wallet(PlayerId, ~"gold").
%% Purchase a store listing (atomically debits wallet and grants item)
{ok, _} = asobi_economy:purchase(PlayerId, ListingId).All economy operations use ACID transactions to prevent double-spending or inconsistent state.