Major Patch - MARKETPLACE + CURRENCY EXCHANGE - v1.1.0

Spire of Ash · published

## TL;DR
- A full **player-to-player trade marketplace** is now live — list equipment, keys, and flasks for sale, browse and buy from other players, and exchange currencies in bulk via the order book.
- **Glyphs** are a new consumable currency socketable into keys at the Key Altar before a run, biasing loot toward specific goals (gold, rarity, element, currency type, etc.). 20 glyphs ship in this release.
- Bought/restored trade items now **correctly appear in your stash grid** — previously they were added to inventory but invisible until you manually moved them.
- Trade escrow logic is covered by a **33-test unit suite** verifying stash placement across all item kinds and multi-account flows.

## New Features

### Trade Marketplace
- Added the **Trade** tab to the run view with three sub-views: **Marketplace**, **Currency Exchange**, and **Trade History**.
- **Marketplace**: List any equipment, flask, or key for sale at a custom price in gold or orbs. Browse, filter, and buy listings from other players. Realtime Supabase subscriptions push new/sold/cancelled updates live.
- **Currency Exchange**: Post bulk buy/sell orders for any currency pair. Other players can fill your orders partially or fully. Order book sorted by best ratio.
- **Create Listing** modal lets you pick from your stash, set a price currency and amount, and list. Items are escrowed from your inventory on listing.
- **Advanced Filters**: filter marketplace by item kind, rarity, level range, slot, price range, and stat filters.
- **Trade History**: view your past sales, purchases, and cancelled listings.
- Payment collection happens passively — sold-item proceeds are credited on your next tab visit.
- Backend: 6 Supabase Edge Functions (`trade-create-listing`, `trade-buy-listing`, `trade-cancel-listing`, `trade-create-currency-order`, `trade-fill-currency-order`, `trade-cancel-currency-order`) with full RLS, audit logging, and expiry.
- Database: `trade_listings`, `currency_orders`, and `trade_log` tables with indexed queries for active listing browsing and user history.

### Glyph System
- **20 glyphs** added as a new currency kind, dropping globally from key level 15+.
- Glyphs socket into **up to 4 slots** on a key at the Key Altar (slots unlock at key levels 15/30/45/60). Consumed on run start.
- Glyph effects bias loot in a dungeon run:
- **Glyph of Wealth** (+40% gold), **Abundance** (+25% item quantity), **Fortune** (+30% item rarity)
- **Glyph of Uniques** (+80% unique chance), **Duplicates** (+15% duplicate chance), **Quality** (+20 base quality)
- **Armorer / Weaponsmith** (3× slot weight for armor/weapons)
- **Currencies / Orbs / Inscriptions / Sigils** (2–3× category weight)
- **Flames / Frost / Storms / Void / Aether** (2× elemental affix tag weight)
- **Keys** (+50% key drop rate), **Transmutation** (15% equipment→currency conversion)
- Glyph modifier pipeline integrated into `lootDropSystem`, `itemGeneration`, and combat `bootstrap` — affects gold find, item quantity/rarity/quality, unique/currency/key/aether drop rates, slot weights, currency category weights, and affix tag weights.
- UI: Glyph Slot Matrix rendered between the key altar and orb matrix in the Key Device panel. Inline picker for socketing/removing glyphs, showing owned counts and descriptions.
- 520-assertion test suite (`glyphEffects.test.ts`) covers resolver, slot thresholds, modifier aggregation, and loot integration.

## Bug Fixes
- **Trade stash visibility fix**: `restoreEquipmentItem` and `restoreKey` now create proper stash grid / key stash tab entries when items are restored from escrow (bought, cancelled, or payment-collected). Previously, items were pushed to the master inventory/key arrays but had no grid placement — making them invisible in the stash UI until manually rearranged.
- **Marketplace filter fix**: Advanced filters no longer incorrectly show equipment-specific controls when the "jewel" item kind is selected.
- **Marketplace cancel fix**: Cancel-listing escrow ID extraction simplified to always use `.id` from item data, fixing a potential crash path for skill gem listings.