Economy API usage.
Every function the library exposes, with the code that calls it. The server computes and validates every balance; the client only ever displays what the server has decided.
Server API — EconomyProvider
The single entry point trusted server modules (Market, Trading,
Rewards) require. Every mutating call returns a
MutationResult — branch on .ok, do not
rely on raised errors.
local ServerScriptService = game:GetService("ServerScriptService")
local EconomyProvider = require(ServerScriptService.Server.EconomyProvider)
-- Give a player currency.
local result = EconomyProvider.addMoney(player.UserId, "gold", 50)
if result.ok then
print("New gold balance:", result.balance)
else
warn("Add failed:", result.reason)
end
-- Charge a player. Fails without mutating if funds are insufficient.
local charge = EconomyProvider.minusMoney(player.UserId, "coin", 10)
if not charge.ok then
warn(charge.reason) -- e.g. "insufficient funds"
end
-- Read a single balance, or the whole wallet.
local gold = EconomyProvider.getBalance(player.UserId, "gold") or 0
local wallet = EconomyProvider.getWallet(player.UserId)
-- Pre-check affordability before a purchase (not atomic; re-check with minusMoney).
if EconomyProvider.canAfford(player.UserId, "gold", price) then
local purchase = EconomyProvider.minusMoney(player.UserId, "gold", price)
if purchase.ok then grantItem(player) end
end
Currency Registry — EconomyProvider & CurrencyConfig
Four base currencies (coin, copper,
silver, gold) always exist. Register a
custom currency on both sides so the client can
label it — the server through EconomyProvider, the
client through CurrencyConfig directly.
-- Server: registered through the EconomyProvider facade.
EconomyProvider.registerCurrency({ id = "gem", displayName = "Gem", max = 1_000_000 })
-- Client: EconomyProvider does not exist here, so register through CurrencyConfig.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CurrencyConfig = require(ReplicatedStorage.EconomyShared.CurrencyConfig)
CurrencyConfig.register({ id = "gem", displayName = "Gem", max = 1_000_000 })
-- Either side: list or look up currencies.
for _, definition in CurrencyConfig.all() do
print(definition.displayName, definition.default, definition.max)
end
Client API — WalletController (read-only)
The client never mutates a balance and never decides one — it only
mirrors what the server already replicated. There is no
addMoney here on purpose.
local StarterPlayerScripts = game:GetService("StarterPlayer").StarterPlayerScripts
local WalletController = require(StarterPlayerScripts.Client.WalletController)
-- Last synced balance, or the currency's default if nothing has synced yet.
local gold = WalletController.getBalance("gold")
-- React to every change the server pushes.
local disconnect = WalletController.onChanged(function(currency, balance)
if currency == "gold" then
updateGoldLabel(balance)
end
end)
-- later: disconnect()