Skip to main content

egs_api/facade/
store.rs

1use crate::EpicGames;
2use crate::api::error::EpicAPIError;
3use crate::api::types::asset_info::AssetInfo;
4use crate::api::types::billing_account::BillingAccount;
5use crate::api::types::catalog_item::CatalogItemPage;
6use crate::api::types::catalog_offer::CatalogOfferPage;
7use crate::api::types::currency::CurrencyPage;
8use crate::api::types::price::PriceResponse;
9use crate::api::types::quick_purchase::QuickPurchaseResponse;
10use crate::api::types::uplay::{
11    UplayClaimResult, UplayCodesResult, UplayGraphQLResponse, UplayRedeemResult,
12};
13
14impl EpicGames {
15    /// Like [`catalog_items`](Self::catalog_items), but returns a `Result` instead of swallowing errors.
16    pub async fn try_catalog_items(
17        &self,
18        namespace: &str,
19        start: i64,
20        count: i64,
21    ) -> Result<CatalogItemPage, EpicAPIError> {
22        self.egs.catalog_items(namespace, start, count).await
23    }
24
25    /// Fetch paginated catalog items for a namespace.
26    ///
27    /// Queries the Epic catalog service for items within a given namespace
28    /// (e.g., a game's namespace). Results are paginated — use `start` and
29    /// `count` to page through. Each [`CatalogItemPage`] includes a `paging`
30    /// field with the total count.
31    ///
32    /// Returns `None` on API errors.
33    pub async fn catalog_items(
34        &self,
35        namespace: &str,
36        start: i64,
37        count: i64,
38    ) -> Option<CatalogItemPage> {
39        self.try_catalog_items(namespace, start, count).await.ok()
40    }
41
42    /// Like [`catalog_offers`](Self::catalog_offers), but returns a `Result` instead of swallowing errors.
43    pub async fn try_catalog_offers(
44        &self,
45        namespace: &str,
46        start: i64,
47        count: i64,
48    ) -> Result<CatalogOfferPage, EpicAPIError> {
49        self.egs.catalog_offers(namespace, start, count).await
50    }
51
52    /// Fetch paginated catalog offers for a namespace.
53    ///
54    /// Queries the Epic catalog service for offers (purchasable items) within
55    /// a namespace. Offers include pricing metadata, seller info, and linked
56    /// catalog items. Use `start` and `count` to paginate.
57    ///
58    /// Returns `None` on API errors.
59    pub async fn catalog_offers(
60        &self,
61        namespace: &str,
62        start: i64,
63        count: i64,
64    ) -> Option<CatalogOfferPage> {
65        self.try_catalog_offers(namespace, start, count).await.ok()
66    }
67
68    /// Like [`bulk_catalog_items`](Self::bulk_catalog_items), but returns a `Result` instead of swallowing errors.
69    pub async fn try_bulk_catalog_items(
70        &self,
71        items: &[(&str, &str)],
72    ) -> Result<
73        std::collections::HashMap<String, std::collections::HashMap<String, AssetInfo>>,
74        EpicAPIError,
75    > {
76        self.egs.bulk_catalog_items(items).await
77    }
78
79    /// Bulk fetch catalog items across multiple namespaces.
80    ///
81    /// Accepts a slice of `(namespace, item_id)` pairs and returns them grouped
82    /// by namespace → item_id → [`AssetInfo`]. Useful for resolving catalog
83    /// metadata for items from different games in a single request.
84    ///
85    /// Returns `None` on API errors.
86    pub async fn bulk_catalog_items(
87        &self,
88        items: &[(&str, &str)],
89    ) -> Option<std::collections::HashMap<String, std::collections::HashMap<String, AssetInfo>>>
90    {
91        self.try_bulk_catalog_items(items).await.ok()
92    }
93
94    /// Like [`currencies`](Self::currencies), but returns a `Result` instead of swallowing errors.
95    pub async fn try_currencies(
96        &self,
97        start: i64,
98        count: i64,
99    ) -> Result<CurrencyPage, EpicAPIError> {
100        self.egs.currencies(start, count).await
101    }
102
103    /// Fetch available currencies from the Epic catalog.
104    ///
105    /// Returns paginated currency definitions including code, symbol, and
106    /// decimal precision. Use `start` and `count` to paginate.
107    ///
108    /// Returns `None` on API errors.
109    pub async fn currencies(&self, start: i64, count: i64) -> Option<CurrencyPage> {
110        self.try_currencies(start, count).await.ok()
111    }
112
113    /// Like [`library_state_token_status`](Self::library_state_token_status), but returns a `Result` instead of swallowing errors.
114    pub async fn try_library_state_token_status(
115        &self,
116        token_id: &str,
117    ) -> Result<bool, EpicAPIError> {
118        self.egs.library_state_token_status(token_id).await
119    }
120
121    /// Check the validity of a library state token.
122    ///
123    /// Returns `Some(true)` if the token is still valid, `Some(false)` if
124    /// expired or invalid, or `None` on API errors. Library state tokens are
125    /// used to detect changes to the user's library since the last sync.
126    ///
127    /// Returns `None` on API errors.
128    pub async fn library_state_token_status(&self, token_id: &str) -> Option<bool> {
129        self.try_library_state_token_status(token_id).await.ok()
130    }
131
132    /// Like [`offer_prices`](Self::offer_prices), but returns a `Result` instead of swallowing errors.
133    pub async fn try_offer_prices(
134        &self,
135        namespace: &str,
136        offer_ids: &[String],
137        country: &str,
138    ) -> Result<PriceResponse, EpicAPIError> {
139        self.egs.offer_prices(namespace, offer_ids, country).await
140    }
141
142    /// Fetch offer prices from Epic's price engine.
143    ///
144    /// Queries current pricing for one or more offers within a namespace,
145    /// localized to a specific country. The response includes original price,
146    /// discount price, and pre-formatted display strings.
147    ///
148    /// Returns `None` on API errors.
149    pub async fn offer_prices(
150        &self,
151        namespace: &str,
152        offer_ids: &[String],
153        country: &str,
154    ) -> Option<PriceResponse> {
155        self.try_offer_prices(namespace, offer_ids, country)
156            .await
157            .ok()
158    }
159
160    /// Like [`quick_purchase`](Self::quick_purchase), but returns a `Result` instead of swallowing errors.
161    pub async fn try_quick_purchase(
162        &self,
163        namespace: &str,
164        offer_id: &str,
165    ) -> Result<QuickPurchaseResponse, EpicAPIError> {
166        self.egs.quick_purchase(namespace, offer_id).await
167    }
168
169    /// Execute a quick purchase (typically for free game claims).
170    ///
171    /// Initiates a purchase order for a free offer. The response contains the
172    /// order ID and its processing status. For paid offers, use the full
173    /// checkout flow in the Epic Games launcher instead.
174    ///
175    /// Returns `None` on API errors.
176    pub async fn quick_purchase(
177        &self,
178        namespace: &str,
179        offer_id: &str,
180    ) -> Option<QuickPurchaseResponse> {
181        self.try_quick_purchase(namespace, offer_id).await.ok()
182    }
183
184    /// Like [`billing_account`](Self::billing_account), but returns a `Result` instead of swallowing errors.
185    pub async fn try_billing_account(&self) -> Result<BillingAccount, EpicAPIError> {
186        self.egs.billing_account().await
187    }
188
189    /// Fetch the default billing account for payment processing.
190    ///
191    /// Returns the account's billing country, which is used to determine
192    /// regional pricing and payment availability.
193    ///
194    /// Returns `None` on API errors.
195    pub async fn billing_account(&self) -> Option<BillingAccount> {
196        self.try_billing_account().await.ok()
197    }
198
199    // ── Uplay / Ubisoft Store ──
200
201    /// Fetch Uplay codes linked to the user's Epic account.
202    pub async fn store_get_uplay_codes(
203        &self,
204    ) -> Result<UplayGraphQLResponse<UplayCodesResult>, EpicAPIError> {
205        self.egs.store_get_uplay_codes().await
206    }
207
208    /// Claim a Uplay code for a specific game.
209    pub async fn store_claim_uplay_code(
210        &self,
211        uplay_account_id: &str,
212        game_id: &str,
213    ) -> Result<UplayGraphQLResponse<UplayClaimResult>, EpicAPIError> {
214        self.egs
215            .store_claim_uplay_code(uplay_account_id, game_id)
216            .await
217    }
218
219    /// Redeem all pending Uplay codes for the user's account.
220    pub async fn store_redeem_uplay_codes(
221        &self,
222        uplay_account_id: &str,
223    ) -> Result<UplayGraphQLResponse<UplayRedeemResult>, EpicAPIError> {
224        self.egs.store_redeem_uplay_codes(uplay_account_id).await
225    }
226}