From 3507c5714dc126554241324c368efc38dbab3e0c Mon Sep 17 00:00:00 2001 From: OpenFUT Agent Date: Thu, 13 Aug 2026 20:06:54 +0000 Subject: [PATCH] feat(fifa17): add purchase_items to host CoreEconomy client Complete the transport contract: purchase_items (atomic debit + mint N) on the CoreEconomy trait + HttpCoreClient (POST /economy/purchase-items) + FakeEconomy. This is the open-on-buy primitive the Store BUY handler will use (createPackResponse returns the minted itemList). Fail-closed like the rest of the client. --- openfut-utas-host/src/lib.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/openfut-utas-host/src/lib.rs b/openfut-utas-host/src/lib.rs index e3e5242..60e877c 100644 --- a/openfut-utas-host/src/lib.rs +++ b/openfut-utas-host/src/lib.rs @@ -399,6 +399,8 @@ pub trait CoreEconomy: Send + Sync { fn sell_item(&self, item_id: &str, price: i64) -> Result; fn grant_reward(&self, amount: i64) -> Result; fn purchase_item(&self, cost: i64, item_id: &str, card_id: &str) -> Result; + /// Debit `cost` and mint several items atomically (open-on-buy Store packs). + fn purchase_items(&self, cost: i64, items: &[EconomyGrantItem]) -> Result; } impl HttpCoreClient { @@ -517,6 +519,18 @@ impl CoreEconomy for HttpCoreClient { )?; json_i64(&v, "balance") } + + fn purchase_items(&self, cost: i64, items: &[EconomyGrantItem]) -> Result { + let items_json: Vec = items + .iter() + .map(|i| json!({ "item_id": i.item_id, "card_id": i.card_id })) + .collect(); + let v = self.economy_post( + "purchase-items", + &json!({ "cost": cost, "items": items_json }), + )?; + json_i64(&v, "balance") + } } /// Serialize a [`CoreReplaceRequest`] into the `PUT /squad/replace` JSON body. @@ -2215,6 +2229,16 @@ mod tests { } Ok(self.balance) } + fn purchase_items( + &self, + _cost: i64, + _items: &[EconomyGrantItem], + ) -> Result { + if self.fail { + return Err(CoreError::Status(500)); + } + Ok(self.balance) + } } #[test]