Godot 4 · GDScript
Currency & purchases
Gamdato ships with an economy: virtual currencies the player buys with real money (via Stripe), and items they acquire by spending those currencies. Everything is defined in the panel and consumed from the addon.
Panel Configuration
In the panel you define three things: your game currencies (e.g. "gems"), top-up packs (a SKU with a USD price that grants X currency via Stripe), and purchasable items (a SKU with its currency cost and grant rules).
Save the SKU of each pack and item: these are the identifiers you pass to buy_pack() and purchase().
Read Balances
Request the player balances and the currency catalog. The result arrives through the balances_loaded signal.
Gamdato.balances_loaded.connect(_on_balances)
Gamdato.get_balances()
func _on_balances(balances: Array, currencies: Array) -> void:
for b in balances:
print("%s: %d" % [b.currency_id, b.balance])# balances: Array, each:
{
"currency_id": String,
"balance": int
}
# currencies: Array, the catalog you defined in the panel:
{
"id": String,
"code": String,
"display_name": String,
"icon_url": String,
"is_active": bool
}
# "code" is the currency code you pass to get_currency_leaderboard().Buy Currency (Stripe)
Start a top-up pack purchase. The addon opens Stripe Checkout in the system browser; on return, balances are updated server-side. The topup_started signal confirms the URL was opened.
Gamdato.topup_started.connect(_on_topup)
Gamdato.buy_pack("premium_pack")
func _on_topup(ok: bool, url: String, error_code: String) -> void:
if ok: print("Checkout opened: %s" % url)
else: print("Error: %s" % error_code)Spend Currency
Spend the player currency on an item. The server validates the balance and applies the grant rules atomically. The result arrives through purchase_completed.
Gamdato.purchase_completed.connect(_on_purchase)
Gamdato.purchase("sword_skin")
func _on_purchase(ok: bool, sku: String, result: Dictionary, error_code: String) -> void:
if ok: print("Bought %s. Balances: %s" % [sku, result.balances])
else: print("Failed: %s" % error_code)error_code may be insufficient_funds, already_owned or item_not_found. Pass an idempotency_key to avoid double charges on retry.
Player Inventory
List the items the player owns. Useful to unlock content when the game starts. Arrives through inventory_loaded.
Gamdato.inventory_loaded.connect(_on_inventory)
Gamdato.get_inventory()
func _on_inventory(items: Array) -> void:
for it in items:
print("Owns: %s (%s)" % [it.item_id, it.source])# items: Array, each owned item:
{
"item_id": String,
"source": String,
"acquired_at": String,
"metadata": Dictionary
}
# Rows also include internal ids (id, player_id, game_id).Transaction History
List the player recent currency movements (grants, purchases, top-ups), newest first. Arrives through ledger_loaded.
Gamdato.ledger_loaded.connect(_on_ledger)
Gamdato.get_ledger() # or get_ledger(50, 0)
func _on_ledger(entries: Array) -> void:
for e in entries:
print("%s %+d -> %d" % [e.op_type, e.delta, e.balance_after])# entries: Array, newest first:
{
"id": String,
"currency_id": String,
"delta": int,
"balance_after": int,
"op_type": String,
"created_at": String
}
# Rows also include internal ids/metadata (player_id, game_id, ref_kind, ref_value, idempotency_key, metadata).Currency Leaderboard
A ranking of players by currency balance (must be enabled for that currency in the panel). Pass the currency code. Arrives through currency_leaderboard_loaded.
Gamdato.currency_leaderboard_loaded.connect(_on_currency_lb)
Gamdato.get_currency_leaderboard("gems")
func _on_currency_lb(code: String, entries: Array) -> void:
for row in entries:
print("#%d %s %d" % [row.rank, row.player_name, row.balance])# entries: Array, ordered by balance, highest first:
{
"rank": int,
"player_id": String,
"player_name": String,
"balance": int
}Grant Currency (Rewards in Code)
Give the player currency from a reason you defined in the panel (a quest payout, a level-up bonus...). Pass the reason key. Arrives through grant_completed.
Gamdato.grant_completed.connect(_on_grant)
Gamdato.grant_currency("quest_reward")
func _on_grant(ok: bool, reason_key: String, result: Dictionary, error_code: String) -> void:
if ok: print("Granted! Balances: %s" % result.get("balances"))
else: print("Failed: %s" % error_code)Grants are defined in the panel by a reason key and may have cooldowns or caps. This is for in-game rewards, not real-money purchases (use buy_pack for those).