• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

safe-global / safe-client-gateway / 20074265211

09 Dec 2025 06:27PM UTC coverage: 90.202% (+0.02%) from 90.178%
20074265211

Pull #2803

github

PooyaRaki
fix(circuit-breaker): fix test
Pull Request #2803: feat(circuit-breaker): implement circuit breaker pattern for resilience

2922 of 3621 branches covered (80.7%)

Branch coverage included in aggregate %.

639 of 683 new or added lines in 138 files covered. (93.56%)

3 existing lines in 2 files now uncovered.

13916 of 15046 relevant lines covered (92.49%)

598.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.44
/src/datasources/cache/cache.router.ts
1
import crypto from 'crypto';
214✔
2
import { CacheDir } from '@/datasources/cache/entities/cache-dir.entity';
214✔
3
import type { Address, Hash } from 'viem';
4
import type { TransactionInfo } from '@/modules/transactions/routes/entities/transaction-info.entity';
5

6
export class CacheRouter {
214✔
7
  private static readonly ACCOUNT_DATA_SETTINGS_KEY = 'account_data_settings';
214✔
8
  private static readonly ACCOUNT_DATA_TYPES_KEY = 'account_data_types';
214✔
9
  private static readonly ACCOUNT_KEY = 'account';
214✔
10
  private static readonly ALL_TRANSACTIONS_KEY = 'all_transactions';
214✔
11
  private static readonly AUTH_NONCE_KEY = 'auth_nonce';
214✔
12
  private static readonly BACKBONE_KEY = 'backbone';
214✔
13
  private static readonly BRIDGE_CHAINS_KEY = 'bridge_chains';
214✔
14
  private static readonly CHAIN_KEY = 'chain';
214✔
15
  private static readonly CHAINS_KEY = 'chains';
214✔
16
  private static readonly CONTRACTS_KEY = 'contracts';
214✔
17
  private static readonly COUNTERFACTUAL_SAFE_KEY = 'counterfactual_safe';
214✔
18
  private static readonly COUNTERFACTUAL_SAFES_KEY = 'counterfactual_safes';
214✔
19
  private static readonly CREATION_TRANSACTION_KEY = 'creation_transaction';
214✔
20
  private static readonly DECODED_DATA_KEY = 'decoded_data';
214✔
21
  private static readonly DELEGATES_KEY = 'delegates';
214✔
22
  private static readonly FIREBASE_OAUTH2_TOKEN_KEY = 'firebase_oauth2_token';
214✔
23
  private static readonly INCOMING_TRANSFERS_KEY = 'incoming_transfers';
214✔
24
  private static readonly INDEXING_KEY = 'indexing';
214✔
25
  private static readonly MESSAGE_KEY = 'message';
214✔
26
  private static readonly MESSAGES_KEY = 'messages';
214✔
27
  private static readonly MODULE_TRANSACTION_KEY = 'module_transaction';
214✔
28
  private static readonly MODULE_TRANSACTIONS_KEY = 'module_transactions';
214✔
29
  private static readonly MULTISIG_TRANSACTION_KEY = 'multisig_transaction';
214✔
30
  private static readonly MULTISIG_TRANSACTIONS_KEY = 'multisig_transactions';
214✔
31
  private static readonly NATIVE_COIN_PRICE_KEY = 'native_coin_price';
214✔
32
  private static readonly OWNERS_SAFE_KEY = 'owner_safes';
214✔
33
  private static readonly RATE_LIMIT_KEY = 'rate_limit';
214✔
34
  private static readonly RELAY_KEY = 'relay';
214✔
35
  private static readonly RPC_REQUESTS_KEY = 'rpc_requests';
214✔
36
  private static readonly SAFE_APPS_KEY = 'safe_apps';
214✔
37
  private static readonly SAFE_BALANCES_KEY = 'safe_balances';
214✔
38
  private static readonly SAFE_COLLECTIBLES_KEY = 'safe_collectibles';
214✔
39
  private static readonly SAFE_EXISTS_KEY = 'safe_exists';
214✔
40
  private static readonly SAFE_FIAT_CODES_KEY = 'safe_fiat_codes';
214✔
41
  private static readonly SAFE_KEY = 'safe';
214✔
42
  private static readonly SINGLETONS_KEY = 'singletons';
214✔
43
  private static readonly STAKING_DEDICATED_STAKING_STATS_KEY =
44
    'staking_dedicated_staking_stats';
214✔
45
  private static readonly STAKING_DEFI_VAULT_STATS_KEY =
46
    'staking_defi_vault_stats';
214✔
47
  private static readonly STAKING_DEFI_VAULT_STAKES_KEY =
48
    'staking_defi_vault_stakes';
214✔
49
  private static readonly STAKING_DEFI_MORPHO_EXTRA_REWARDS_KEY =
50
    'staking_defi_morpho_extra_rewards';
214✔
51
  private static readonly STAKING_DEPLOYMENTS_KEY = 'staking_deployments';
214✔
52
  private static readonly STAKING_REWARDS_FEE_KEY = 'staking_rewards_fee';
214✔
53
  private static readonly STAKING_NETWORK_STATS_KEY = 'staking_network_stats';
214✔
54
  private static readonly STAKING_POOLED_STAKING_STATS_KEY =
55
    'staking_pooled_staking_stats';
214✔
56
  private static readonly STAKING_STAKES_KEY = 'staking_stakes';
214✔
57
  private static readonly STAKING_TRANSACTION_STATUS_KEY =
58
    'staking_transaction_status';
214✔
59
  private static readonly TARGETED_MESSAGING_OUTREACHES =
60
    'targeted_messaging_outreaches';
214✔
61
  private static readonly TARGETED_MESSAGING_OUTREACH_FILE_PROCESSOR_LOCK =
62
    'targeted_messaging_outreach_file_processor_lock';
214✔
63
  private static readonly TARGETED_MESSAGING_SUBMISSION_KEY =
64
    'targeted_messaging_submission';
214✔
65
  private static readonly TARGETED_MESSAGING_TARGETED_SAFE_KEY =
66
    'targeted_messaging_targeted_safe';
214✔
67
  private static readonly TOKEN_KEY = 'token';
214✔
68
  private static readonly TOKEN_PRICE_KEY = 'token_price';
214✔
69
  private static readonly TOKENS_KEY = 'tokens';
214✔
70
  private static readonly TRANSFER_KEY = 'transfer';
214✔
71
  private static readonly TRANSFERS_KEY = 'transfers';
214✔
72
  private static readonly TRUSTED_FOR_DELEGATE_CALL_CONTRACTS_KEY =
73
    'trusted_contracts';
214✔
74
  private static readonly UNSUPPORTED_CHAIN_EVENT = 'unsupported_chain_event';
214✔
75
  private static readonly ZERION_BALANCES_KEY = 'zerion_balances';
214✔
76
  private static readonly ZERION_COLLECTIBLES_KEY = 'zerion_collectibles';
214✔
77
  private static readonly ZERION_POSITIONS_KEY = 'zerion_positions';
214✔
78
  private static readonly ZERION_CHAINS_KEY = 'zerion_chains';
214✔
79
  private static readonly PORTFOLIO_KEY = 'portfolio';
214✔
80
  private static readonly ORM_QUERY_CACHE_KEY = 'orm_query_cache';
214✔
81
  private static readonly TRANSACTIONS_EXPORT_KEY = 'transactions_export';
214✔
82
  private static readonly CONTRACT_ANALYSIS_KEY = 'contract_analysis';
214✔
83
  private static readonly RECIPIENT_ANALYSIS_KEY = 'recipient_analysis';
214✔
84

85
  static getAuthNonceCacheKey(nonce: string): string {
86
    return `${CacheRouter.AUTH_NONCE_KEY}_${nonce}`;
106✔
87
  }
88

89
  static getAuthNonceCacheDir(nonce: string): CacheDir {
90
    return new CacheDir(CacheRouter.getAuthNonceCacheKey(nonce), '');
106✔
91
  }
92

93
  static getBridgeChainsCacheDir(): CacheDir {
94
    return new CacheDir(CacheRouter.BRIDGE_CHAINS_KEY, '');
4✔
95
  }
96

97
  static getBalancesCacheKey(args: {
98
    chainId: string;
99
    safeAddress: Address;
100
  }): string {
101
    return `${args.chainId}_${CacheRouter.SAFE_BALANCES_KEY}_${args.safeAddress}`;
100✔
102
  }
103

104
  static getBalancesCacheDir(args: {
105
    chainId: string;
106
    safeAddress: Address;
107
    trusted?: boolean;
108
    excludeSpam?: boolean;
109
  }): CacheDir {
110
    return new CacheDir(
60✔
111
      CacheRouter.getBalancesCacheKey(args),
112
      `${args.trusted}_${args.excludeSpam}`,
113
    );
114
  }
115

116
  static getZerionBalancesCacheKey(args: {
117
    chainId: string;
118
    safeAddress: Address;
119
  }): string {
120
    return `${args.chainId}_${CacheRouter.ZERION_BALANCES_KEY}_${args.safeAddress}`;
26✔
121
  }
122

123
  static getZerionBalancesCacheDir(args: {
124
    chainId: string;
125
    safeAddress: Address;
126
    fiatCode: string;
127
  }): CacheDir {
128
    return new CacheDir(
26✔
129
      CacheRouter.getZerionBalancesCacheKey(args),
130
      args.fiatCode.toUpperCase(),
131
    );
132
  }
133

134
  static getZerionCollectiblesCacheKey(args: {
135
    chainId: string;
136
    safeAddress: Address;
137
  }): string {
138
    return `${args.chainId}_${CacheRouter.ZERION_COLLECTIBLES_KEY}_${args.safeAddress}`;
8✔
139
  }
140

141
  static getZerionCollectiblesCacheDir(args: {
142
    chainId: string;
143
    safeAddress: Address;
144
    limit?: number;
145
    offset?: number;
146
  }): CacheDir {
147
    return new CacheDir(
8✔
148
      CacheRouter.getZerionCollectiblesCacheKey(args),
149
      `${args.limit}_${args.offset}`,
150
    );
151
  }
152

153
  static getZerionPositionsCacheKey(args: {
154
    chainId: string;
155
    safeAddress: Address;
156
  }): string {
157
    return `${args.chainId}_${CacheRouter.ZERION_POSITIONS_KEY}_${args.safeAddress}`;
×
158
  }
159

160
  static getZerionPositionsCacheDir(args: {
161
    chainId: string;
162
    safeAddress: Address;
163
    fiatCode: string;
164
    refresh?: string;
165
  }): CacheDir {
166
    return new CacheDir(
×
167
      CacheRouter.getZerionPositionsCacheKey(args),
168
      `${args.fiatCode.toUpperCase()}_${args.refresh ?? ''}`,
×
169
    );
170
  }
171

172
  static getRateLimitCacheKey(prefix: string): string {
173
    return `${prefix}_${CacheRouter.RATE_LIMIT_KEY}`;
378✔
174
  }
175

176
  static getSafeCacheDir(args: {
177
    chainId: string;
178
    safeAddress: Address;
179
  }): CacheDir {
180
    return new CacheDir(CacheRouter.getSafeCacheKey(args), '');
982✔
181
  }
182

183
  static getSafeCacheKey(args: {
184
    chainId: string;
185
    safeAddress: Address;
186
  }): string {
187
    return `${args.chainId}_${CacheRouter.SAFE_KEY}_${args.safeAddress}`;
1,016✔
188
  }
189

190
  static getIsSafeCacheDir(args: {
191
    chainId: string;
192
    safeAddress: Address;
193
  }): CacheDir {
194
    return new CacheDir(CacheRouter.getIsSafeCacheKey(args), '');
68✔
195
  }
196

197
  static getIsSafeCacheKey(args: {
198
    chainId: string;
199
    safeAddress: Address;
200
  }): string {
201
    return `${args.chainId}_${CacheRouter.SAFE_EXISTS_KEY}_${args.safeAddress}`;
72✔
202
  }
203

204
  static getBackboneCacheDir(chainId: string): CacheDir {
205
    return new CacheDir(`${chainId}_${CacheRouter.BACKBONE_KEY}`, '');
16✔
206
  }
207

208
  static getSingletonsCacheDir(chainId: string): CacheDir {
209
    return new CacheDir(`${chainId}_${CacheRouter.SINGLETONS_KEY}`, '');
68✔
210
  }
211

212
  static getCollectiblesCacheDir(args: {
213
    chainId: string;
214
    safeAddress: Address;
215
    limit?: number;
216
    offset?: number;
217
    trusted?: boolean;
218
    excludeSpam?: boolean;
219
  }): CacheDir {
220
    return new CacheDir(
10✔
221
      CacheRouter.getCollectiblesKey(args),
222
      `${args.limit}_${args.offset}_${args.trusted}_${args.excludeSpam}`,
223
    );
224
  }
225

226
  static getCollectiblesKey(args: {
227
    chainId: string;
228
    safeAddress: Address;
229
  }): string {
230
    return `${args.chainId}_${CacheRouter.SAFE_COLLECTIBLES_KEY}_${args.safeAddress}`;
54✔
231
  }
232

233
  static getDelegatesCacheKey(args: {
234
    chainId: string;
235
    safeAddress?: Address;
236
  }): string {
237
    return `${args.chainId}_${CacheRouter.DELEGATES_KEY}_${args.safeAddress}`;
168✔
238
  }
239

240
  static getDelegatesCacheDir(args: {
241
    chainId: string;
242
    safeAddress?: Address;
243
    delegate?: Address;
244
    delegator?: Address;
245
    label?: string;
246
    limit?: number;
247
    offset?: number;
248
  }): CacheDir {
249
    return new CacheDir(
162✔
250
      CacheRouter.getDelegatesCacheKey(args),
251
      `${args.delegate}_${args.delegator}_${args.label}_${args.limit}_${args.offset}`,
252
    );
253
  }
254

255
  static getFirebaseOAuth2TokenCacheDir(): CacheDir {
256
    return new CacheDir(CacheRouter.FIREBASE_OAUTH2_TOKEN_KEY, '');
8✔
257
  }
258

259
  static getTransferCacheDir(args: {
260
    chainId: string;
261
    transferId: string;
262
  }): CacheDir {
263
    return new CacheDir(
10✔
264
      `${args.chainId}_${CacheRouter.TRANSFER_KEY}_${args.transferId}`,
265
      '',
266
    );
267
  }
268

269
  static getTransfersCacheDir(args: {
270
    chainId: string;
271
    safeAddress: string;
272
    onlyErc20: boolean;
273
    onlyErc721: boolean;
274
    limit?: number;
275
    offset?: number;
276
    to?: string;
277
  }): CacheDir {
278
    return new CacheDir(
120✔
279
      CacheRouter.getTransfersCacheKey(args),
280
      `${args.onlyErc20}_${args.onlyErc721}_${args.limit}_${args.offset}_${args.to}`,
281
    );
282
  }
283

284
  static getTransfersCacheKey(args: {
285
    chainId: string;
286
    safeAddress: string;
287
  }): string {
288
    return `${args.chainId}_${CacheRouter.TRANSFERS_KEY}_${args.safeAddress}`;
182✔
289
  }
290

291
  static getModuleTransactionCacheDir(args: {
292
    chainId: string;
293
    moduleTransactionId: string;
294
  }): CacheDir {
295
    return new CacheDir(
12✔
296
      `${args.chainId}_${CacheRouter.MODULE_TRANSACTION_KEY}_${args.moduleTransactionId}`,
297
      '',
298
    );
299
  }
300

301
  static getModuleTransactionsCacheDir(args: {
302
    chainId: string;
303
    safeAddress: Address;
304
    to?: string;
305
    txHash?: string;
306
    module?: string;
307
    limit?: number;
308
    offset?: number;
309
  }): CacheDir {
310
    return new CacheDir(
70✔
311
      CacheRouter.getModuleTransactionsCacheKey(args),
312
      `${args.to}_${args.module}_${args.txHash}_${args.limit}_${args.offset}`,
313
    );
314
  }
315

316
  static getModuleTransactionsCacheKey(args: {
317
    chainId: string;
318
    safeAddress: Address;
319
  }): string {
320
    return `${args.chainId}_${CacheRouter.MODULE_TRANSACTIONS_KEY}_${args.safeAddress}`;
84✔
321
  }
322

323
  static getIncomingTransfersCacheDir(args: {
324
    chainId: string;
325
    safeAddress: string;
326
    executionDateGte?: string;
327
    executionDateLte?: string;
328
    to?: string;
329
    value?: string;
330
    tokenAddress?: string;
331
    txHash?: string;
332
    limit?: number;
333
    offset?: number;
334
  }): CacheDir {
335
    return new CacheDir(
40✔
336
      CacheRouter.getIncomingTransfersCacheKey(args),
337
      `${args.executionDateGte}_${args.executionDateLte}_${args.to}_${args.value}_${args.tokenAddress}_${args.txHash}_${args.limit}_${args.offset}`,
338
    );
339
  }
340

341
  static getIncomingTransfersCacheKey(args: {
342
    chainId: string;
343
    safeAddress: string;
344
  }): string {
345
    return `${args.chainId}_${CacheRouter.INCOMING_TRANSFERS_KEY}_${args.safeAddress}`;
70✔
346
  }
347

348
  static getIndexingCacheDir(chainId: string): CacheDir {
349
    return new CacheDir(`${chainId}_${CacheRouter.INDEXING_KEY}`, '');
12✔
350
  }
351

352
  static getMultisigTransactionsCacheDir(args: {
353
    chainId: string;
354
    safeAddress: string;
355
    ordering?: string;
356
    executed?: boolean;
357
    trusted?: boolean;
358
    executionDateGte?: string;
359
    executionDateLte?: string;
360
    to?: string;
361
    value?: string;
362
    nonce?: string;
363
    nonceGte?: number;
364
    limit?: number;
365
    offset?: number;
366
  }): CacheDir {
367
    return new CacheDir(
242✔
368
      CacheRouter.getMultisigTransactionsCacheKey(args),
369
      `${args.ordering}_${args.executed}_${args.trusted}_${args.executionDateGte}_${args.executionDateLte}_${args.to}_${args.value}_${args.nonce}_${args.nonceGte}_${args.limit}_${args.offset}`,
370
    );
371
  }
372

373
  static getMultisigTransactionsCacheKey(args: {
374
    chainId: string;
375
    safeAddress: string;
376
  }): string {
377
    return `${args.chainId}_${CacheRouter.MULTISIG_TRANSACTIONS_KEY}_${args.safeAddress}`;
346✔
378
  }
379

380
  static getMultisigTransactionCacheDir(args: {
381
    chainId: string;
382
    safeTransactionHash: string;
383
  }): CacheDir {
384
    return new CacheDir(CacheRouter.getMultisigTransactionCacheKey(args), '');
126✔
385
  }
386

387
  static getMultisigTransactionCacheKey(args: {
388
    chainId: string;
389
    safeTransactionHash: string;
390
  }): string {
391
    return `${args.chainId}_${CacheRouter.MULTISIG_TRANSACTION_KEY}_${args.safeTransactionHash}`;
190✔
392
  }
393

394
  static getCreationTransactionCacheDir(args: {
395
    chainId: string;
396
    safeAddress: Address;
397
  }): CacheDir {
398
    return new CacheDir(
18✔
399
      `${args.chainId}_${CacheRouter.CREATION_TRANSACTION_KEY}_${args.safeAddress}`,
400
      '',
401
    );
402
  }
403

404
  static getDecodedDataCacheKey(args: {
405
    chainId: string;
406
    data: Address;
407
    to: Address;
408
  }): string {
409
    return `${args.chainId}_${CacheRouter.DECODED_DATA_KEY}_${args.data}_${args.to}`;
532✔
410
  }
411

412
  static getDecodedDataCacheDir(args: {
413
    chainId: string;
414
    data: Address;
415
    to: Address;
416
  }): CacheDir {
417
    return new CacheDir(CacheRouter.getDecodedDataCacheKey(args), '');
532✔
418
  }
419

420
  static getContractsCacheKey(args: {
421
    chainId: string;
422
    address: Address;
423
  }): string {
424
    return `${args.chainId}_${CacheRouter.CONTRACTS_KEY}_${args.address}`;
1,354✔
425
  }
426

427
  static getContractsCacheDir(args: {
428
    chainId: string;
429
    address: Address;
430
  }): CacheDir {
431
    return new CacheDir(CacheRouter.getContractsCacheKey(args), '');
1,354✔
432
  }
433

434
  static getTrustedForDelegateCallContractsCacheKey(chainId: string): string {
435
    return `${chainId}_${CacheRouter.TRUSTED_FOR_DELEGATE_CALL_CONTRACTS_KEY}`;
14✔
436
  }
437

438
  static getTrustedForDelegateCallContractsCacheDir(args: {
439
    chainId: string;
440
    limit?: number;
441
    offset?: number;
442
  }): CacheDir {
443
    return new CacheDir(
14✔
444
      CacheRouter.getTrustedForDelegateCallContractsCacheKey(args.chainId),
445
      `${args.limit}_${args.offset}`,
446
    );
447
  }
448

449
  static getAllTransactionsCacheDir(args: {
450
    chainId: string;
451
    safeAddress: Address;
452
    ordering?: string;
453
    executed?: boolean;
454
    queued?: boolean;
455
    limit?: number;
456
    offset?: number;
457
  }): CacheDir {
458
    return new CacheDir(
78✔
459
      CacheRouter.getAllTransactionsKey(args),
460
      `${args.ordering}_${args.executed}_${args.queued}_${args.limit}_${args.offset}`,
461
    );
462
  }
463

464
  static getAllTransactionsKey(args: {
465
    chainId: string;
466
    safeAddress: Address;
467
  }): string {
468
    return `${args.chainId}_${CacheRouter.ALL_TRANSACTIONS_KEY}_${args.safeAddress}`;
152✔
469
  }
470

471
  static getTokenCacheDir(args: {
472
    chainId: string;
473
    address: string;
474
  }): CacheDir {
475
    return new CacheDir(
1,446✔
476
      `${args.chainId}_${CacheRouter.TOKEN_KEY}_${args.address}`,
477
      '',
478
    );
479
  }
480

481
  static getTokensCacheKey(chainId: string): string {
482
    return `${chainId}_${CacheRouter.TOKENS_KEY}`;
8✔
483
  }
484

485
  static getTokensCacheDir(args: {
486
    chainId: string;
487
    limit?: number;
488
    offset?: number;
489
  }): CacheDir {
490
    return new CacheDir(
8✔
491
      CacheRouter.getTokensCacheKey(args.chainId),
492
      `${args.limit}_${args.offset}`,
493
    );
494
  }
495

496
  static getSafesByOwnerCacheDir(args: {
497
    chainId: string;
498
    ownerAddress: Address;
499
  }): CacheDir {
500
    return new CacheDir(
24✔
501
      `${args.chainId}_${CacheRouter.OWNERS_SAFE_KEY}_${args.ownerAddress}`,
502
      '',
503
    );
504
  }
505

506
  static getMessageByHashCacheKey(args: {
507
    chainId: string;
508
    messageHash: string;
509
  }): string {
510
    return `${args.chainId}_${CacheRouter.MESSAGE_KEY}_${args.messageHash}`;
82✔
511
  }
512

513
  static getMessageByHashCacheDir(args: {
514
    chainId: string;
515
    messageHash: string;
516
  }): CacheDir {
517
    return new CacheDir(this.getMessageByHashCacheKey(args), '');
78✔
518
  }
519

520
  static getMessagesBySafeCacheKey(args: {
521
    chainId: string;
522
    safeAddress: Address;
523
  }): string {
524
    return `${args.chainId}_${CacheRouter.MESSAGES_KEY}_${args.safeAddress}`;
98✔
525
  }
526

527
  static getMessagesBySafeCacheDir(args: {
528
    chainId: string;
529
    safeAddress: Address;
530
    limit?: number;
531
    offset?: number;
532
  }): CacheDir {
533
    return new CacheDir(
70✔
534
      this.getMessagesBySafeCacheKey(args),
535
      `${args.limit}_${args.offset}`,
536
    );
537
  }
538

539
  static getChainsCacheKey(): string {
540
    return CacheRouter.CHAINS_KEY;
38✔
541
  }
542

543
  static getChainsCacheDir(args: {
544
    limit?: number;
545
    offset?: number;
546
  }): CacheDir {
547
    return new CacheDir(
24✔
548
      CacheRouter.getChainsCacheKey(),
549
      `${args.limit}_${args.offset}`,
550
    );
551
  }
552

553
  static getChainCacheKey(chainId: string): string {
554
    return `${chainId}_${CacheRouter.CHAIN_KEY}`;
2,342✔
555
  }
556

557
  static getChainCacheDir(chainId: string): CacheDir {
558
    return new CacheDir(CacheRouter.getChainCacheKey(chainId), '');
2,328✔
559
  }
560

561
  static getRelayKey(args: { chainId: string; address: Address }): string {
562
    return `${args.chainId}_${CacheRouter.RELAY_KEY}_${args.address}`;
918✔
563
  }
564

565
  static getRelayCacheDir(args: {
566
    chainId: string;
567
    address: Address;
568
  }): CacheDir {
569
    return new CacheDir(CacheRouter.getRelayKey(args), '');
918✔
570
  }
571

572
  static getSafeAppsKey(chainId: string): string {
573
    return `${chainId}_${CacheRouter.SAFE_APPS_KEY}`;
4✔
574
  }
575

576
  static getSafeAppsCacheDir(args: {
577
    chainId?: string;
578
    clientUrl?: string;
579
    onlyListed?: boolean;
580
    url?: string;
581
  }): CacheDir {
582
    return new CacheDir(
90✔
583
      `${args.chainId}_${CacheRouter.SAFE_APPS_KEY}`,
584
      `${args.clientUrl}_${args.onlyListed}_${args.url}`,
585
    );
586
  }
587

588
  static getNativeCoinPriceCacheDir(args: {
589
    nativeCoinId: string;
590
    fiatCode: string;
591
  }): CacheDir {
592
    return new CacheDir(
42✔
593
      `${args.nativeCoinId}_${CacheRouter.NATIVE_COIN_PRICE_KEY}_${args.fiatCode.toUpperCase()}`,
594
      '',
595
    );
596
  }
597

598
  static getTokenPriceCacheDir(args: {
599
    chainName: string;
600
    fiatCode: string;
601
    tokenAddress: string;
602
  }): CacheDir {
603
    return new CacheDir(
214✔
604
      `${args.chainName}_${CacheRouter.TOKEN_PRICE_KEY}_${args.tokenAddress}_${args.fiatCode.toUpperCase()}`,
605
      '',
606
    );
607
  }
608

609
  static getPriceFiatCodesCacheDir(): CacheDir {
610
    return new CacheDir(CacheRouter.SAFE_FIAT_CODES_KEY, '');
10✔
611
  }
612

613
  static getAccountCacheDir(address: Address): CacheDir {
614
    return new CacheDir(`${CacheRouter.ACCOUNT_KEY}_${address}`, '');
80✔
615
  }
616

617
  static getAccountDataTypesCacheDir(): CacheDir {
618
    return new CacheDir(CacheRouter.ACCOUNT_DATA_TYPES_KEY, '');
20✔
619
  }
620

621
  static getAccountDataSettingsCacheDir(address: Address): CacheDir {
622
    return new CacheDir(
22✔
623
      `${CacheRouter.ACCOUNT_DATA_SETTINGS_KEY}_${address}`,
624
      '',
625
    );
626
  }
627

628
  static getCounterfactualSafeCacheDir(
629
    chainId: string,
630
    predictedAddress: Address,
631
  ): CacheDir {
632
    return new CacheDir(
24✔
633
      `${chainId}_${CacheRouter.COUNTERFACTUAL_SAFE_KEY}_${predictedAddress}`,
634
      '',
635
    );
636
  }
637

638
  static getCounterfactualSafesCacheDir(address: Address): CacheDir {
639
    return new CacheDir(
78✔
640
      `${CacheRouter.COUNTERFACTUAL_SAFES_KEY}_${address}`,
641
      '',
642
    );
643
  }
644

645
  static getRpcRequestsKey(chainId: string): string {
646
    return `${chainId}_${CacheRouter.RPC_REQUESTS_KEY}`;
16✔
647
  }
648

649
  static getRpcRequestsCacheDir(args: {
650
    chainId: string;
651
    method: string;
652
    params: string;
653
  }): CacheDir {
654
    return new CacheDir(
12✔
655
      CacheRouter.getRpcRequestsKey(args.chainId),
656
      `${args.method}_${args.params}`,
657
    );
658
  }
659

660
  static getStakingDeploymentsCacheDir(
661
    cacheType: 'earn' | 'staking',
662
  ): CacheDir {
663
    return new CacheDir(this.STAKING_DEPLOYMENTS_KEY, cacheType);
52✔
664
  }
665

666
  static getStakingRewardsFeeCacheDir(args: {
667
    cacheType: 'earn' | 'staking';
668
    chainId: string;
669
    contract: Address;
670
  }): CacheDir {
671
    return new CacheDir(
22✔
672
      `${args.chainId}_${this.STAKING_REWARDS_FEE_KEY}_${args.contract}`,
673
      args.cacheType,
674
    );
675
  }
676

677
  static getStakingNetworkStatsCacheDir(
678
    cacheType: 'earn' | 'staking',
679
  ): CacheDir {
680
    return new CacheDir(this.STAKING_NETWORK_STATS_KEY, cacheType);
22✔
681
  }
682

683
  static getStakingDedicatedStakingStatsCacheDir(
684
    cacheType: 'earn' | 'staking',
685
  ): CacheDir {
686
    return new CacheDir(this.STAKING_DEDICATED_STAKING_STATS_KEY, cacheType);
14✔
687
  }
688

689
  static getStakingPooledStakingStatsCacheDir(args: {
690
    cacheType: 'earn' | 'staking';
691
    pool: Address;
692
  }): CacheDir {
693
    return new CacheDir(
4✔
694
      `${this.STAKING_POOLED_STAKING_STATS_KEY}_${args.pool}`,
695
      args.cacheType,
696
    );
697
  }
698

699
  static getStakingDefiVaultStatsCacheDir(args: {
700
    cacheType: 'earn' | 'staking';
701
    chainId: string;
702
    vault: Address;
703
  }): CacheDir {
704
    return new CacheDir(
6✔
705
      `${args.chainId}_${this.STAKING_DEFI_VAULT_STATS_KEY}_${args.vault}`,
706
      args.cacheType,
707
    );
708
  }
709

710
  static getStakingDefiVaultStakesCacheDir(args: {
711
    cacheType: 'earn' | 'staking';
712
    chainId: string;
713
    safeAddress: Address;
714
    vault: Address;
715
  }): CacheDir {
716
    return new CacheDir(
6✔
717
      `${args.chainId}_${this.STAKING_DEFI_VAULT_STAKES_KEY}_${args.safeAddress}_${args.vault}`,
718
      args.cacheType,
719
    );
720
  }
721

722
  static getStakingDefiMorphoExtraRewardsCacheDir(args: {
723
    cacheType: 'earn' | 'staking';
724
    chainId: string;
725
    safeAddress: Address;
726
  }): CacheDir {
727
    return new CacheDir(
4✔
728
      `${args.chainId}_${this.STAKING_DEFI_MORPHO_EXTRA_REWARDS_KEY}_${args.safeAddress}`,
729
      args.cacheType,
730
    );
731
  }
732

733
  /**
734
   * Calculated the chain/Safe-specific cache key of {@link Stake}.
735
   *
736
   * @param {string} args.chainId - Chain ID
737
   * @param {string} args.safeAddress - Safe address
738
   * @returns {string} - Cache key
739
   */
740
  static getStakingStakesCacheKey(args: {
741
    chainId: string;
742
    safeAddress: Address;
743
  }): string {
744
    return `${args.chainId}_${CacheRouter.STAKING_STAKES_KEY}_${args.safeAddress}`;
88✔
745
  }
746

747
  /**
748
   * Calculate cache directory for staking stakes.
749
   *
750
   * Note: This function hashes the validators' public keys to keep the
751
   * cache field short and deterministic. Redis and other cache systems
752
   * may experience performance degradation with long fields.
753
   *
754
   * @param {string} args.cacheType - Cache type (earn or staking)
755
   * @param {string} args.chainId - Chain ID
756
   * @param {string} args.safeAddress - Safe address
757
   * @param {string} args.validatorsPublicKeys - Array of validators public keys
758
   * @returns {@link CacheDir} - Cache directory
759
   */
760
  static getStakingStakesCacheDir(args: {
761
    cacheType: 'earn' | 'staking';
762
    chainId: string;
763
    safeAddress: Address;
764
    validatorsPublicKeys: Array<Address>;
765
  }): CacheDir {
766
    const hash = crypto.createHash('sha256');
22✔
767
    hash.update(args.validatorsPublicKeys.join('_'));
22✔
768
    return new CacheDir(
22✔
769
      CacheRouter.getStakingStakesCacheKey(args),
770
      `${args.cacheType}_${hash.digest('hex')}`,
771
    );
772
  }
773

774
  static getUnsupportedChainEventCacheKey(chainId: string): string {
775
    return `${chainId}_${this.UNSUPPORTED_CHAIN_EVENT}`;
54✔
776
  }
777

778
  static getStakingTransactionStatusCacheDir(args: {
779
    cacheType: 'earn' | 'staking';
780
    chainId: string;
781
    txHash: Hash;
782
  }): CacheDir {
783
    return new CacheDir(
8✔
784
      `${args.chainId}_${CacheRouter.STAKING_TRANSACTION_STATUS_KEY}_${args.txHash}`,
785
      args.cacheType,
786
    );
787
  }
788

789
  static getTargetedSafeCacheKey(outreachId: number): string {
790
    return `${CacheRouter.TARGETED_MESSAGING_TARGETED_SAFE_KEY}_${outreachId}`;
96✔
791
  }
792

793
  static getTargetedSafeCacheDir(args: {
794
    outreachId: number;
795
    safeAddress: Address;
796
    chainId?: string;
797
  }): CacheDir {
798
    return new CacheDir(
36✔
799
      CacheRouter.getTargetedSafeCacheKey(args.outreachId),
800
      `${args.safeAddress}_${args.chainId ?? 'null'}`,
29✔
801
    );
802
  }
803

804
  static getSubmissionCacheKey(outreachId: number): string {
805
    return `${CacheRouter.TARGETED_MESSAGING_SUBMISSION_KEY}_${outreachId}`;
28✔
806
  }
807

808
  static getSubmissionCacheDir(args: {
809
    outreachId: number;
810
    safeAddress: Address;
811
    signerAddress: Address;
812
    chainId: string | null;
813
  }): CacheDir {
814
    return new CacheDir(
16✔
815
      CacheRouter.getSubmissionCacheKey(args.outreachId),
816
      `${args.safeAddress}_${args.signerAddress}_${args.chainId ?? 'null'}`,
14✔
817
    );
818
  }
819

820
  static getOutreachesCacheDir(): CacheDir {
821
    return new CacheDir(CacheRouter.TARGETED_MESSAGING_OUTREACHES, '');
×
822
  }
823

824
  static getOutreachFileProcessorCacheKey(): string {
825
    return CacheRouter.TARGETED_MESSAGING_OUTREACH_FILE_PROCESSOR_LOCK;
66✔
826
  }
827

828
  static getOutreachFileProcessorCacheDir(): CacheDir {
829
    return new CacheDir(CacheRouter.getOutreachFileProcessorCacheKey(), '');
42✔
830
  }
831

832
  static getTransactionsExportCacheKey(args: {
833
    chainId: string;
834
    safeAddress: Address;
835
  }): string {
836
    return `${args.chainId}_${CacheRouter.TRANSACTIONS_EXPORT_KEY}_${args.safeAddress}`;
10✔
837
  }
838

839
  static getTransactionsExportCacheDir(args: {
840
    chainId: string;
841
    safeAddress: Address;
842
    executionDateGte?: string;
843
    executionDateLte?: string;
844
    limit?: number;
845
    offset?: number;
846
  }): CacheDir {
847
    return new CacheDir(
10✔
848
      CacheRouter.getTransactionsExportCacheKey(args),
849
      `${args.executionDateGte}_${args.executionDateLte}_${args.limit}_${args.offset}`,
850
    );
851
  }
852

853
  /**
854
   * Gets the in-memory cache key for the given cacheDir.
855
   */
856
  static getMemoryKey(cacheDir: CacheDir): string {
857
    return `${cacheDir.key}:${cacheDir.field}`;
306✔
858
  }
859

860
  /**
861
   * Gets Redis cache key for the ORM query cache.
862
   *
863
   * @param {string} prefix - Prefix for the cache key
864
   * @param {string} chainId - Chain ID
865
   * @param {string} safeAddress - Safe address
866
   *
867
   * @returns {string} - Cache key
868
   */
869
  static getOrnCacheKey(
870
    prefix: string,
871
    chainId: string,
872
    safeAddress: Address,
873
  ): string {
874
    return `${CacheRouter.ORM_QUERY_CACHE_KEY}:${prefix}:${chainId}:${safeAddress}`;
420✔
875
  }
876

877
  /**
878
   * Gets cache directory for contract analysis results.
879
   *
880
   * @param {string} args.chainId - Chain ID
881
   * @param {[Address, boolean][]} args.contractPairs - Array of pairs: contract address and isDelegateCall flag
882
   * @returns {CacheDir} - Cache directory
883
   */
884
  static getContractAnalysisCacheDir(args: {
885
    chainId: string;
886
    contractPairs: Array<[Address, boolean]>;
887
  }): CacheDir {
888
    const contractsHash = crypto.createHash('sha256');
16✔
889
    contractsHash.update(
16✔
890
      args.contractPairs.sort((a, b) => a[0].localeCompare(b[0])).join(','),
6✔
891
    );
892
    return new CacheDir(
16✔
893
      `${args.chainId}_${CacheRouter.CONTRACT_ANALYSIS_KEY}`,
894
      contractsHash.digest('hex'),
895
    );
896
  }
897

898
  /**
899
   * Gets cache directory for recipient analysis results.
900
   *
901
   * @param {string} args.chainId - Chain ID
902
   * @param {string} args.safeAddress - Safe address
903
   * @param {Address[]} args.recipients - Array of recipient addresses
904
   * @param {TransactionInfo} args.txInfo - The transaction info
905
   * @returns {CacheDir} - Cache directory
906
   */
907
  static getRecipientAnalysisCacheDir(args: {
908
    chainId: string;
909
    safeAddress: Address;
910
    recipients: Array<Address>;
911
    txInfo?: TransactionInfo;
912
  }): CacheDir {
913
    const hash = crypto.createHash('sha256');
34✔
914
    hash.update(args.recipients.sort().join(','));
34✔
915
    if (args.txInfo) {
34✔
916
      try {
18✔
917
        hash.update(JSON.stringify(args.txInfo));
18✔
918
      } catch {
919
        // fallback: do not update hash if serialization fails
920
      }
921
    }
922
    return new CacheDir(
34✔
923
      `${args.chainId}_${CacheRouter.RECIPIENT_ANALYSIS_KEY}_${args.safeAddress}`,
924
      hash.digest('hex'),
925
    );
926
  }
927

928
  static getPortfolioCacheKey(args: { address: Address }): string {
929
    return `${CacheRouter.PORTFOLIO_KEY}_${args.address}_zerion`;
30✔
930
  }
931

932
  static getPortfolioCacheDir(args: {
933
    address: Address;
934
    fiatCode: string;
935
    trusted?: boolean;
936
    isTestnet?: boolean;
937
  }): CacheDir {
938
    const trustedSuffix = args.trusted ? '_trusted' : '';
26✔
939
    const testnetSuffix = args.isTestnet ? '_testnet' : '';
26!
940
    return new CacheDir(
26✔
941
      CacheRouter.getPortfolioCacheKey(args),
942
      `${args.fiatCode.toUpperCase()}${trustedSuffix}${testnetSuffix}`,
943
    );
944
  }
945

946
  static getZerionChainsCacheDir(isTestnet: boolean): CacheDir {
NEW
947
    const field = isTestnet ? 'mapping_testnet' : 'mapping';
×
NEW
948
    return new CacheDir(CacheRouter.ZERION_CHAINS_KEY, field);
×
949
  }
950
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc