@reown/appkit-core-react-native 0.0.0-feat-multichain-20250925192219 → 0.0.0-feat-multichain-20250930155416

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.
Files changed (107) hide show
  1. package/lib/commonjs/controllers/ApiController.js +19 -8
  2. package/lib/commonjs/controllers/ApiController.js.map +1 -1
  3. package/lib/commonjs/controllers/BlockchainApiController.js +31 -28
  4. package/lib/commonjs/controllers/BlockchainApiController.js.map +1 -1
  5. package/lib/commonjs/controllers/ConnectionsController.js +5 -0
  6. package/lib/commonjs/controllers/ConnectionsController.js.map +1 -1
  7. package/lib/commonjs/controllers/EnsController.js +2 -0
  8. package/lib/commonjs/controllers/EnsController.js.map +1 -1
  9. package/lib/commonjs/controllers/EventsController.js +1 -0
  10. package/lib/commonjs/controllers/EventsController.js.map +1 -1
  11. package/lib/commonjs/controllers/LogController.js +189 -0
  12. package/lib/commonjs/controllers/LogController.js.map +1 -0
  13. package/lib/commonjs/controllers/OnRampController.js +14 -0
  14. package/lib/commonjs/controllers/OnRampController.js.map +1 -1
  15. package/lib/commonjs/controllers/SendController.js +2 -0
  16. package/lib/commonjs/controllers/SendController.js.map +1 -1
  17. package/lib/commonjs/controllers/SwapController.js +8 -0
  18. package/lib/commonjs/controllers/SwapController.js.map +1 -1
  19. package/lib/commonjs/controllers/TransactionsController.js +2 -0
  20. package/lib/commonjs/controllers/TransactionsController.js.map +1 -1
  21. package/lib/commonjs/features/reown-authentication/ReownAuthentication.js +14 -6
  22. package/lib/commonjs/features/reown-authentication/ReownAuthentication.js.map +1 -1
  23. package/lib/commonjs/index.js +14 -0
  24. package/lib/commonjs/index.js.map +1 -1
  25. package/lib/commonjs/utils/ApiUtil.js +1 -1
  26. package/lib/commonjs/utils/ApiUtil.js.map +1 -1
  27. package/lib/commonjs/utils/CoreHelperUtil.js.map +1 -1
  28. package/lib/commonjs/utils/FetchUtil.js +7 -2
  29. package/lib/commonjs/utils/FetchUtil.js.map +1 -1
  30. package/lib/commonjs/utils/LogUtils.js +131 -0
  31. package/lib/commonjs/utils/LogUtils.js.map +1 -0
  32. package/lib/commonjs/utils/StorageUtil.js +48 -49
  33. package/lib/commonjs/utils/StorageUtil.js.map +1 -1
  34. package/lib/module/controllers/ApiController.js +19 -8
  35. package/lib/module/controllers/ApiController.js.map +1 -1
  36. package/lib/module/controllers/BlockchainApiController.js +31 -28
  37. package/lib/module/controllers/BlockchainApiController.js.map +1 -1
  38. package/lib/module/controllers/ConnectionsController.js +5 -0
  39. package/lib/module/controllers/ConnectionsController.js.map +1 -1
  40. package/lib/module/controllers/EnsController.js +2 -0
  41. package/lib/module/controllers/EnsController.js.map +1 -1
  42. package/lib/module/controllers/EventsController.js +1 -0
  43. package/lib/module/controllers/EventsController.js.map +1 -1
  44. package/lib/module/controllers/LogController.js +186 -0
  45. package/lib/module/controllers/LogController.js.map +1 -0
  46. package/lib/module/controllers/OnRampController.js +14 -0
  47. package/lib/module/controllers/OnRampController.js.map +1 -1
  48. package/lib/module/controllers/SendController.js +2 -0
  49. package/lib/module/controllers/SendController.js.map +1 -1
  50. package/lib/module/controllers/SwapController.js +8 -0
  51. package/lib/module/controllers/SwapController.js.map +1 -1
  52. package/lib/module/controllers/TransactionsController.js +2 -0
  53. package/lib/module/controllers/TransactionsController.js.map +1 -1
  54. package/lib/module/features/reown-authentication/ReownAuthentication.js +14 -6
  55. package/lib/module/features/reown-authentication/ReownAuthentication.js.map +1 -1
  56. package/lib/module/index.js +2 -0
  57. package/lib/module/index.js.map +1 -1
  58. package/lib/module/utils/ApiUtil.js +1 -1
  59. package/lib/module/utils/ApiUtil.js.map +1 -1
  60. package/lib/module/utils/CoreHelperUtil.js.map +1 -1
  61. package/lib/module/utils/FetchUtil.js +8 -2
  62. package/lib/module/utils/FetchUtil.js.map +1 -1
  63. package/lib/module/utils/LogUtils.js +121 -0
  64. package/lib/module/utils/LogUtils.js.map +1 -0
  65. package/lib/module/utils/StorageUtil.js +48 -49
  66. package/lib/module/utils/StorageUtil.js.map +1 -1
  67. package/lib/typescript/controllers/ApiController.d.ts +6 -4
  68. package/lib/typescript/controllers/ApiController.d.ts.map +1 -1
  69. package/lib/typescript/controllers/BlockchainApiController.d.ts.map +1 -1
  70. package/lib/typescript/controllers/ConnectionsController.d.ts.map +1 -1
  71. package/lib/typescript/controllers/EnsController.d.ts.map +1 -1
  72. package/lib/typescript/controllers/EventsController.d.ts.map +1 -1
  73. package/lib/typescript/controllers/LogController.d.ts +69 -0
  74. package/lib/typescript/controllers/LogController.d.ts.map +1 -0
  75. package/lib/typescript/controllers/OnRampController.d.ts.map +1 -1
  76. package/lib/typescript/controllers/SendController.d.ts.map +1 -1
  77. package/lib/typescript/controllers/SwapController.d.ts.map +1 -1
  78. package/lib/typescript/controllers/TransactionsController.d.ts.map +1 -1
  79. package/lib/typescript/features/reown-authentication/ReownAuthentication.d.ts.map +1 -1
  80. package/lib/typescript/index.d.ts +2 -0
  81. package/lib/typescript/index.d.ts.map +1 -1
  82. package/lib/typescript/utils/ApiUtil.d.ts +1 -1
  83. package/lib/typescript/utils/CoreHelperUtil.d.ts +1 -1
  84. package/lib/typescript/utils/CoreHelperUtil.d.ts.map +1 -1
  85. package/lib/typescript/utils/FetchUtil.d.ts +1 -1
  86. package/lib/typescript/utils/FetchUtil.d.ts.map +1 -1
  87. package/lib/typescript/utils/LogUtils.d.ts +15 -0
  88. package/lib/typescript/utils/LogUtils.d.ts.map +1 -0
  89. package/lib/typescript/utils/StorageUtil.d.ts.map +1 -1
  90. package/package.json +3 -3
  91. package/src/controllers/ApiController.ts +28 -8
  92. package/src/controllers/BlockchainApiController.ts +39 -29
  93. package/src/controllers/ConnectionsController.ts +5 -0
  94. package/src/controllers/EnsController.ts +2 -0
  95. package/src/controllers/EventsController.ts +1 -0
  96. package/src/controllers/LogController.ts +253 -0
  97. package/src/controllers/OnRampController.ts +12 -0
  98. package/src/controllers/SendController.ts +2 -0
  99. package/src/controllers/SwapController.ts +8 -0
  100. package/src/controllers/TransactionsController.ts +2 -0
  101. package/src/features/reown-authentication/ReownAuthentication.ts +11 -6
  102. package/src/index.ts +8 -0
  103. package/src/utils/ApiUtil.ts +1 -1
  104. package/src/utils/CoreHelperUtil.ts +1 -1
  105. package/src/utils/FetchUtil.ts +11 -2
  106. package/src/utils/LogUtils.ts +179 -0
  107. package/src/utils/StorageUtil.ts +48 -49
@@ -19,6 +19,7 @@ import { OptionsController } from './OptionsController';
19
19
  import { ConstantsUtil, OnRampErrorType } from '../utils/ConstantsUtil';
20
20
  import { StorageUtil } from '../utils/StorageUtil';
21
21
  import { SnackController } from './SnackController';
22
+ import { LogController } from './LogController';
22
23
  import { EventsController } from './EventsController';
23
24
  import { BlockchainApiController, EXCLUDED_ONRAMP_PROVIDERS } from './BlockchainApiController';
24
25
  import { ConnectionsController } from './ConnectionsController';
@@ -142,6 +143,7 @@ export const OnRampController = {
142
143
 
143
144
  StorageUtil.setOnRampPreferredCountry(country);
144
145
  } catch (error) {
146
+ LogController.sendError(error, 'OnRampController.ts', 'setSelectedCountry');
145
147
  state.loading = false;
146
148
  state.error = {
147
149
  type: OnRampErrorType.FAILED_TO_LOAD_COUNTRIES,
@@ -240,6 +242,7 @@ export const OnRampController = {
240
242
  countries.find(c => c.countryCode === countryCode) || countries[0] || undefined;
241
243
  }
242
244
  } catch (error) {
245
+ LogController.sendError(error, 'OnRampController.ts', 'fetchCountries');
243
246
  state.error = {
244
247
  type: OnRampErrorType.FAILED_TO_LOAD_COUNTRIES,
245
248
  message: 'Failed to load countries'
@@ -261,6 +264,7 @@ export const OnRampController = {
261
264
 
262
265
  state.countriesDefaults = countriesDefaults;
263
266
  } catch (error) {
267
+ LogController.sendError(error, 'OnRampController.ts', 'fetchCountriesDefaults');
264
268
  state.error = {
265
269
  type: OnRampErrorType.FAILED_TO_LOAD_COUNTRIES,
266
270
  message: 'Failed to load countries defaults'
@@ -282,6 +286,7 @@ export const OnRampController = {
282
286
 
283
287
  state.serviceProviders = serviceProviders || [];
284
288
  } catch (error) {
289
+ LogController.sendError(error, 'OnRampController.ts', 'fetchServiceProviders');
285
290
  state.error = {
286
291
  type: OnRampErrorType.FAILED_TO_LOAD_PROVIDERS,
287
292
  message: 'Failed to load service providers'
@@ -313,6 +318,7 @@ export const OnRampController = {
313
318
 
314
319
  state.selectedPaymentMethod = state.paymentMethods[0];
315
320
  } catch (error) {
321
+ LogController.sendError(error, 'OnRampController.ts', 'fetchPaymentMethods');
316
322
  state.error = {
317
323
  type: OnRampErrorType.FAILED_TO_LOAD_METHODS,
318
324
  message: 'Failed to load payment methods'
@@ -342,6 +348,7 @@ export const OnRampController = {
342
348
 
343
349
  state.purchaseCurrency = selectedCurrency || undefined;
344
350
  } catch (error) {
351
+ LogController.sendError(error, 'OnRampController.ts', 'fetchCryptoCurrencies');
345
352
  state.error = {
346
353
  type: OnRampErrorType.FAILED_TO_LOAD_CURRENCIES,
347
354
  message: 'Failed to load crypto currencies'
@@ -385,6 +392,7 @@ export const OnRampController = {
385
392
  this.setPaymentCurrency(defaultCurrency);
386
393
  }
387
394
  } catch (error) {
395
+ LogController.sendError(error, 'OnRampController.ts', 'fetchFiatCurrencies');
388
396
  state.error = {
389
397
  type: OnRampErrorType.FAILED_TO_LOAD_CURRENCIES,
390
398
  message: 'Failed to load fiat currencies'
@@ -503,6 +511,7 @@ export const OnRampController = {
503
511
  sp => sp.serviceProvider === state.selectedQuote?.serviceProvider
504
512
  );
505
513
  } catch (error: any) {
514
+ LogController.sendError(error, 'OnRampController.ts', 'getQuotes');
506
515
  if (error.name === 'AbortError') {
507
516
  // Do nothing, another request was made
508
517
  return;
@@ -553,6 +562,7 @@ export const OnRampController = {
553
562
 
554
563
  state.paymentCurrenciesLimits = limits;
555
564
  } catch (error) {
565
+ LogController.sendError(error, 'OnRampController.ts', 'fetchFiatLimits');
556
566
  state.error = {
557
567
  type: OnRampErrorType.FAILED_TO_LOAD_LIMITS,
558
568
  message: 'Failed to load fiat limits'
@@ -617,6 +627,7 @@ export const OnRampController = {
617
627
 
618
628
  return widget;
619
629
  } catch (e: any) {
630
+ LogController.sendError(e, 'OnRampController.ts', 'generateWidget', { quote });
620
631
  EventsController.sendEvent({
621
632
  type: 'track',
622
633
  event: 'BUY_FAIL',
@@ -662,6 +673,7 @@ export const OnRampController = {
662
673
  this.fetchFiatCurrencies()
663
674
  ]);
664
675
  } catch (error) {
676
+ LogController.sendError(error, 'OnRampController.ts', 'loadOnRampData');
665
677
  if (!state.error) {
666
678
  state.error = {
667
679
  type: OnRampErrorType.FAILED_TO_LOAD,
@@ -9,6 +9,7 @@ import { RouterController } from './RouterController';
9
9
  import { ConnectionsController } from './ConnectionsController';
10
10
  import { SwapController } from './SwapController';
11
11
  import { ConstantsUtil as CoreConstantsUtil } from '../utils/ConstantsUtil';
12
+ import { LogController } from './LogController';
12
13
 
13
14
  // -- Types --------------------------------------------- //
14
15
  export interface TxParams {
@@ -120,6 +121,7 @@ export const SendController = {
120
121
  RouterController.reset(isAuth ? 'Account' : 'AccountDefault');
121
122
  this.resetState();
122
123
  } catch (error: any) {
124
+ LogController.sendError(error, 'SendController.ts', 'sendToken');
123
125
  EventsController.sendEvent({
124
126
  type: 'track',
125
127
  event: 'SEND_ERROR',
@@ -14,6 +14,7 @@ import { BlockchainApiController } from './BlockchainApiController';
14
14
  import { OptionsController } from './OptionsController';
15
15
  import { SwapCalculationUtil } from '../utils/SwapCalculationUtil';
16
16
  import { SnackController } from './SnackController';
17
+ import { LogController } from './LogController';
17
18
  import { RouterController } from './RouterController';
18
19
  import { CoreHelperUtil } from '../utils/CoreHelperUtil';
19
20
  import { TransactionsController } from './TransactionsController';
@@ -249,6 +250,7 @@ export const SwapController = {
249
250
  this.setSourceTokenAmount('1');
250
251
  }
251
252
  } catch (error) {
253
+ LogController.sendError(error, 'SwapController.ts', 'initializeState');
252
254
  SnackController.showError('Failed to initialize swap');
253
255
  RouterController.goBack();
254
256
  } finally {
@@ -491,6 +493,7 @@ export const SwapController = {
491
493
  this.setTransactionDetails();
492
494
  }
493
495
  } catch (error) {
496
+ LogController.sendError(error, 'SwapController.ts', 'getQuote');
494
497
  SnackController.showError('Failed to get swap quote');
495
498
  } finally {
496
499
  state.loadingQuote = false;
@@ -750,6 +753,11 @@ export const SwapController = {
750
753
  return transactionHash;
751
754
  } catch (err) {
752
755
  const error = err as TransactionError;
756
+ LogController.sendError(error, 'SwapController.ts', 'sendTransactionForSwap', {
757
+ sourceToken: this.state.sourceToken?.symbol,
758
+ toToken: this.state.toToken?.symbol,
759
+ amount: this.state.sourceTokenAmount
760
+ });
753
761
  state.transactionError = error?.shortMessage;
754
762
  state.loadingTransaction = false;
755
763
  SnackController.showError(error?.shortMessage ?? 'Transaction error');
@@ -5,6 +5,7 @@ import { EventsController } from './EventsController';
5
5
  import { SnackController } from './SnackController';
6
6
  import { BlockchainApiController } from './BlockchainApiController';
7
7
  import { ConnectionsController } from './ConnectionsController';
8
+ import { LogController } from './LogController';
8
9
 
9
10
  // -- Types --------------------------------------------- //
10
11
  type TransactionByMonthMap = Record<string, Transaction[]>;
@@ -74,6 +75,7 @@ export const TransactionsController = {
74
75
  state.empty = nonSpamTransactions.length === 0;
75
76
  state.next = response?.next ? response.next : undefined;
76
77
  } catch (error) {
78
+ LogController.sendError(error, 'TransactionsController.ts', 'fetchTransactions');
77
79
  EventsController.sendEvent({
78
80
  type: 'track',
79
81
  event: 'ERROR_FETCH_TRANSACTIONS',
@@ -16,6 +16,8 @@ import { ConnectionsController } from '../../controllers/ConnectionsController';
16
16
  import { CoreHelperUtil } from '../../utils/CoreHelperUtil';
17
17
  import { OptionsController } from '../../controllers/OptionsController';
18
18
  import { FetchUtil } from '../../utils/FetchUtil';
19
+ import { ApiUtil } from '../../utils/ApiUtil';
20
+ import { LogController } from '../../controllers/LogController';
19
21
 
20
22
  /**
21
23
  * This is the configuration for using SIWX with Reown Authentication service.
@@ -108,7 +110,9 @@ export class ReownAuthentication implements SIWXConfig {
108
110
  this.emit('sessionChanged', session);
109
111
 
110
112
  return [session];
111
- } catch {
113
+ } catch (error) {
114
+ LogController.sendError(error, 'ReownAuthentication.ts', 'getSessions');
115
+
112
116
  return [];
113
117
  }
114
118
  }
@@ -299,13 +303,14 @@ export class ReownAuthentication implements SIWXConfig {
299
303
  }
300
304
 
301
305
  private getSDKProperties(): { projectId: string; st: string; sv: string; domain: string } {
302
- const headers = ApiController._getApiHeaders();
306
+ const { projectId, st, sv } = ApiController._getApiParams();
307
+ const domain = ApiUtil.getOrigin();
303
308
 
304
309
  return {
305
- projectId: headers['x-project-id'],
306
- st: headers['x-sdk-type'],
307
- sv: headers['x-sdk-version'],
308
- domain: headers['origin']
310
+ projectId,
311
+ st,
312
+ sv,
313
+ domain
309
314
  };
310
315
  }
311
316
 
package/src/index.ts CHANGED
@@ -16,6 +16,13 @@ export {
16
16
 
17
17
  export { SnackController, type SnackControllerState } from './controllers/SnackController';
18
18
 
19
+ export {
20
+ LogController,
21
+ type LogControllerState,
22
+ type LogEntry,
23
+ type LogLevel
24
+ } from './controllers/LogController';
25
+
19
26
  export { ApiController, type ApiControllerState } from './controllers/ApiController';
20
27
 
21
28
  export { AssetController, type AssetControllerState } from './controllers/AssetController';
@@ -54,6 +61,7 @@ export { CoreHelperUtil } from './utils/CoreHelperUtil';
54
61
  export { StorageUtil } from './utils/StorageUtil';
55
62
  export { EventUtil } from './utils/EventUtil';
56
63
  export { WalletUtil } from './utils/WalletUtil';
64
+ export { LogUtils } from './utils/LogUtils';
57
65
 
58
66
  // -- Features ----------------------------------------------------------------
59
67
  export { ReownAuthentication } from './features/reown-authentication/ReownAuthentication';
@@ -3,7 +3,7 @@ import { CoreHelperUtil } from './CoreHelperUtil';
3
3
 
4
4
  export const ApiUtil = {
5
5
  getOrigin() {
6
- return CoreHelperUtil.getBundleId();
6
+ return CoreHelperUtil.getBundleId() ?? 'react-native-unknown-origin';
7
7
  },
8
8
 
9
9
  getReactNativeVersion() {
@@ -252,7 +252,7 @@ export const CoreHelperUtil = {
252
252
  });
253
253
  },
254
254
 
255
- getBundleId() {
255
+ getBundleId(): string | undefined {
256
256
  if ((global as any)?.Application?.applicationId) {
257
257
  return (global as any)?.Application?.applicationId;
258
258
  }
@@ -1,4 +1,5 @@
1
1
  import type { RequestCache } from '@reown/appkit-common-react-native';
2
+ import { LogController } from '../controllers/LogController';
2
3
 
3
4
  // -- Types ----------------------------------------------------------------------
4
5
  interface Options {
@@ -71,9 +72,13 @@ export class FetchUtil {
71
72
  return this.processResponse<T>(response);
72
73
  }
73
74
 
74
- public async fetchImage(path: string, headers?: Record<string, string>) {
75
+ public async fetchImage(
76
+ path: string,
77
+ headers?: Record<string, string>,
78
+ params?: Record<string, string>
79
+ ) {
75
80
  try {
76
- const url = this.createUrl({ path }).toString();
81
+ const url = this.createUrl({ path, params }).toString();
77
82
  const response = await fetch(url, { headers });
78
83
  const blob = await response.blob();
79
84
  const reader = new FileReader();
@@ -130,14 +135,18 @@ export class FetchUtil {
130
135
  if (response.headers.get('content-type')?.includes('application/json')) {
131
136
  try {
132
137
  const errorData = await response.json();
138
+ LogController.sendError(errorData, 'FetchUtil.ts', 'processResponse');
133
139
 
134
140
  return Promise.reject(errorData);
135
141
  } catch (jsonError) {
142
+ LogController.sendError(jsonError, 'FetchUtil.ts', 'processResponse');
143
+
136
144
  return Promise.reject(`Code: ${response.status} - ${response.statusText}`);
137
145
  }
138
146
  }
139
147
 
140
148
  const errorText = await response.text();
149
+ LogController.sendError(errorText, 'FetchUtil.ts', 'processResponse');
141
150
 
142
151
  return Promise.reject(`Code: ${response.status} - ${response.statusText} - ${errorText}`);
143
152
  }
@@ -0,0 +1,179 @@
1
+ // -- Constants ----------------------------------------- //
2
+ const SENSITIVE_KEYS = [
3
+ 'password',
4
+ 'pass',
5
+ 'pwd',
6
+ 'secret',
7
+ 'token',
8
+ 'key',
9
+ 'auth',
10
+ 'authorization',
11
+ 'bearer',
12
+ 'credential',
13
+ 'api_key',
14
+ 'apikey',
15
+ 'access_token',
16
+ 'refresh_token',
17
+ 'private_key',
18
+ 'privatekey',
19
+ 'mnemonic',
20
+ 'seed',
21
+ 'phrase',
22
+ 'wallet',
23
+ 'address',
24
+ 'email',
25
+ 'phone',
26
+ 'ssn',
27
+ 'social',
28
+ 'credit',
29
+ 'card',
30
+ 'cvv',
31
+ 'connection_string',
32
+ 'connection',
33
+ 'user_token'
34
+ ];
35
+
36
+ const MAX_STRING_LENGTH = 480; // Maximum length for any string value (account for potential replacements)
37
+ const MAX_STACK_LINES = 10; // Maximum lines in stack trace
38
+
39
+ // -- Data Sanitization Functions ---------------------- //
40
+ export const sanitizeString = (value: string): string => {
41
+ if (typeof value !== 'string') {
42
+ value = String(value);
43
+ }
44
+
45
+ if (value.length > MAX_STRING_LENGTH) {
46
+ return value.substring(0, MAX_STRING_LENGTH) + '... [truncated]';
47
+ }
48
+
49
+ return value;
50
+ };
51
+
52
+ export const sanitizeStackTrace = (stack: string): string => {
53
+ if (typeof stack !== 'string') {
54
+ stack = String(stack);
55
+ }
56
+
57
+ const lines = stack.split('\n');
58
+ const sanitizedLines = lines.slice(0, MAX_STACK_LINES).map(line => {
59
+ // Remove file paths that might contain sensitive info
60
+ return line.replace(/\/[^\s]*\//g, '/[path]/');
61
+ });
62
+
63
+ if (lines.length > MAX_STACK_LINES) {
64
+ sanitizedLines.push('... [stack trace truncated]');
65
+ }
66
+
67
+ return sanitizedLines.join('\n');
68
+ };
69
+
70
+ export const sanitizeUrl = (url: string): string => {
71
+ try {
72
+ const urlObj = new URL(url);
73
+ // Remove query parameters that might contain sensitive data
74
+ urlObj.search = '';
75
+ // Keep only the origin and pathname
76
+
77
+ return urlObj.origin + urlObj.pathname;
78
+ } catch {
79
+ // If URL parsing fails, just return sanitized string
80
+
81
+ return sanitizeString(url);
82
+ }
83
+ };
84
+
85
+ const isSensitiveKey = (key: string): boolean => {
86
+ const lowerKey = key.toLowerCase();
87
+
88
+ return SENSITIVE_KEYS.some(sensitiveKey => lowerKey.includes(sensitiveKey));
89
+ };
90
+
91
+ export const sanitizeValue = (value: unknown, visited = new WeakSet()): unknown => {
92
+ if (value === null || value === undefined) {
93
+ return value;
94
+ }
95
+
96
+ if (typeof value === 'string') {
97
+ // Check if it looks like a URL
98
+ if (value.startsWith('http://') || value.startsWith('https://')) {
99
+ return sanitizeUrl(value);
100
+ }
101
+
102
+ return sanitizeString(value);
103
+ }
104
+
105
+ if (typeof value === 'number' || typeof value === 'boolean') {
106
+ return value;
107
+ }
108
+
109
+ if (Array.isArray(value)) {
110
+ // Prevent circular references in arrays
111
+ if (visited.has(value)) {
112
+ return '[Circular Reference]';
113
+ }
114
+
115
+ visited.add(value);
116
+ const result = value.slice(0, 10).map(item => sanitizeValue(item, visited));
117
+ visited.delete(value);
118
+
119
+ return result;
120
+ }
121
+
122
+ if (typeof value === 'object') {
123
+ return sanitizeObject(value as Record<string, unknown>, visited);
124
+ }
125
+
126
+ // For other types, convert to string and sanitize
127
+ return sanitizeString(String(value));
128
+ };
129
+
130
+ export const sanitizeObject = (
131
+ obj: Record<string, unknown>,
132
+ visited = new WeakSet()
133
+ ): Record<string, unknown> => {
134
+ // Prevent circular references
135
+ if (visited.has(obj)) {
136
+ return { '[Circular Reference]': true };
137
+ }
138
+
139
+ visited.add(obj);
140
+
141
+ const sanitized: Record<string, unknown> = {};
142
+ const keys = Object.keys(obj).slice(0, 20); // Limit number of keys
143
+
144
+ for (const key of keys) {
145
+ if (isSensitiveKey(key)) {
146
+ sanitized[key] = '[REDACTED]';
147
+ } else {
148
+ sanitized[key] = sanitizeValue(obj[key], visited);
149
+ }
150
+ }
151
+
152
+ if (Object.keys(obj).length > 20) {
153
+ sanitized['...'] = '[additional properties truncated]';
154
+ }
155
+
156
+ visited.delete(obj);
157
+
158
+ return sanitized;
159
+ };
160
+
161
+ export const sanitizeData = (
162
+ data?: Record<string, unknown>
163
+ ): Record<string, unknown> | undefined => {
164
+ if (!data) {
165
+ return undefined;
166
+ }
167
+
168
+ return sanitizeObject(data);
169
+ };
170
+
171
+ // -- Utility Functions --------------------------------- //
172
+ export const LogUtils = {
173
+ sanitizeString,
174
+ sanitizeStackTrace,
175
+ sanitizeUrl,
176
+ sanitizeValue,
177
+ sanitizeObject,
178
+ sanitizeData
179
+ };