Domain model
Vocabulary (use these words in code and specs)
- Leaf — a node in the dependency tree not crafted further in our plan; it is bought or supplied.
- Buyable — obtainable on the Trading Post. Priced via
/v2/commerce/prices. - Gated input — account-bound or earned, not on the TP (Gift of Exploration, Gift of Battle, Bloodstone Shard, Obsidian Shards, Mystic Clovers). A time cost, not a gold cost. Classified programmatically from the item's
flags[]. - Forge node — a Mystic Forge combine step.
net_sell— the finished legendary's TP price minus the fixed 15% TP tax (5% listing + 10% exchange). The tax is hardcoded; it is not an API field.- Profit —
net_sell − Σ cost(buyable leaves), with gated inputs treated as player-supplied.
Hard facts (do not re-litigate)
- The Mystic Forge is not a crafting discipline, so no Forge recipe exists in
/v2/recipes. Every legendary combine step comes from a curated, version-controlled dataset sourced from the GW2 Wiki. That dataset is this project's key maintenance point — game patches drift it. It must be typed, schema-validated by a test, and changed only deliberately. - Cost resolution is recursive:
cost = min(buy_price, Σ children craft cost).
Legendary types & the curated dataset (graduated from spec 006)
Verified against the live API + GW2 Wiki on 2026-07-27/28 (specs/006-static-data/research.md).
- One universal shape. Almost every legendary is a ~4-ingredient Mystic Forge combine: all three weapon generations, the trinkets (e.g. Aurora), the back items (e.g. Ad Infinitum), and legendary runes. Only legendary armor is different — discipline-crafted (Armorsmith/Leatherworker/Tailor) + vendor, consuming currencies as well as items. The curated recipe schema is therefore a general
outputItemId + ingredients[] + method + sourcelist (no fixed precursor/gift slots), withmethodreservingdiscipline/vendor/collectionand an ingredient kind reservingcurrencyfor the armor/trinket work. (F6/F9.) - Sellability is a per-item
/v2/commerce/pricesfact, NOT a per-generation rule. Gen 1 and Gen 3 weapons are TP-sellable; Gen 2 weapons are account-bound, as are all armor, trinkets, and back items. Sonet_sell/the craft-for-profit persona applies to Gen 1 + Gen 3 weapons only; everything else is craft-for-self (cost + time, no resale). Never hardcode "generation ⇒ sellable" — read commerce/prices. (F7.) - Shared gifts are reused across types (Gift of Fortune → Gen 1 weapons and Ad Infinitum; Mystic Tribute → Gen 2 weapons and Aurora). A flat curated table keyed by
outputItemIdstores each shared node once; adding a legendary type is adding rows, not restructuring. (F8.) - Buyable-vs-gated classifier:
gated ⟺ item flags[] includesAccountBound`` specifically.SoulBindOnUse/NoSell/AccountBindOnUsealone do not imply gated (e.g. The Legend is TP-buyable despiteNoSell+SoulBindOnUse)./v2/commerce/pricesmembership is the authoritative ground truth the pricing layer reads; the flag rule is the fast static proxy. (F2/V4.) - Home of the curated data:
packages/legendary-recipes— a JSON dataset (the api loads it at runtime) plus a Zod schema + validated loader (the guard test validates the JSON in CI). Spec 006 curates all 21 Gen 1 weapons; the schema is future-proofed for the rest.
See docs/project-brief.md for the full domain write-up (API surface, legendary structure, profit model).