Trading
Scope and Context
The trading service manages player credits inside a game. It opens and maintains bank accounts, issues vouchers that consume credits, and processes resource sales that add credits.
Trading integrates with external domains through events:
- Game (external): drives bank-account creation when players join games.
- Player (external): replicated for identity and traceability.
- Robot (external): delivery events trigger resource sale handling and credit deposits.
Aggregates and Responsibilities
BankAccount
The BankAccount aggregate manages balance changes for a unique (gameId, playerId) pair.
- Opens accounts for players in games.
- Deposits credits (for example from resource sales).
- Withdraws credits (for example for voucher purchases).
- Enforces credit and balance invariants.
Credits are treated as an in-game value type with arithmetic and comparison rules. From a domain perspective, credits are created/destroyed by operations in this service, rather than transferred through an external monetary system.
Voucher
The Voucher aggregate is the entry point for purchase intents.
- Supports purchase flows for:
ConstructRobotVoucherUpgradeRobotVoucher
- Validates request input.
- Computes total costs.
- Withdraws credits through
BankAccount. - Persists and emits issued vouchers.
Voucher-related constraints include:
- Construction vouchers require at least one robot.
- Upgrade vouchers require an allowed upgrade level range (currently
1..5). - Robot existence/capability checks are not performed by trading.
Prices / Pricing
The Prices (Pricing) component provides price information for purchasable/sellable items
and is used by resource sale flows. Pricing logic is separated from account mutation logic.
- Maintains resource value definitions.
- Resolves credit value for delivered resources.
- Prices are initialized with defaults at game creation, then controllable via rest.
- Publishes price-change related events
Core Use Cases
Opening a Bank Account (Automated)
When a player joins a game, trading opens a bank account with the configured starting balance.
Withdrawing Credits
Credits are withdrawn for paid actions (for example voucher purchases). Trading checks:
- Account exists for the player in the game.
- Balance is sufficient.
On success, trading emits:
CreditsWithdrawnBankAccountECST
On failure (for example insufficient credits), the caller receives a failure outcome and can inform the player.
Depositing Credits
Credits are deposited when players earn value, for example through resource deliveries.
On success, trading emits:
CreditsDepositedBankAccountECST
Buying Vouchers
Voucher purchase flow:
- Player intent is validated by
Voucher. - Total price is calculated.
BankAccountwithdrawal is attempted.- If successful, the voucher is persisted and emitted.
- If withdrawal fails, voucher issuance is rejected.
Typical emitted events include:
ConstructRobotVoucherIssued(or upgrade equivalent)CreditsWithdrawn(triggered through account mutation)BankAccountECST(triggered through account mutation)
Selling Resources
- Robot delivers resource
- Price is calculated
- Credits are deposited
Typical emitted events include:
ResourcesSoldCreditsDepositedBankAccountECST
Invariants and Business Rules
BankAccount Invariants
- Balance must never become negative.
- Credits are always positive values.
- A withdrawal must be at least one credit.
- There is at most one bank account per player and game.
Cross-Aggregate Rules
- Trading reacts to game events to create/open bank accounts.
- Trading assumes upstream events represent valid game/player existence.
- Trading does not validate robot ownership/existence for voucher upgrade targets.
Eventing and Integration Patterns
- Outgoing events generally extend a shared base event type to provide common headers.
- Event payloads are defined within the event type and exposed via builder/factory methods.
- Most events are published through a
WriteOutboxinterface backed by Postgres. - DLT publication is a notable exception where no transaction context may exist.
Functional Dependencies
Trading depends on inbound events from:
- Game service to detect participation and initialize bank accounts.
- Robot service to process resource deliveries and award credits.
It publishes outbound domain events so other services can react to financial state changes and vouchers.