@xoxno/types 1.0.368 → 1.0.370

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,961 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CacheIndexKeys = exports.CachePatterns = exports.CacheKeys = void 0;
4
+ const ttl_1 = require("./ttl");
5
+ /**
6
+ * Helper function for serializing ActivityChain arrays in cache keys.
7
+ */
8
+ function serializeChain(chain) {
9
+ return (chain ?? []).sort().join(',');
10
+ }
11
+ /**
12
+ * Cache key generators for commonly used patterns.
13
+ * These ensure consistent key formats across repositories.
14
+ */
15
+ exports.CacheKeys = {
16
+ // ==========================================
17
+ // User-related cache keys
18
+ // ==========================================
19
+ UserProfile: (address) => ({
20
+ key: `user:${address}:profile`,
21
+ ttl: ttl_1.TTLS.ONE_DAY * 3,
22
+ }),
23
+ UserSettings: (address) => ({
24
+ key: `user:${address}:settings`,
25
+ ttl: ttl_1.TTLS.ONE_YEAR,
26
+ }),
27
+ UserInventorySummary: (address, activeAuction) => ({
28
+ key: `user:${address}:inventory:summary:${activeAuction}`,
29
+ ttl: ttl_1.TTLS.ONE_MINUTE * 10,
30
+ }),
31
+ UserHerotag: (address) => ({
32
+ key: `user:${address}:herotag`,
33
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
34
+ }),
35
+ UserFavorite: (address, favoriteId) => ({
36
+ key: `user:${address}:favorite:${favoriteId}`,
37
+ ttl: ttl_1.TTLS.ONE_YEAR,
38
+ }),
39
+ UserOffers: (address, offerType) => ({
40
+ key: `user:${address}:offers:${offerType}`,
41
+ ttl: ttl_1.TTLS.ONE_HOUR * 2,
42
+ }),
43
+ UserPlacedOffersCount: (address, offerType) => ({
44
+ key: `user:${address}:offers:${offerType}:count`,
45
+ ttl: ttl_1.TTLS.ONE_HOUR * 2,
46
+ }),
47
+ UserFavoriteUserAddresses: (address) => ({
48
+ key: `user:${address}:favorites:users`,
49
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
50
+ }),
51
+ UserFavoriteCollectionTickers: (address) => ({
52
+ key: `user:${address}:favorites:collections`,
53
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
54
+ }),
55
+ UserFavoriteNftIdentifiers: (address) => ({
56
+ key: `user:${address}:favorites:nfts`,
57
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
58
+ }),
59
+ UserTradingSummary: (address) => ({
60
+ key: `user:${address}:trading:summary`,
61
+ ttl: ttl_1.TTLS.ONE_MINUTE * 15,
62
+ }),
63
+ UserOwnedAndListedSummary: (address) => ({
64
+ key: `user:${address}:owned:listed:summary`,
65
+ ttl: ttl_1.TTLS.ONE_HOUR * 3,
66
+ }),
67
+ UserStatistics: (hash) => ({
68
+ key: `query:user:statistics:${hash}`,
69
+ ttl: ttl_1.TTLS.ONE_HOUR * 3,
70
+ }),
71
+ UserSearch: (filter) => ({
72
+ key: `search:user:${filter}`,
73
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
74
+ }),
75
+ UserCount: (chain) => ({
76
+ key: `user:count${serializeChain(chain)}`,
77
+ ttl: ttl_1.TTLS.ONE_DAY,
78
+ }),
79
+ AddressEsdt: (address) => ({
80
+ key: `user:${address}:esdt`,
81
+ ttl: ttl_1.TTLS.ONE_SECOND * 6,
82
+ }),
83
+ UserXoxnoDropScore: (skip, top, address) => ({
84
+ key: `user:${address}:xoxno:drop:score:${skip}:${top}`,
85
+ ttl: ttl_1.TTLS.ONE_HOUR,
86
+ }),
87
+ EmailVerificationCode: (address) => ({
88
+ key: `user:${address}:email:verification:code`,
89
+ ttl: ttl_1.TTLS.ONE_MINUTE * 10,
90
+ }),
91
+ // ==========================================
92
+ // Collection-related cache keys
93
+ // ==========================================
94
+ CollectionProfile: (collection) => ({
95
+ key: `collection:${collection}:profile`,
96
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
97
+ }),
98
+ CollectionStats: (collection) => ({
99
+ key: `collection:${collection}:stats`,
100
+ ttl: ttl_1.TTLS.ONE_MINUTE * 30,
101
+ }),
102
+ CollectionFloorPrice: (collection, token) => ({
103
+ key: `collection:${collection}:floor:${token}`,
104
+ ttl: ttl_1.TTLS.ONE_MONTH,
105
+ }),
106
+ CollectionTraitMap: (collection) => ({
107
+ key: `collection:${collection}:traits:map`,
108
+ ttl: ttl_1.TTLS.ONE_HOUR * 3,
109
+ }),
110
+ CollectionRanks: (collection) => ({
111
+ key: `collection:${collection}:ranks`,
112
+ ttl: ttl_1.TTLS.ONE_DAY * 2,
113
+ }),
114
+ CollectionMintProfile: (collection) => ({
115
+ key: `collection:${collection}:mint:profile`,
116
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
117
+ }),
118
+ CollectionMintStages: (collection, enabledOnly) => ({
119
+ key: `collection:${collection}:mint:stages:${enabledOnly}`,
120
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
121
+ }),
122
+ CollectionListedCount: (collection) => ({
123
+ key: `collection:${collection}:listed:count`,
124
+ ttl: ttl_1.TTLS.ONE_DAY,
125
+ }),
126
+ CollectionListingDistribution: (collection) => ({
127
+ key: `collection:${collection}:listing:distribution`,
128
+ ttl: ttl_1.TTLS.ONE_HOUR * 6,
129
+ }),
130
+ CollectionFloorPriceByAttribute: (collection) => ({
131
+ key: `collection:${collection}:floor:attributes`,
132
+ ttl: ttl_1.TTLS.ONE_HOUR * 3,
133
+ }),
134
+ CollectionHoldersDetailed: (key, realOwners) => ({
135
+ key: `collection:${key}:holders:detailed:${realOwners}`,
136
+ ttl: ttl_1.TTLS.ONE_HOUR * 6,
137
+ }),
138
+ CollectionHoldersCount: (key) => ({
139
+ key: `collection:${key}:holders:count`,
140
+ ttl: ttl_1.TTLS.ONE_HOUR * 6,
141
+ }),
142
+ CollectionHoldersDocCount: (collection) => ({
143
+ key: `collection:${collection}:holders:doc:count`,
144
+ ttl: ttl_1.TTLS.ONE_MONTH * 6,
145
+ }),
146
+ SftTotalSupplyCount: (collection) => ({
147
+ key: `collection:${collection}:supply:count`,
148
+ ttl: ttl_1.TTLS.ONE_DAY,
149
+ }),
150
+ CollectionProfileDocs: (hash) => ({
151
+ key: `query:collection:profile:docs:${hash}`,
152
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
153
+ }),
154
+ CollectionStatsDocs: (query) => ({
155
+ key: `query:collection:stats:${query}`,
156
+ ttl: ttl_1.TTLS.ONE_MINUTE * 10,
157
+ }),
158
+ CollectionOfferDocs: (hash) => ({
159
+ key: `query:collection:offers:${hash}`,
160
+ ttl: ttl_1.TTLS.ONE_SECOND * 30,
161
+ }),
162
+ CollectionSearch: (filter) => ({
163
+ key: `search:collection:${filter}`,
164
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
165
+ }),
166
+ CollectionTickerByTags: (creatorTag, collectionTag) => ({
167
+ key: `collection:ticker:${creatorTag}:${collectionTag}`,
168
+ ttl: ttl_1.TTLS.ONE_YEAR,
169
+ }),
170
+ CollectionListings: (collection) => ({
171
+ key: `collection:${collection}:listings`,
172
+ ttl: ttl_1.TTLS.ONE_HOUR,
173
+ }),
174
+ AllBannedCollections: () => ({
175
+ key: 'collection:banned:all',
176
+ ttl: ttl_1.TTLS.ONE_DAY * 90,
177
+ }),
178
+ AllVerifiedCollections: () => ({
179
+ key: 'collection:verified:all',
180
+ ttl: ttl_1.TTLS.ONE_DAY * 90,
181
+ }),
182
+ // ==========================================
183
+ // NFT-related cache keys
184
+ // ==========================================
185
+ NftDoc: (identifier) => ({
186
+ key: `nft:${identifier}:doc`,
187
+ ttl: ttl_1.TTLS.ONE_DAY * 30,
188
+ }),
189
+ NftHasOffer: (identifier) => ({
190
+ key: `nft:${identifier}:offer:exists`,
191
+ ttl: ttl_1.TTLS.ONE_YEAR,
192
+ }),
193
+ NftOffers: (identifier) => {
194
+ const collection = identifier.split('-').slice(0, 2).join('-');
195
+ return {
196
+ key: `collection:${collection}:offers:${identifier}`,
197
+ ttl: ttl_1.TTLS.ONE_HOUR,
198
+ };
199
+ },
200
+ NftDataDocs: (query) => ({
201
+ key: `query:nft:data:${query}`,
202
+ ttl: ttl_1.TTLS.ONE_DAY * 7,
203
+ }),
204
+ NftSearch: (filter) => ({
205
+ key: `search:nft:${filter}`,
206
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
207
+ }),
208
+ NftMetadataUrl: (url) => ({
209
+ key: `nft:metadata:url:${url}`,
210
+ ttl: ttl_1.TTLS.ONE_DAY * 30,
211
+ }),
212
+ NftMetadata: (identifier) => ({
213
+ key: `nft:metadata:${identifier}`,
214
+ ttl: ttl_1.TTLS.ONE_DAY * 30,
215
+ }),
216
+ // ==========================================
217
+ // Staking-related cache keys
218
+ // ==========================================
219
+ StakingPoolDoc: (poolId) => ({
220
+ key: `staking:${poolId}:profile`,
221
+ ttl: ttl_1.TTLS.ONE_MONTH,
222
+ }),
223
+ StakingWlNonces: (poolId) => ({
224
+ key: `staking:${poolId}:whitelist:nonces`,
225
+ ttl: ttl_1.TTLS.ONE_MONTH,
226
+ }),
227
+ StakingUserReward: (address, poolId) => ({
228
+ key: `staking:${poolId}:user:${address}:reward`,
229
+ ttl: ttl_1.TTLS.ONE_SECOND * 6,
230
+ }),
231
+ StakingDataDocs: (query) => ({
232
+ key: `query:staking:data:${query}`,
233
+ ttl: ttl_1.TTLS.ONE_SECOND * 30,
234
+ }),
235
+ StakingPoolsByCollection: (collections, activePoolsOnly) => {
236
+ const collectionsKey = collections.sort().join(',');
237
+ return {
238
+ key: `staking:pools:collection:${collectionsKey}:active:${activePoolsOnly}`,
239
+ ttl: ttl_1.TTLS.ONE_HOUR * 2,
240
+ };
241
+ },
242
+ StakingPoolsSummaryByCollection: () => ({
243
+ key: 'staking:pools:collection:summary',
244
+ ttl: ttl_1.TTLS.ONE_HOUR * 3,
245
+ }),
246
+ StakingProviderOwner: (provider) => ({
247
+ key: `staking:${provider}:owner`,
248
+ ttl: ttl_1.TTLS.ONE_DAY,
249
+ }),
250
+ StakingCreatedDelegationContract: (address) => ({
251
+ key: `staking:contract:${address}:delegation:created`,
252
+ ttl: ttl_1.TTLS.ONE_DAY * 300,
253
+ }),
254
+ StakingProviderUserRewards: (address, currentEpoch) => ({
255
+ key: `staking:${address}:rewards:${currentEpoch}`,
256
+ ttl: ttl_1.TTLS.ONE_DAY,
257
+ }),
258
+ StakingProviderEpochRewards: (provider, epoch) => ({
259
+ key: `staking:${provider}:epoch:${epoch}:rewards`,
260
+ ttl: ttl_1.TTLS.ONE_WEEK * 54,
261
+ }),
262
+ ClaimableRewards: (address, delegationContract) => ({
263
+ key: `staking:rewards:${address}:${delegationContract}:claimable`,
264
+ ttl: ttl_1.TTLS.ONE_HOUR * 3,
265
+ }),
266
+ AllUserDelegations: (address) => ({
267
+ key: `staking:user:${address}:delegations:all`,
268
+ ttl: ttl_1.TTLS.ONE_HOUR * 3,
269
+ }),
270
+ EgldStakingProviders: (providers, withIdentityInfo = true) => ({
271
+ key: `staking:${providers.join(',')}:egld:identity:${withIdentityInfo}`,
272
+ ttl: ttl_1.TTLS.ONE_HOUR * 3,
273
+ }),
274
+ EgldStakingProvider: (provider) => ({
275
+ key: `staking:${provider}:egld`,
276
+ ttl: ttl_1.TTLS.ONE_HOUR * 3,
277
+ }),
278
+ GetLastUpdatedEpoch: (provider, epoch) => ({
279
+ key: `staking:${provider}:epoch:${epoch}:last:updated`,
280
+ ttl: ttl_1.TTLS.ONE_DAY,
281
+ }),
282
+ // ==========================================
283
+ // Lending-related cache keys
284
+ // ==========================================
285
+ LendingMarketProfileDoc: (token) => ({
286
+ key: `lending:${token}:profile`,
287
+ ttl: ttl_1.TTLS.ONE_MONTH,
288
+ }),
289
+ LendingAccountProfileDoc: (identifier, token) => ({
290
+ key: `lending:${token}:${identifier}:profile`,
291
+ ttl: ttl_1.TTLS.ONE_MONTH,
292
+ }),
293
+ LendingTokenEModeProfileDoc: (token, eModeCategory) => ({
294
+ key: `lending:${token}:emode:${eModeCategory}:profile`,
295
+ ttl: ttl_1.TTLS.ONE_YEAR,
296
+ }),
297
+ LendingPoolContracts: (controllerAddress) => ({
298
+ key: `lending:global:pool:${controllerAddress}:contracts`,
299
+ ttl: ttl_1.TTLS.ONE_YEAR,
300
+ }),
301
+ LendingAllActiveAccounts: () => ({
302
+ key: 'lending:global:accounts:all',
303
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
304
+ }),
305
+ LendingAccountAttributes: (nonce) => ({
306
+ key: `lending:account:${nonce}:attributes`,
307
+ ttl: ttl_1.TTLS.ONE_YEAR,
308
+ }),
309
+ LendingLiquidateablePositions: () => ({
310
+ key: 'lending:global:positions:liquidateable',
311
+ ttl: ttl_1.TTLS.ONE_MINUTE,
312
+ }),
313
+ LendingMarketIndexes: (tokens) => ({
314
+ key: `lending:market:${tokens.join(',')}:indexes`,
315
+ ttl: ttl_1.TTLS.ONE_SECOND * 5,
316
+ }),
317
+ LendingAllMarketsTokens: () => ({
318
+ key: 'lending:global:market:tokens:all',
319
+ ttl: ttl_1.TTLS.ONE_HOUR * 6,
320
+ }),
321
+ LendingAccountPosition: (identifier) => ({
322
+ key: `lending:position:${identifier}`,
323
+ ttl: ttl_1.TTLS.ONE_DAY,
324
+ }),
325
+ LendingFaucetClaimed: (address) => ({
326
+ key: `lending:global:faucet:${address}:claimed`,
327
+ ttl: ttl_1.TTLS.ONE_YEAR,
328
+ }),
329
+ LendingBulkOraclePrice: (tokens, returnAsUsd) => ({
330
+ key: `lending:oracle:${tokens.join(',')}:bulk:${returnAsUsd}`,
331
+ ttl: ttl_1.TTLS.ONE_SECOND * 30,
332
+ }),
333
+ LendingTokenPriceAsUsd: (token) => ({
334
+ key: `lending:${token}:price:usd`,
335
+ ttl: ttl_1.TTLS.ONE_SECOND * 30,
336
+ }),
337
+ LendingTokenPriceAsEgld: (token) => ({
338
+ key: `lending:${token}:price:egld`,
339
+ ttl: ttl_1.TTLS.ONE_SECOND * 30,
340
+ }),
341
+ LendingOverallStats: () => ({
342
+ key: 'lending:global:stats:overall',
343
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
344
+ }),
345
+ LendingTopMarketParticipants: (token) => ({
346
+ key: `lending:${token}:participants:top`,
347
+ ttl: ttl_1.TTLS.ONE_HOUR * 6,
348
+ }),
349
+ LendingMarketParticipantsCount: (token) => ({
350
+ key: `lending:${token}:participants:count`,
351
+ ttl: ttl_1.TTLS.ONE_HOUR,
352
+ }),
353
+ LendingPositionLeaderboard: (hash) => ({
354
+ key: `query:lending:position:${hash}:leaderboard`,
355
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
356
+ }),
357
+ LendingEModeCategoryProfileDoc: (id) => ({
358
+ key: `lending:emode:${id}:category:profile`,
359
+ ttl: ttl_1.TTLS.ONE_YEAR,
360
+ }),
361
+ LendingMarketStatsGraphData: (startTime, endTime, bin, token) => ({
362
+ key: `lending:market:${token}:stats:graph:${startTime}:${endTime}:${bin}`,
363
+ ttl: ttl_1.TTLS.ONE_MINUTE * 15,
364
+ }),
365
+ LendingMarketAverageGraphData: (token) => ({
366
+ key: `lending:market:${token}:stats`,
367
+ ttl: ttl_1.TTLS.ONE_HOUR * 4,
368
+ }),
369
+ // ==========================================
370
+ // Event/Ticketing-related cache keys
371
+ // ==========================================
372
+ EventProfileDoc: (eventId) => ({
373
+ key: `event:${eventId}:profile`,
374
+ ttl: ttl_1.TTLS.ONE_MONTH,
375
+ }),
376
+ EventStageDoc: (eventId, stageId) => ({
377
+ key: `event:${eventId}:stage:${stageId}:profile`,
378
+ ttl: ttl_1.TTLS.ONE_MONTH,
379
+ }),
380
+ EventTicketProfileDoc: (eventId, ticketId) => ({
381
+ key: `event:${eventId}:ticket:${ticketId}:profile`,
382
+ ttl: ttl_1.TTLS.ONE_MONTH,
383
+ }),
384
+ EventGuestDoc: (eventId, address) => ({
385
+ key: `event:${eventId}:guest:${address}:profile`,
386
+ ttl: ttl_1.TTLS.ONE_MONTH,
387
+ }),
388
+ EventStartsFromPrice: (eventId) => ({
389
+ key: `event:${eventId}:price:starts:from`,
390
+ ttl: ttl_1.TTLS.ONE_MONTH,
391
+ }),
392
+ EventQuestions: (eventId) => ({
393
+ key: `event:${eventId}:questions`,
394
+ ttl: ttl_1.TTLS.ONE_MONTH,
395
+ }),
396
+ EventVoucherDoc: (eventId, voucherId) => ({
397
+ key: `event:${eventId}:voucher:${voucherId}:profile`,
398
+ ttl: ttl_1.TTLS.ONE_MONTH,
399
+ }),
400
+ EventUserRoleDoc: (eventId, address) => ({
401
+ key: `event:${eventId}:user:${address}:role`,
402
+ ttl: ttl_1.TTLS.ONE_MONTH,
403
+ }),
404
+ EventGuestSummary: (eventId) => ({
405
+ key: `event:${eventId}:guests:summary`,
406
+ ttl: ttl_1.TTLS.ONE_MINUTE * 30,
407
+ }),
408
+ EventVoucherDocByCode: (eventId, code) => ({
409
+ key: `event:${eventId}:voucher:code:${code}`,
410
+ ttl: ttl_1.TTLS.ONE_HOUR,
411
+ }),
412
+ EventIdBySlug: (slug) => ({
413
+ key: `event:slug:${slug}:id`,
414
+ ttl: ttl_1.TTLS.ONE_YEAR,
415
+ }),
416
+ EventReferralConfigDoc: (eventId, configId) => ({
417
+ key: `event:${eventId}:referralConfig:${configId}`,
418
+ ttl: ttl_1.TTLS.ONE_MONTH,
419
+ }),
420
+ EventReferralDoc: (eventId, referralCode) => ({
421
+ key: `event:${eventId}:referral:${referralCode}:profile`,
422
+ ttl: ttl_1.TTLS.ONE_MONTH,
423
+ }),
424
+ // ==========================================
425
+ // Token-related cache keys
426
+ // ==========================================
427
+ TokenDecimals: (token) => ({
428
+ key: `token:${token}:decimals`,
429
+ ttl: ttl_1.TTLS.ONE_YEAR,
430
+ }),
431
+ TokenProperties: (tokenIdentifier) => ({
432
+ key: `token:${tokenIdentifier}:properties`,
433
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
434
+ }),
435
+ TokenData: (token) => ({
436
+ key: `token:${token}:data`,
437
+ ttl: ttl_1.TTLS.ONE_MONTH,
438
+ }),
439
+ TokenSupply: (token) => ({
440
+ key: `token:${token}:supply`,
441
+ ttl: ttl_1.TTLS.ONE_HOUR,
442
+ }),
443
+ TokenSummary: (token) => ({
444
+ key: `token:${token}:summary`,
445
+ ttl: ttl_1.TTLS.ONE_HOUR,
446
+ }),
447
+ MvxTokenSummary: (token) => ({
448
+ key: `token:${token}:summary:mvx`,
449
+ ttl: ttl_1.TTLS.ONE_MINUTE * 15,
450
+ }),
451
+ TokenFiatPrice: (fiatCurrencies, token) => ({
452
+ key: `token:${token}:fiat:price:${fiatCurrencies.join(',')}`,
453
+ ttl: ttl_1.TTLS.ONE_MINUTE * 10,
454
+ }),
455
+ TokenUsdcValue: (token, timestamp) => ({
456
+ key: `token:${token}:usdc:value:${timestamp}`,
457
+ ttl: ttl_1.TTLS.ONE_DAY,
458
+ }),
459
+ LpTokenInfo: (token) => ({
460
+ key: `token:lp:${token}:info`,
461
+ ttl: ttl_1.TTLS.ONE_HOUR * 3,
462
+ }),
463
+ AllSwapTokens: () => ({
464
+ key: 'token:swap:all',
465
+ ttl: ttl_1.TTLS.ONE_DAY,
466
+ }),
467
+ AllTokensMap: () => ({
468
+ key: 'token:map:all',
469
+ ttl: ttl_1.TTLS.ONE_HOUR * 2,
470
+ }),
471
+ AshTokenUsdValue: (token) => ({
472
+ key: `ash:token:${token}:usd:value`,
473
+ ttl: ttl_1.TTLS.ONE_MINUTE * 10,
474
+ }),
475
+ AshSupportedTokens: () => ({
476
+ key: 'ash:supported:tokens',
477
+ ttl: ttl_1.TTLS.ONE_DAY,
478
+ }),
479
+ TokenAccountsCount: (token) => ({
480
+ key: `token:${token}:accounts:count`,
481
+ ttl: ttl_1.TTLS.ONE_HOUR * 6,
482
+ }),
483
+ TokensByIdentifier: (tokens, returnMap) => ({
484
+ key: `tokens:by:identifier:${tokens.sort().join(',')}:map:${returnMap}`,
485
+ ttl: ttl_1.TTLS.ONE_DAY,
486
+ }),
487
+ TokensByFilterString: (identifier, category, chain) => {
488
+ const identifierKey = identifier?.length
489
+ ? identifier.sort().join(',')
490
+ : 'all';
491
+ const categoryKey = category?.length ? category.sort().join(',') : 'all';
492
+ const chainKey = serializeChain(chain);
493
+ return {
494
+ key: `tokens:by:filter:${identifierKey}:${categoryKey}:${chainKey}`,
495
+ ttl: ttl_1.TTLS.ONE_DAY,
496
+ };
497
+ },
498
+ FilteredTokenDocs: (identifier, category, chain) => {
499
+ const identifierKey = identifier?.length
500
+ ? identifier.sort().join(',')
501
+ : 'all';
502
+ const categoryKey = category?.length ? category.sort().join(',') : 'all';
503
+ const chainKey = serializeChain(chain);
504
+ return {
505
+ key: `token:docs:filtered:${identifierKey}:${categoryKey}:${chainKey}`,
506
+ ttl: ttl_1.TTLS.ONE_DAY,
507
+ };
508
+ },
509
+ // ==========================================
510
+ // Launchpad-related cache keys
511
+ // ==========================================
512
+ LaunchpadAllRegisteredContracts: () => ({
513
+ key: 'launchpad:contracts:registered:all',
514
+ ttl: ttl_1.TTLS.ONE_MONTH,
515
+ }),
516
+ UserCreatorProfile: (address) => ({
517
+ key: `launchpad:creator:${address}:profile`,
518
+ ttl: ttl_1.TTLS.ONE_MONTH,
519
+ }),
520
+ UserCreatorProfileByTag: (creatorTag) => ({
521
+ key: `launchpad:creator:${creatorTag}:profile`,
522
+ ttl: ttl_1.TTLS.ONE_MONTH,
523
+ }),
524
+ UserCreatorTagRegistered: (tag) => ({
525
+ key: `launchpad:creator:${tag}:registered`,
526
+ ttl: ttl_1.TTLS.ONE_MONTH,
527
+ }),
528
+ GetCreatorProfileByContractAddress: (contractAddress) => ({
529
+ key: `launchpad:creator:${contractAddress}:profile`,
530
+ ttl: ttl_1.TTLS.ONE_YEAR,
531
+ }),
532
+ // ==========================================
533
+ // Minter-related cache keys
534
+ // ==========================================
535
+ MinterLocalOwner: (address) => ({
536
+ key: `mint:launchpad:${address}:local:owner`,
537
+ ttl: ttl_1.TTLS.ONE_YEAR,
538
+ }),
539
+ MinterUserMintsGlobal: (collectionTag, contractAddress, userAddress) => ({
540
+ key: `mint:${contractAddress}:${collectionTag}:user:${userAddress}:mints:global`,
541
+ ttl: ttl_1.TTLS.ONE_SECOND * 6,
542
+ }),
543
+ MinterUserMintsPerStage: (collectionTag, contractAddress, userAddress, stageName) => ({
544
+ key: `mint:${contractAddress}:${collectionTag}:user:${userAddress}:stage:${stageName}:mints`,
545
+ ttl: ttl_1.TTLS.ONE_SECOND * 6,
546
+ }),
547
+ MinterMintShareholders: (collectionTag, contractAddress) => ({
548
+ key: `mint:${contractAddress}:${collectionTag}:shareholders:mint`,
549
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
550
+ }),
551
+ MinterRoyaltiesShareholders: (contractAddress) => ({
552
+ key: `mint:${contractAddress}:shareholders:royalties`,
553
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
554
+ }),
555
+ MinterIsUserWhitelisted: (collectionTag, contractAddress, userAddress, stageName) => ({
556
+ key: `mint:${contractAddress}:${collectionTag}:user:${userAddress}:stage:${stageName}:whitelisted`,
557
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
558
+ }),
559
+ // ==========================================
560
+ // System-related cache keys
561
+ // ==========================================
562
+ CurrentEpoch: () => ({
563
+ key: 'system:epoch:current',
564
+ ttl: ttl_1.TTLS.ONE_SECOND * 6,
565
+ }),
566
+ EpochEndTimestamp: () => ({
567
+ key: 'system:epoch:end:timestamp',
568
+ ttl: ttl_1.TTLS.ONE_SECOND * 6,
569
+ }),
570
+ ShardCount: () => ({
571
+ key: 'system:shard:count',
572
+ ttl: ttl_1.TTLS.ONE_WEEK,
573
+ }),
574
+ CurrentTokenValue: () => ({
575
+ key: 'system:token:value:current',
576
+ ttl: ttl_1.TTLS.ONE_HOUR,
577
+ }),
578
+ NextRelayWalletIndex: (shard) => ({
579
+ key: `system:relay:wallet:${shard}:index:next`,
580
+ ttl: ttl_1.TTLS.ONE_YEAR,
581
+ }),
582
+ AccumulatorCreators: () => ({
583
+ key: 'system:accumulator:creators',
584
+ ttl: ttl_1.TTLS.ONE_HOUR,
585
+ }),
586
+ LowVolumeCollections: () => ({
587
+ key: 'system:collections:low:volume',
588
+ ttl: ttl_1.TTLS.ONE_HOUR,
589
+ }),
590
+ // ==========================================
591
+ // Liquid staking cache keys
592
+ // ==========================================
593
+ EGLDLiquidStats: () => ({
594
+ key: 'liquid:egld:stats:overall',
595
+ ttl: ttl_1.TTLS.ONE_HOUR,
596
+ }),
597
+ XoxnoLiquidStats: () => ({
598
+ key: 'liquid:xoxno:stats:overall',
599
+ ttl: ttl_1.TTLS.ONE_MINUTE * 15,
600
+ }),
601
+ XoxnoLiquidApy: () => ({
602
+ key: 'liquid:xoxno:stats:apy',
603
+ ttl: ttl_1.TTLS.ONE_HOUR,
604
+ }),
605
+ ExchangeRateLiquidXOXNO: () => ({
606
+ key: 'liquid:xoxno:stats:exchange:rate',
607
+ ttl: ttl_1.TTLS.ONE_HOUR,
608
+ }),
609
+ ExchangeRateLiquidXOXNOEGLD: () => ({
610
+ key: 'liquid:egld:stats:exchange:rate',
611
+ ttl: ttl_1.TTLS.ONE_HOUR,
612
+ }),
613
+ SEgldExchangeRate: () => ({
614
+ key: 'system:segld:exchange:rate',
615
+ ttl: ttl_1.TTLS.ONE_HOUR * 12,
616
+ }),
617
+ FeesXOXNOEGLD: () => ({
618
+ key: 'liquid:egld:stats:fees',
619
+ ttl: ttl_1.TTLS.ONE_DAY,
620
+ }),
621
+ PendingDelegateXOXNOEGLD: () => ({
622
+ key: 'liquid:egld:pending:delegate',
623
+ ttl: ttl_1.TTLS.ONE_HOUR,
624
+ }),
625
+ VirtualEGLDReserveXOXNOEGLD: () => ({
626
+ key: 'liquid:egld:reserve:virtual',
627
+ ttl: ttl_1.TTLS.ONE_HOUR,
628
+ }),
629
+ TotalWithdrawnXOXNOEGLD: () => ({
630
+ key: 'liquid:egld:total:withdrawn',
631
+ ttl: ttl_1.TTLS.ONE_HOUR,
632
+ }),
633
+ ValidatorsLiquidXOXNOEGLD: () => ({
634
+ key: 'liquid:egld:providers',
635
+ ttl: ttl_1.TTLS.ONE_HOUR * 5,
636
+ }),
637
+ AprLiquidXOXNOEGLD: () => ({
638
+ key: 'liquid:egld:stats:apr',
639
+ ttl: ttl_1.TTLS.ONE_HOUR,
640
+ }),
641
+ PendingUnstakeXOXNOEGLD: () => ({
642
+ key: 'liquid:egld:pending:unstake',
643
+ ttl: ttl_1.TTLS.ONE_HOUR,
644
+ }),
645
+ // ==========================================
646
+ // Governance cache keys
647
+ // ==========================================
648
+ GovernanceVotesProviders: () => ({
649
+ key: 'governance:providers',
650
+ ttl: ttl_1.TTLS.ONE_MINUTE,
651
+ }),
652
+ GovernanceVotes: () => ({
653
+ key: 'governance',
654
+ ttl: ttl_1.TTLS.ONE_MINUTE,
655
+ }),
656
+ // ==========================================
657
+ // Perp/Trading cache keys
658
+ // ==========================================
659
+ PerpSpotBalance: (user, coin) => ({
660
+ key: `perp:spot:${user}:${coin}`,
661
+ ttl: ttl_1.TTLS.ONE_YEAR,
662
+ }),
663
+ PerpPerpBalance: (user, coin) => ({
664
+ key: `perp:perp:${user}:${coin}`,
665
+ ttl: ttl_1.TTLS.ONE_YEAR,
666
+ }),
667
+ PerpOpenOrders: (user) => ({
668
+ key: `perp:openOrders:${user}`,
669
+ ttl: ttl_1.TTLS.ONE_YEAR,
670
+ }),
671
+ PerpFilledOrders: (user) => ({
672
+ key: `perp:filledOrders:${user}`,
673
+ ttl: ttl_1.TTLS.ONE_YEAR,
674
+ }),
675
+ PerpSpotUsers: () => ({
676
+ key: 'perp:spot:users',
677
+ ttl: ttl_1.TTLS.ONE_YEAR,
678
+ }),
679
+ PerpTermsAccepted: (user) => ({
680
+ key: `perp:legal-check:${user}:terms`,
681
+ ttl: ttl_1.TTLS.ONE_YEAR,
682
+ }),
683
+ // ==========================================
684
+ // Bober-related cache keys
685
+ // ==========================================
686
+ GetBoberBattleBiggestWinners: () => ({
687
+ key: 'bober:battle:biggest:winners',
688
+ ttl: ttl_1.TTLS.ONE_MINUTE * 10,
689
+ }),
690
+ GetAllBoberBattleTokens: () => ({
691
+ key: 'bober:battle:tokens',
692
+ ttl: ttl_1.TTLS.ONE_MINUTE * 10,
693
+ }),
694
+ BoberWheelWinners: () => ({
695
+ key: 'bober:wheel:winners',
696
+ ttl: ttl_1.TTLS.ONE_MINUTE * 10,
697
+ }),
698
+ BoberWheelConfig: () => ({
699
+ key: 'bober:wheel:config',
700
+ ttl: ttl_1.TTLS.ONE_MINUTE,
701
+ }),
702
+ BoberWheelScheduledSpin: () => ({
703
+ key: 'bober:wheel:scheduled:spin',
704
+ ttl: ttl_1.TTLS.ONE_DAY,
705
+ }),
706
+ BoberBattleLeaderboard: (hash) => ({
707
+ key: `bober:battle:leaderboard:${hash}`,
708
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
709
+ }),
710
+ BoberBattleSingleLeaderboard: (hash) => ({
711
+ key: `bober:battle:single:leaderboard:${hash}`,
712
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
713
+ }),
714
+ // ==========================================
715
+ // Chat-related cache keys
716
+ // ==========================================
717
+ AllGroupChatIds: () => ({
718
+ key: 'chat:groups:all:ids',
719
+ ttl: ttl_1.TTLS.ONE_MONTH * 6,
720
+ }),
721
+ GroupChatProfile: (chatId) => ({
722
+ key: `chat:${chatId}:profile`,
723
+ ttl: ttl_1.TTLS.ONE_MONTH * 6,
724
+ }),
725
+ ConversationDeleteTimestamp: (chatId, address) => ({
726
+ key: `chat:${chatId}:user:${address}:delete:timestamp`,
727
+ ttl: ttl_1.TTLS.ONE_YEAR,
728
+ }),
729
+ IsSenderBlockedByReceiver: (sender, receiver) => ({
730
+ key: `chat:block:${sender}:by:${receiver}`,
731
+ ttl: ttl_1.TTLS.ONE_YEAR,
732
+ }),
733
+ UserLastReadChatMessage: (chatId, address) => ({
734
+ key: `chat:${chatId}:user:${address}:last:read`,
735
+ ttl: ttl_1.TTLS.ONE_YEAR,
736
+ }),
737
+ UserLastSentChatMessage: (chatId, address) => ({
738
+ key: `chat:${chatId}:user:${address}:last:sent`,
739
+ ttl: ttl_1.TTLS.ONE_YEAR,
740
+ }),
741
+ // ==========================================
742
+ // Web2-related cache keys
743
+ // ==========================================
744
+ Web2NativeWalletAddress: (userId) => ({
745
+ key: `web2:${userId}:native:wallet:address`,
746
+ ttl: ttl_1.TTLS.ONE_YEAR,
747
+ }),
748
+ Web2UserDoc: (userId) => ({
749
+ key: `web2:${userId}:doc`,
750
+ ttl: ttl_1.TTLS.ONE_MONTH * 3,
751
+ }),
752
+ // ==========================================
753
+ // Location-related cache keys
754
+ // ==========================================
755
+ LocationPolygon: (query) => ({
756
+ key: `location:polygon:${query.toLowerCase().trim()}`,
757
+ ttl: ttl_1.TTLS.ONE_MONTH * 6,
758
+ }),
759
+ GetCountries: () => ({
760
+ key: 'location:countries:zontix',
761
+ ttl: ttl_1.TTLS.ONE_DAY * 30,
762
+ }),
763
+ // ==========================================
764
+ // Platform-related cache keys
765
+ // ==========================================
766
+ PinnedNftsApiResponse: () => ({
767
+ key: 'platform:nfts:pinned:response',
768
+ ttl: ttl_1.TTLS.ONE_HOUR,
769
+ }),
770
+ DropsPinnedCollectionsApiResponse: () => ({
771
+ key: 'drops:pinned:collections:api:response',
772
+ ttl: ttl_1.TTLS.ONE_HOUR * 6,
773
+ }),
774
+ HomePinnedCollectionsApiResponse: () => ({
775
+ key: 'home:pinned:collections:api:response',
776
+ ttl: ttl_1.TTLS.ONE_HOUR * 6,
777
+ }),
778
+ ListingCount: (chain) => ({
779
+ key: `platform:stats:listing:count${serializeChain(chain)}`,
780
+ ttl: ttl_1.TTLS.ONE_HOUR * 6,
781
+ }),
782
+ TradingStatistics: (chain) => ({
783
+ key: `platform:stats:trading${serializeChain(chain)}`,
784
+ ttl: ttl_1.TTLS.ONE_DAY,
785
+ }),
786
+ HatomTokenValues: () => ({
787
+ key: 'platform:hatom:token:values',
788
+ ttl: ttl_1.TTLS.ONE_HOUR,
789
+ }),
790
+ PendingExternalPayments: () => ({
791
+ key: 'pending:external:payments',
792
+ ttl: ttl_1.TTLS.ONE_MINUTE * 10,
793
+ }),
794
+ TwispayCallbackProcessed: (transactionId) => ({
795
+ key: `twispay:callback:processed:${transactionId}`,
796
+ ttl: ttl_1.TTLS.ONE_MONTH,
797
+ }),
798
+ // ==========================================
799
+ // Activity-related cache keys
800
+ // ==========================================
801
+ ActivityQuery: (queryHash) => ({
802
+ key: `activity:query:${queryHash}`,
803
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
804
+ }),
805
+ VolumeGraphData: (startTime, endTime, bin, collection, chain) => ({
806
+ key: `volume:graph:data:${startTime}:${endTime}:${bin}:${collection}:${serializeChain(chain)}`,
807
+ ttl: ttl_1.TTLS.ONE_MINUTE * 15,
808
+ }),
809
+ // ==========================================
810
+ // Search-related cache keys
811
+ // ==========================================
812
+ GlobalSearch: (filter) => ({
813
+ key: `search:global:${filter}`,
814
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
815
+ }),
816
+ DropsSearch: (filter) => ({
817
+ key: `search:drops:${filter}`,
818
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
819
+ }),
820
+ // ==========================================
821
+ // Data API cache keys
822
+ // ==========================================
823
+ DataApiTokens: () => ({
824
+ key: 'data:api:tokens',
825
+ ttl: ttl_1.TTLS.ONE_MINUTE * 10,
826
+ }),
827
+ DataApiTokenPrice: (identifier, dateString, isCurrentDate) => ({
828
+ key: `data:api:price:${identifier}:${dateString}`,
829
+ ttl: isCurrentDate ? ttl_1.TTLS.ONE_MINUTE * 5 : ttl_1.TTLS.ONE_WEEK,
830
+ }),
831
+ // ==========================================
832
+ // ABI cache keys
833
+ // ==========================================
834
+ GetAbi: (abiName) => ({
835
+ key: `abi:${abiName}`,
836
+ ttl: ttl_1.TTLS.ONE_DAY,
837
+ }),
838
+ // ==========================================
839
+ // Sui-related cache keys
840
+ // ==========================================
841
+ SuiTransactionSender: (txDigest) => ({
842
+ key: `platform:sui:transaction:${txDigest}:sender`,
843
+ ttl: ttl_1.TTLS.ONE_YEAR,
844
+ }),
845
+ SuiObject: (objectId) => ({
846
+ key: `platform:sui:object:${objectId}`,
847
+ ttl: ttl_1.TTLS.ONE_YEAR,
848
+ }),
849
+ SuiEvents: (packageId, startTime, endTime, eventTypes) => ({
850
+ key: `platform:sui:events:${packageId}:${startTime}:${endTime}:${eventTypes.join(',')}`,
851
+ ttl: ttl_1.TTLS.ONE_HOUR * 6,
852
+ }),
853
+ SuiUserCoins: (userAddress) => ({
854
+ key: `platform:sui:user:${userAddress}:coins`,
855
+ ttl: ttl_1.TTLS.ONE_MINUTE,
856
+ }),
857
+ SuiCollectionInfo: (collectionType) => ({
858
+ key: `platform:sui:collection:${collectionType}:info`,
859
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
860
+ }),
861
+ SuiAllCollectionTypes: () => ({
862
+ key: 'platform:sui:collections:types:all',
863
+ ttl: ttl_1.TTLS.ONE_HOUR,
864
+ }),
865
+ SuiTokenPrices: (coinTypes) => ({
866
+ key: `platform:sui:tokens:${coinTypes.join(',')}:prices`,
867
+ ttl: ttl_1.TTLS.ONE_MINUTE * 5,
868
+ }),
869
+ SuiQueryEventsPage: (moveEventType, order, limit, cursor) => {
870
+ const cursorKey = cursor
871
+ ? `${cursor.txDigest}:${cursor.eventSeq}`
872
+ : 'start';
873
+ const orderKey = order ?? 'ascending';
874
+ const limitKey = limit ?? 'default';
875
+ return {
876
+ key: `platform:sui:queryEvents:${moveEventType}:${orderKey}:${limitKey}:${cursorKey}`,
877
+ ttl: ttl_1.TTLS.ONE_MINUTE,
878
+ };
879
+ },
880
+ // ==========================================
881
+ // Kusto-related cache keys
882
+ // ==========================================
883
+ KustoXoxnoLiquidStats: () => ({
884
+ key: 'kusto:xoxno:liquid:stats',
885
+ ttl: ttl_1.TTLS.ONE_HOUR,
886
+ }),
887
+ KustoEgldLiquidStats: () => ({
888
+ key: 'kusto:egld:liquid:stats',
889
+ ttl: ttl_1.TTLS.ONE_HOUR,
890
+ }),
891
+ };
892
+ /**
893
+ * Cache key patterns for invalidation.
894
+ * Used by az-functions to find and delete related cache entries.
895
+ *
896
+ * @deprecated Use CacheIndexKeys with index sets instead of SCAN patterns.
897
+ * SCAN is expensive in serverless environments and causes connection saturation.
898
+ */
899
+ exports.CachePatterns = {
900
+ UserAll: (address) => `user:${address}:*`,
901
+ CollectionAll: (collection) => `collection:${collection}:*`,
902
+ NftAll: (identifier) => `nft:${identifier}:*`,
903
+ StakingPoolAll: (poolId) => `staking:${poolId}:*`,
904
+ LendingTokenAll: (token) => `lending:${token}:*`,
905
+ EventAll: (eventId) => `event:${eventId}:*`,
906
+ };
907
+ // ==========================================
908
+ // Index Set Keys (for O(1) cache invalidation)
909
+ // ==========================================
910
+ /**
911
+ * Index set keys for efficient cache invalidation.
912
+ *
913
+ * Instead of using SCAN to find cache keys by pattern (expensive in serverless),
914
+ * we maintain Redis SETs that track which cache keys belong to which collection/address.
915
+ *
916
+ * Usage:
917
+ * - API: When setting a cache, also SADD the key to relevant index sets
918
+ * - Azure Functions: When invalidating, use SMEMBERS to get keys from index sets
919
+ *
920
+ * This reduces O(n) SCAN operations to O(1) SMEMBERS lookups.
921
+ */
922
+ exports.CacheIndexKeys = {
923
+ // ==========================================
924
+ // NFT Query Index Sets
925
+ // ==========================================
926
+ /**
927
+ * Index of all NFT query cache keys for a specific collection.
928
+ * When API caches an NFT query result, it adds the cache key to this set.
929
+ * When invalidating, az-functions reads this set instead of SCAN.
930
+ */
931
+ NftQueryByCollection: (collection) => `idx:nft:query:collection:${collection.toLowerCase()}`,
932
+ /**
933
+ * Index of all NFT query cache keys for a specific address (owner, seller).
934
+ */
935
+ NftQueryByAddress: (address) => `idx:nft:query:address:${address.toLowerCase()}`,
936
+ /**
937
+ * Index of all global/wildcard NFT query cache keys (explore pages).
938
+ * These are queries with no specific collection or address filter.
939
+ */
940
+ NftQueryGlobal: 'idx:nft:query:global',
941
+ // ==========================================
942
+ // Offer Query Index Sets
943
+ // ==========================================
944
+ OfferQueryByCollection: (collection) => `idx:offer:query:collection:${collection.toLowerCase()}`,
945
+ OfferQueryByAddress: (address) => `idx:offer:query:address:${address.toLowerCase()}`,
946
+ OfferQueryByIdentifier: (identifier) => `idx:offer:query:identifier:${identifier.toLowerCase()}`,
947
+ OfferQueryGlobal: 'idx:offer:query:global',
948
+ // ==========================================
949
+ // Collection Query Index Sets
950
+ // ==========================================
951
+ CollectionQueryByTicker: (ticker) => `idx:collection:query:ticker:${ticker.toLowerCase()}`,
952
+ CollectionStatsQueryByTicker: (ticker) => `idx:collection:stats:ticker:${ticker.toLowerCase()}`,
953
+ CollectionOffersQueryByTicker: (ticker) => `idx:collection:offers:ticker:${ticker.toLowerCase()}`,
954
+ CollectionQueryGlobal: 'idx:collection:query:global',
955
+ // ==========================================
956
+ // Activity Query Index Sets
957
+ // ==========================================
958
+ ActivityQueryByCollection: (collection) => `idx:activity:query:collection:${collection.toLowerCase()}`,
959
+ ActivityQueryByAddress: (address) => `idx:activity:query:address:${address.toLowerCase()}`,
960
+ ActivityQueryGlobal: 'idx:activity:query:global',
961
+ };