diff --git a/docs/FIFA17_TRANSFER_MARKET_WIRE.md b/docs/FIFA17_TRANSFER_MARKET_WIRE.md index 9a5f45d..93ac838 100644 --- a/docs/FIFA17_TRANSFER_MARKET_WIRE.md +++ b/docs/FIFA17_TRANSFER_MARKET_WIRE.md @@ -196,3 +196,76 @@ moved and an auction could never run out. Now derived from `created_at + duratio (duration taken from the `ISStart` body), clamped at 0, with an aged-out active listing projecting as `expired`/`none` — FIFA 17's relistable state. Verified live: the standing listing correctly reads `expires: 0` once past its hour. + +--- + +## RESOLVED against the live client — 2026-08-17 (supersedes the tags above) + +Driven by the real FIFA 17 client end to end: list → expire → **relist** → active, +with the operator confirming each UI state. Live-client behaviour OUTRANKS both the +Python oracle and contemporaneous Web App implementations wherever they disagree. + +### `tradeOwner` — do not re-litigate this + +```text +tradeOwner exists in the FIFA 17-era FUT API: + FIFA17-HISTORICAL + +tradeOwner required by FIFA17.exe Transfer List Actions: + DISPROVEN for the current client path +``` + +It is absent from the twelve atoms FIFA 17's `auctionInfo` deserializer +(`0x18013e410`) reads, so the client value-SKIPs it at `0x180135ff0`. It was +implemented, deployed, observed to change nothing, and REMOVED. A future agent +rediscovering the old Web App sources will find this note before spending +deployments on it again. + +### What actually gated the Actions panel — all lifecycle/state bugs + +```text +CONFIRMED — FIFA17.exe live client + +Own Transfer List interactivity does NOT depend on tradeOwner in this path. + +trade/status polling is LOAD-BEARING for Transfer List state. The tail carries no +numeric id, so it fell through the `trade…` buy/view arm and answered every poll +with an empty auctionInfo. Route is ISVIEWTRADE: + GET ut/{ns}/trade/status?tradeIds=a,b,c + +auctionInfo.expires is SECONDS REMAINING *and must evolve with wall-clock time*. +A structurally valid but FROZEN value breaks lifecycle behaviour: the auction never +ages into expired/relistable, which is the state where Re-list appears. + +Relisting must PERSIST. FIFA 17 relists by re-sending ISStart (POST /auctionhouse) +for an item that already has a listing row, so the primary-key conflict IS the +relist. Swallowing it as success left the stale expired row intact and produced a +client-visible lifecycle failure behind an HTTP 200. +``` + +### Known-good own active auction (frozen fixture) + +Captured at `docs/evidence/market-lifecycle-2026-08-17/`, including +`_index.json._countdown_proof` which records `expires` decrementing (`frozen: +false`) so the live clock is machine-checkable rather than asserted in prose. + +```text +tradeState = active +bidState = none +expires = decrementing (seconds remaining) +sellerName = CAGE +auction record = 12 atoms +response envelope = 4 members (auctionInfo, credits, duplicateItemIdList, total) +ISViewTrade body = 2 members (auctionInfo, credits) +pricelimits = BARE ARRAY (container type is load-bearing) +``` + +**Do not "improve" this shape without a live-client retest.** + +### The development rule this established + +A response can be structurally plausible, pass differential parity, and render +perfectly while still being behaviourally wrong, because FIFA expects an **evolving +server-side state machine** rather than a static object that looks like one. The +frozen `expires` is the canonical example: every field was the right name, type and +vocabulary, and the feature was still broken. diff --git a/docs/evidence/market-lifecycle-2026-08-17/_index.json b/docs/evidence/market-lifecycle-2026-08-17/_index.json new file mode 100644 index 0000000..e84cf25 --- /dev/null +++ b/docs/evidence/market-lifecycle-2026-08-17/_index.json @@ -0,0 +1,38 @@ +{ + "_countdown_proof": { + "delta": -4, + "expires_after_4s": 2216, + "expires_first": 2220, + "frozen": false + }, + "auctionhouse-browse": { + "container": "object", + "path": "/auctionhouse", + "status": 200 + }, + "marketdata-pricelimits": { + "container": "array", + "path": "/marketdata/pricelimits?defId=20801", + "status": 200 + }, + "trade-status-filtered": { + "container": "object", + "path": "/trade/status?tradeIds=1000000097", + "status": 200 + }, + "trade-status-unfiltered": { + "container": "object", + "path": "/trade/status", + "status": 200 + }, + "tradePile": { + "container": "object", + "path": "/tradePile", + "status": 200 + }, + "tradePile-counts": { + "container": "object", + "path": "/tradePile/counts", + "status": 200 + } +} diff --git a/docs/evidence/market-lifecycle-2026-08-17/auctionhouse-browse.json b/docs/evidence/market-lifecycle-2026-08-17/auctionhouse-browse.json new file mode 100644 index 0000000..9d82d87 --- /dev/null +++ b/docs/evidence/market-lifecycle-2026-08-17/auctionhouse-browse.json @@ -0,0 +1,73 @@ +{ + "auctionInfo": [ + { + "bidState": "none", + "buyNowPrice": 15000, + "coinsProcessed": 0, + "currentBid": 0, + "expires": 2220, + "itemData": { + "assetId": 20801, + "attributeList": [ + { + "index": 0, + "value": 92 + }, + { + "index": 1, + "value": 92 + }, + { + "index": 2, + "value": 81 + }, + { + "index": 3, + "value": 91 + }, + { + "index": 4, + "value": 33 + }, + { + "index": 5, + "value": 80 + } + ], + "cardassetid": 20801, + "cardsubtypeid": 0, + "contract": 7, + "definitionId": 20801, + "discardValue": 1500, + "fitness": 99, + "id": 100000097, + "itemState": "forSale", + "itemType": "player", + "leagueId": 53, + "nation": 38, + "owners": 1, + "playStyle": 250, + "preferredPosition": "LW", + "rareflag": 1, + "rating": 94, + "resourceId": 20801, + "teamid": 243, + "untradeable": false + }, + "sellerEstablished": 1, + "sellerName": "CAGE", + "startingBid": 150, + "tradeId": 1000000097, + "tradeState": "active", + "watched": false + } + ], + "count": 0, + "credits": 29843976, + "duplicateItemIdList": [], + "maxAuctionsAllowed": 100, + "offered": 0, + "selling": 1, + "sold": 0, + "total": 1 +} diff --git a/docs/evidence/market-lifecycle-2026-08-17/marketdata-pricelimits.json b/docs/evidence/market-lifecycle-2026-08-17/marketdata-pricelimits.json new file mode 100644 index 0000000..9483d33 --- /dev/null +++ b/docs/evidence/market-lifecycle-2026-08-17/marketdata-pricelimits.json @@ -0,0 +1,7 @@ +[ + { + "defId": 20801, + "maxPrice": 15000, + "minPrice": 150 + } +] diff --git a/docs/evidence/market-lifecycle-2026-08-17/trade-status-filtered.json b/docs/evidence/market-lifecycle-2026-08-17/trade-status-filtered.json new file mode 100644 index 0000000..55d702b --- /dev/null +++ b/docs/evidence/market-lifecycle-2026-08-17/trade-status-filtered.json @@ -0,0 +1,66 @@ +{ + "auctionInfo": [ + { + "bidState": "none", + "buyNowPrice": 15000, + "coinsProcessed": 0, + "currentBid": 0, + "expires": 2220, + "itemData": { + "assetId": 20801, + "attributeList": [ + { + "index": 0, + "value": 92 + }, + { + "index": 1, + "value": 92 + }, + { + "index": 2, + "value": 81 + }, + { + "index": 3, + "value": 91 + }, + { + "index": 4, + "value": 33 + }, + { + "index": 5, + "value": 80 + } + ], + "cardassetid": 20801, + "cardsubtypeid": 0, + "contract": 7, + "definitionId": 20801, + "discardValue": 1500, + "fitness": 99, + "id": 100000097, + "itemState": "listFS", + "itemType": "player", + "leagueId": 53, + "nation": 38, + "owners": 1, + "playStyle": 250, + "preferredPosition": "LW", + "rareflag": 1, + "rating": 94, + "resourceId": 20801, + "teamid": 243, + "untradeable": false + }, + "sellerEstablished": 1, + "sellerName": "CAGE", + "startingBid": 150, + "tradeId": 1000000097, + "tradeState": "active", + "watched": false + } + ], + "credits": 29843976 +} diff --git a/docs/evidence/market-lifecycle-2026-08-17/trade-status-unfiltered.json b/docs/evidence/market-lifecycle-2026-08-17/trade-status-unfiltered.json new file mode 100644 index 0000000..55d702b --- /dev/null +++ b/docs/evidence/market-lifecycle-2026-08-17/trade-status-unfiltered.json @@ -0,0 +1,66 @@ +{ + "auctionInfo": [ + { + "bidState": "none", + "buyNowPrice": 15000, + "coinsProcessed": 0, + "currentBid": 0, + "expires": 2220, + "itemData": { + "assetId": 20801, + "attributeList": [ + { + "index": 0, + "value": 92 + }, + { + "index": 1, + "value": 92 + }, + { + "index": 2, + "value": 81 + }, + { + "index": 3, + "value": 91 + }, + { + "index": 4, + "value": 33 + }, + { + "index": 5, + "value": 80 + } + ], + "cardassetid": 20801, + "cardsubtypeid": 0, + "contract": 7, + "definitionId": 20801, + "discardValue": 1500, + "fitness": 99, + "id": 100000097, + "itemState": "listFS", + "itemType": "player", + "leagueId": 53, + "nation": 38, + "owners": 1, + "playStyle": 250, + "preferredPosition": "LW", + "rareflag": 1, + "rating": 94, + "resourceId": 20801, + "teamid": 243, + "untradeable": false + }, + "sellerEstablished": 1, + "sellerName": "CAGE", + "startingBid": 150, + "tradeId": 1000000097, + "tradeState": "active", + "watched": false + } + ], + "credits": 29843976 +} diff --git a/docs/evidence/market-lifecycle-2026-08-17/tradePile-counts.json b/docs/evidence/market-lifecycle-2026-08-17/tradePile-counts.json new file mode 100644 index 0000000..ec3d183 --- /dev/null +++ b/docs/evidence/market-lifecycle-2026-08-17/tradePile-counts.json @@ -0,0 +1,7 @@ +{ + "count": 1, + "maxAuctionsAllowed": 100, + "offered": 0, + "selling": 1, + "sold": 0 +} diff --git a/docs/evidence/market-lifecycle-2026-08-17/tradePile.json b/docs/evidence/market-lifecycle-2026-08-17/tradePile.json new file mode 100644 index 0000000..ead56c0 --- /dev/null +++ b/docs/evidence/market-lifecycle-2026-08-17/tradePile.json @@ -0,0 +1,68 @@ +{ + "auctionInfo": [ + { + "bidState": "none", + "buyNowPrice": 15000, + "coinsProcessed": 0, + "currentBid": 0, + "expires": 2220, + "itemData": { + "assetId": 20801, + "attributeList": [ + { + "index": 0, + "value": 92 + }, + { + "index": 1, + "value": 92 + }, + { + "index": 2, + "value": 81 + }, + { + "index": 3, + "value": 91 + }, + { + "index": 4, + "value": 33 + }, + { + "index": 5, + "value": 80 + } + ], + "cardassetid": 20801, + "cardsubtypeid": 0, + "contract": 7, + "definitionId": 20801, + "discardValue": 1500, + "fitness": 99, + "id": 100000097, + "itemState": "listFS", + "itemType": "player", + "leagueId": 53, + "nation": 38, + "owners": 1, + "playStyle": 250, + "preferredPosition": "LW", + "rareflag": 1, + "rating": 94, + "resourceId": 20801, + "teamid": 243, + "untradeable": false + }, + "sellerEstablished": 1, + "sellerName": "CAGE", + "startingBid": 150, + "tradeId": 1000000097, + "tradeState": "active", + "watched": false + } + ], + "credits": 29843976, + "duplicateItemIdList": [], + "total": 1 +}