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