Skip to content

Trading

DredBaron edited this page Aug 4, 2026 · 2 revisions

Overview

The Trade system lets accounts on the same OpenMTG instance propose and complete card trades. When both sides confirm, cards transfer automatically between collections. Trade history is stored separately from your card inventory and can be cleared independently.

Trades must be enabled by an admin before they appear in the UI. See Feature Toggles below.


Trade State Machine

A trade moves through the following states:

State Meaning
proposed Initiator created the trade and added their cards. Counterpart has not yet responded.
active Counterpart added their cards. Both sides can edit or confirm.
accepted Both parties confirmed. Cards have been transferred.
rejected Counterpart declined the trade.
cancelled Initiator cancelled before the counterpart responded.

Any edit to either side's card list (while active) resets both confirmation flags, requiring both users to confirm again.


Workflow

Proposing a trade

  1. Go to Trades in the sidebar.
  2. Click New Trade.
  3. Select the user you want to trade with.
  4. Use the card picker to select cards from your own collection to offer.
  5. Submit the proposal. The trade enters proposed state.

Counterpart response

The counterpart sees a "Your Turn" indicator on the Trades page and a ! badge on the Trades nav link.

  1. Open the trade from the Trades list.
  2. Add cards from your collection to your side of the offer.
  3. Review the initiator's offer on the right panel (read-only).
  4. Confirm or reject the trade.

Editing and confirming

  • Either party can add or remove cards from their own side while the trade is active.
  • Any edit resets both confirmation flags.
  • Click Confirm when satisfied with both sides.
  • Click Un-submit to retract your confirmation and make further changes.
  • Once both parties have confirmed, the transfer executes automatically.

Viewing card photos

In TradeDetail, each card in the counterpart's offer has a Camera button. Clicking it opens a viewer showing the front and back photos that user uploaded for that card entry, if any.


Auto-Transfer

When both parties confirm:

  1. The server validates that each card being offered still exists in the source collection in the required quantity.
  2. For each card transferred:
    • The source entry's quantity is decremented. If it reaches zero, the entry is deleted.
    • The destination collection is searched for a matching entry (same card, foil flag, condition, and language). If found, quantity is incremented. If not found, a new entry is created.
  3. The entire operation is atomic. If any validation fails, no cards move.

Trade items store a denormalized snapshot of each card (name, image, price, foil, condition) at the time of the trade. This means trade history remains accurate even if cards are later edited or deleted.


Trades Page

The Trades list page has two sections:

  • Active - trades in proposed or active state that involve you.
  • History - completed trades (accepted, rejected, cancelled).

Status is shown with color badges. A "Your Turn" label appears on any trade that requires your action.

The Trades nav link in the sidebar and mobile menu shows a ! badge when any trade is waiting on you.


Feature Toggles

An admin can enable or disable Trades from Admin > Settings > Feature Toggles.

When disabled:

  • The Trades nav link is hidden for all users.
  • Trade pages redirect to /collection.
  • The pending count endpoint returns 0.

Data Storage

Trade history is stored in a separate SQLite database, independent of the main PostgreSQL inventory.

Setting Default
Database location TRADES_PATH env var (default ./trades); file is trades.db inside that directory

Deleting the trades database removes all trade history without affecting any card data in PostgreSQL. See Configuration Reference for the TRADES_PATH variable.


API Endpoints

Method Path Description
GET /trades/pending-count Number of trades awaiting your action (used for the nav badge)
GET /trades List active trades and history, up to 50
POST /trades Propose a new trade
GET /trades/{id} Trade detail
PUT /trades/{id}/items Replace your side's items; resets both confirmation flags
POST /trades/{id}/confirm Confirm your side; executes transfer if both sides are confirmed
POST /trades/{id}/unconfirm Retract your confirmation
POST /trades/{id}/reject Reject (counterpart) or cancel (initiator) the trade
GET /trades/{id}/photos/{entry_id}/{side} Serve a card photo to either trade participant

All endpoints require authentication. The photo endpoint is accessible to both participants in the trade, not just the card owner.

Clone this wiki locally