@reown/appkit-core-react-native 0.0.0-chore-spring-effect-20250909214820 → 0.0.0-chore-examples-20251009175707

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 (150) 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 +13 -3
  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 +51 -1
  10. package/lib/commonjs/controllers/EventsController.js.map +1 -1
  11. package/lib/commonjs/controllers/LogController.js +188 -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/OptionsController.js +6 -3
  16. package/lib/commonjs/controllers/OptionsController.js.map +1 -1
  17. package/lib/commonjs/controllers/SendController.js +18 -2
  18. package/lib/commonjs/controllers/SendController.js.map +1 -1
  19. package/lib/commonjs/controllers/SwapController.js +10 -2
  20. package/lib/commonjs/controllers/SwapController.js.map +1 -1
  21. package/lib/commonjs/controllers/ThemeController.js +5 -0
  22. package/lib/commonjs/controllers/ThemeController.js.map +1 -1
  23. package/lib/commonjs/controllers/TransactionsController.js +2 -0
  24. package/lib/commonjs/controllers/TransactionsController.js.map +1 -1
  25. package/lib/commonjs/features/reown-authentication/ReownAuthentication.js +272 -0
  26. package/lib/commonjs/features/reown-authentication/ReownAuthentication.js.map +1 -0
  27. package/lib/commonjs/features/reown-authentication/ReownAuthenticationMessenger.js +48 -0
  28. package/lib/commonjs/features/reown-authentication/ReownAuthenticationMessenger.js.map +1 -0
  29. package/lib/commonjs/features/reown-authentication/index.js +28 -0
  30. package/lib/commonjs/features/reown-authentication/index.js.map +1 -0
  31. package/lib/commonjs/index.js +28 -0
  32. package/lib/commonjs/index.js.map +1 -1
  33. package/lib/commonjs/utils/ApiUtil.js +1 -1
  34. package/lib/commonjs/utils/ApiUtil.js.map +1 -1
  35. package/lib/commonjs/utils/ConstantsUtil.js +0 -1
  36. package/lib/commonjs/utils/ConstantsUtil.js.map +1 -1
  37. package/lib/commonjs/utils/CoreHelperUtil.js +13 -2
  38. package/lib/commonjs/utils/CoreHelperUtil.js.map +1 -1
  39. package/lib/commonjs/utils/FetchUtil.js +7 -2
  40. package/lib/commonjs/utils/FetchUtil.js.map +1 -1
  41. package/lib/commonjs/utils/LogUtils.js +131 -0
  42. package/lib/commonjs/utils/LogUtils.js.map +1 -0
  43. package/lib/commonjs/utils/StorageUtil.js +75 -76
  44. package/lib/commonjs/utils/StorageUtil.js.map +1 -1
  45. package/lib/module/controllers/ApiController.js +19 -8
  46. package/lib/module/controllers/ApiController.js.map +1 -1
  47. package/lib/module/controllers/BlockchainApiController.js +31 -28
  48. package/lib/module/controllers/BlockchainApiController.js.map +1 -1
  49. package/lib/module/controllers/ConnectionsController.js +14 -4
  50. package/lib/module/controllers/ConnectionsController.js.map +1 -1
  51. package/lib/module/controllers/EnsController.js +2 -0
  52. package/lib/module/controllers/EnsController.js.map +1 -1
  53. package/lib/module/controllers/EventsController.js +51 -1
  54. package/lib/module/controllers/EventsController.js.map +1 -1
  55. package/lib/module/controllers/LogController.js +185 -0
  56. package/lib/module/controllers/LogController.js.map +1 -0
  57. package/lib/module/controllers/OnRampController.js +14 -0
  58. package/lib/module/controllers/OnRampController.js.map +1 -1
  59. package/lib/module/controllers/OptionsController.js +6 -3
  60. package/lib/module/controllers/OptionsController.js.map +1 -1
  61. package/lib/module/controllers/SendController.js +18 -2
  62. package/lib/module/controllers/SendController.js.map +1 -1
  63. package/lib/module/controllers/SwapController.js +10 -2
  64. package/lib/module/controllers/SwapController.js.map +1 -1
  65. package/lib/module/controllers/ThemeController.js +5 -0
  66. package/lib/module/controllers/ThemeController.js.map +1 -1
  67. package/lib/module/controllers/TransactionsController.js +2 -0
  68. package/lib/module/controllers/TransactionsController.js.map +1 -1
  69. package/lib/module/features/reown-authentication/ReownAuthentication.js +268 -0
  70. package/lib/module/features/reown-authentication/ReownAuthentication.js.map +1 -0
  71. package/lib/module/features/reown-authentication/ReownAuthenticationMessenger.js +43 -0
  72. package/lib/module/features/reown-authentication/ReownAuthenticationMessenger.js.map +1 -0
  73. package/lib/module/features/reown-authentication/index.js +5 -0
  74. package/lib/module/features/reown-authentication/index.js.map +1 -0
  75. package/lib/module/index.js +6 -0
  76. package/lib/module/index.js.map +1 -1
  77. package/lib/module/utils/ApiUtil.js +1 -1
  78. package/lib/module/utils/ApiUtil.js.map +1 -1
  79. package/lib/module/utils/ConstantsUtil.js +0 -1
  80. package/lib/module/utils/ConstantsUtil.js.map +1 -1
  81. package/lib/module/utils/CoreHelperUtil.js +13 -2
  82. package/lib/module/utils/CoreHelperUtil.js.map +1 -1
  83. package/lib/module/utils/FetchUtil.js +8 -2
  84. package/lib/module/utils/FetchUtil.js.map +1 -1
  85. package/lib/module/utils/LogUtils.js +121 -0
  86. package/lib/module/utils/LogUtils.js.map +1 -0
  87. package/lib/module/utils/StorageUtil.js +76 -77
  88. package/lib/module/utils/StorageUtil.js.map +1 -1
  89. package/lib/typescript/controllers/ApiController.d.ts +6 -4
  90. package/lib/typescript/controllers/ApiController.d.ts.map +1 -1
  91. package/lib/typescript/controllers/BlockchainApiController.d.ts.map +1 -1
  92. package/lib/typescript/controllers/ConnectionsController.d.ts +1 -0
  93. package/lib/typescript/controllers/ConnectionsController.d.ts.map +1 -1
  94. package/lib/typescript/controllers/EnsController.d.ts.map +1 -1
  95. package/lib/typescript/controllers/EventsController.d.ts +13 -1
  96. package/lib/typescript/controllers/EventsController.d.ts.map +1 -1
  97. package/lib/typescript/controllers/LogController.d.ts +65 -0
  98. package/lib/typescript/controllers/LogController.d.ts.map +1 -0
  99. package/lib/typescript/controllers/OnRampController.d.ts.map +1 -1
  100. package/lib/typescript/controllers/OptionsController.d.ts +3 -3
  101. package/lib/typescript/controllers/OptionsController.d.ts.map +1 -1
  102. package/lib/typescript/controllers/RouterController.d.ts +1 -1
  103. package/lib/typescript/controllers/RouterController.d.ts.map +1 -1
  104. package/lib/typescript/controllers/SendController.d.ts.map +1 -1
  105. package/lib/typescript/controllers/SwapController.d.ts.map +1 -1
  106. package/lib/typescript/controllers/ThemeController.d.ts +2 -0
  107. package/lib/typescript/controllers/ThemeController.d.ts.map +1 -1
  108. package/lib/typescript/controllers/TransactionsController.d.ts.map +1 -1
  109. package/lib/typescript/features/reown-authentication/ReownAuthentication.d.ts +174 -0
  110. package/lib/typescript/features/reown-authentication/ReownAuthentication.d.ts.map +1 -0
  111. package/lib/typescript/features/reown-authentication/ReownAuthenticationMessenger.d.ts +16 -0
  112. package/lib/typescript/features/reown-authentication/ReownAuthenticationMessenger.d.ts.map +1 -0
  113. package/lib/typescript/features/reown-authentication/index.d.ts +3 -0
  114. package/lib/typescript/features/reown-authentication/index.d.ts.map +1 -0
  115. package/lib/typescript/index.d.ts +4 -0
  116. package/lib/typescript/index.d.ts.map +1 -1
  117. package/lib/typescript/utils/ApiUtil.d.ts +1 -1
  118. package/lib/typescript/utils/ConstantsUtil.d.ts +0 -1
  119. package/lib/typescript/utils/ConstantsUtil.d.ts.map +1 -1
  120. package/lib/typescript/utils/CoreHelperUtil.d.ts +3 -2
  121. package/lib/typescript/utils/CoreHelperUtil.d.ts.map +1 -1
  122. package/lib/typescript/utils/FetchUtil.d.ts +2 -2
  123. package/lib/typescript/utils/FetchUtil.d.ts.map +1 -1
  124. package/lib/typescript/utils/LogUtils.d.ts +15 -0
  125. package/lib/typescript/utils/LogUtils.d.ts.map +1 -0
  126. package/lib/typescript/utils/StorageUtil.d.ts.map +1 -1
  127. package/package.json +6 -5
  128. package/src/controllers/ApiController.ts +28 -8
  129. package/src/controllers/BlockchainApiController.ts +39 -29
  130. package/src/controllers/ConnectionsController.ts +27 -3
  131. package/src/controllers/EnsController.ts +2 -0
  132. package/src/controllers/EventsController.ts +73 -2
  133. package/src/controllers/LogController.ts +250 -0
  134. package/src/controllers/OnRampController.ts +12 -0
  135. package/src/controllers/OptionsController.ts +11 -6
  136. package/src/controllers/RouterController.ts +3 -3
  137. package/src/controllers/SendController.ts +28 -3
  138. package/src/controllers/SwapController.ts +10 -2
  139. package/src/controllers/ThemeController.ts +7 -0
  140. package/src/controllers/TransactionsController.ts +2 -0
  141. package/src/features/reown-authentication/ReownAuthentication.ts +475 -0
  142. package/src/features/reown-authentication/ReownAuthenticationMessenger.ts +80 -0
  143. package/src/features/reown-authentication/index.ts +2 -0
  144. package/src/index.ts +12 -0
  145. package/src/utils/ApiUtil.ts +1 -1
  146. package/src/utils/ConstantsUtil.ts +0 -1
  147. package/src/utils/CoreHelperUtil.ts +21 -3
  148. package/src/utils/FetchUtil.ts +12 -3
  149. package/src/utils/LogUtils.ts +179 -0
  150. package/src/utils/StorageUtil.ts +85 -102
@@ -42,17 +42,24 @@ import { ConstantsUtil } from '../utils/ConstantsUtil';
42
42
  import { ApiUtil } from '../utils/ApiUtil';
43
43
 
44
44
  import { SnackController } from './SnackController';
45
+ import { LogController } from './LogController';
45
46
 
46
47
  // -- Helpers ------------------------------------------- //
47
48
  const baseUrl = CoreHelperUtil.getBlockchainApiUrl();
48
49
 
49
- const getHeaders = () => {
50
- const { sdkType, sdkVersion } = OptionsController.state;
50
+ const getParams = () => {
51
+ const { projectId, sdkType, sdkVersion } = OptionsController.state;
51
52
 
53
+ return {
54
+ projectId,
55
+ st: sdkType,
56
+ sv: sdkVersion
57
+ };
58
+ };
59
+
60
+ const getHeaders = () => {
52
61
  return {
53
62
  'Content-Type': 'application/json',
54
- 'x-sdk-type': sdkType,
55
- 'x-sdk-version': sdkVersion,
56
63
  'User-Agent': ApiUtil.getUserAgent(),
57
64
  'origin': ApiUtil.getOrigin()
58
65
  };
@@ -89,6 +96,8 @@ export const BlockchainApiController = {
89
96
  await BlockchainApiController.getSupportedNetworks();
90
97
  }
91
98
  } catch (e) {
99
+ LogController.sendError(e, 'BlockchainApiController.ts', 'isNetworkSupported');
100
+
92
101
  return false;
93
102
  }
94
103
 
@@ -97,7 +106,8 @@ export const BlockchainApiController = {
97
106
 
98
107
  async getSupportedNetworks() {
99
108
  const supportedChains = await state.api.get<BlockchainApiControllerState['supportedChains']>({
100
- path: 'v1/supported-chains'
109
+ path: 'v1/supported-chains',
110
+ params: getParams()
101
111
  });
102
112
 
103
113
  state.supportedChains = supportedChains!;
@@ -110,15 +120,13 @@ export const BlockchainApiController = {
110
120
 
111
121
  return state.api.get<BlockchainApiIdentityResponse>({
112
122
  path: `/v1/identity/${address}`,
113
- params: {
114
- projectId: OptionsController.state.projectId
115
- },
116
- headers: getHeaders()
123
+ headers: getHeaders(),
124
+ params: getParams()
117
125
  });
118
126
  },
119
127
 
120
128
  async fetchTransactions(params: BlockchainApiTransactionsRequest) {
121
- const { account, projectId, cursor, signal, cache, chainId } = params;
129
+ const { account, cursor, signal, cache, chainId } = params;
122
130
  const isSupported = ConstantsUtil.ACTIVITY_SUPPORTED_CHAINS.includes(chainId);
123
131
 
124
132
  if (!isSupported) {
@@ -129,7 +137,7 @@ export const BlockchainApiController = {
129
137
  path: `/v1/account/${account}/history`,
130
138
  headers: getHeaders(),
131
139
  params: {
132
- projectId,
140
+ ...getParams(),
133
141
  cursor,
134
142
  chainId
135
143
  },
@@ -150,19 +158,20 @@ export const BlockchainApiController = {
150
158
 
151
159
  const response = await state.api.post<BlockchainApiTokenPriceResponse>({
152
160
  path: '/v1/fungible/price',
161
+ headers: getHeaders(),
162
+ params: getParams(),
153
163
  body: {
154
164
  projectId,
155
165
  currency: 'usd',
156
166
  addresses
157
- },
158
- headers: getHeaders()
167
+ }
159
168
  });
160
169
 
161
170
  return response;
162
171
  },
163
172
 
164
173
  async fetchSwapAllowance(params: BlockchainApiSwapAllowanceRequest) {
165
- const { projectId, tokenAddress, userAddress } = params;
174
+ const { tokenAddress, userAddress } = params;
166
175
  const [namespace, chain] = userAddress.split(':');
167
176
  const networkId: CaipNetworkId = `${namespace}:${chain}`;
168
177
  const isSupported = await BlockchainApiController.isNetworkSupported(networkId);
@@ -174,7 +183,7 @@ export const BlockchainApiController = {
174
183
  return state.api.get<BlockchainApiSwapAllowanceResponse>({
175
184
  path: `/v1/convert/allowance`,
176
185
  params: {
177
- projectId,
186
+ ...getParams(),
178
187
  tokenAddress,
179
188
  userAddress
180
189
  },
@@ -183,7 +192,7 @@ export const BlockchainApiController = {
183
192
  },
184
193
 
185
194
  async fetchGasPrice(params: BlockchainApiGasPriceRequest) {
186
- const { projectId, chainId } = params;
195
+ const { chainId } = params;
187
196
  const isSupported = await BlockchainApiController.isNetworkSupported(chainId);
188
197
 
189
198
  if (!isSupported) {
@@ -194,14 +203,14 @@ export const BlockchainApiController = {
194
203
  path: `/v1/convert/gas-price`,
195
204
  headers: getHeaders(),
196
205
  params: {
197
- projectId,
206
+ ...getParams(),
198
207
  chainId
199
208
  }
200
209
  });
201
210
  },
202
211
 
203
212
  async fetchSwapQuote(params: BlockchainApiSwapQuoteRequest) {
204
- const { projectId, amount, userAddress, from, to, gasPrice } = params;
213
+ const { amount, userAddress, from, to, gasPrice } = params;
205
214
  const [namespace, chain] = userAddress.split(':');
206
215
  const networkId: CaipNetworkId = `${namespace}:${chain}`;
207
216
  const isSupported = await BlockchainApiController.isNetworkSupported(networkId);
@@ -214,7 +223,7 @@ export const BlockchainApiController = {
214
223
  path: `/v1/convert/quotes`,
215
224
  headers: getHeaders(),
216
225
  params: {
217
- projectId,
226
+ ...getParams(),
218
227
  amount,
219
228
  userAddress,
220
229
  from,
@@ -225,7 +234,7 @@ export const BlockchainApiController = {
225
234
  },
226
235
 
227
236
  async fetchSwapTokens(params: BlockchainApiSwapTokensRequest) {
228
- const { projectId, chainId } = params;
237
+ const { chainId } = params;
229
238
  const isSupported = await BlockchainApiController.isNetworkSupported(chainId);
230
239
 
231
240
  if (!isSupported) {
@@ -236,7 +245,7 @@ export const BlockchainApiController = {
236
245
  path: `/v1/convert/tokens`,
237
246
  headers: getHeaders(),
238
247
  params: {
239
- projectId,
248
+ ...getParams(),
240
249
  chainId
241
250
  }
242
251
  });
@@ -255,6 +264,7 @@ export const BlockchainApiController = {
255
264
  return state.api.post<BlockchainApiGenerateSwapCalldataResponse>({
256
265
  path: '/v1/convert/build-transaction',
257
266
  headers: getHeaders(),
267
+ params: getParams(),
258
268
  body: {
259
269
  amount,
260
270
  eip155: {
@@ -269,7 +279,7 @@ export const BlockchainApiController = {
269
279
  },
270
280
 
271
281
  async generateApproveCalldata(params: BlockchainApiGenerateApproveCalldataRequest) {
272
- const { from, projectId, to, userAddress } = params;
282
+ const { from, to, userAddress } = params;
273
283
  const [namespace, chain] = userAddress.split(':');
274
284
  const networkId: CaipNetworkId = `${namespace}:${chain}`;
275
285
  const isSupported = await BlockchainApiController.isNetworkSupported(networkId);
@@ -282,7 +292,7 @@ export const BlockchainApiController = {
282
292
  path: `/v1/convert/build-approve`,
283
293
  headers: getHeaders(),
284
294
  params: {
285
- projectId,
295
+ ...getParams(),
286
296
  userAddress,
287
297
  from,
288
298
  to
@@ -309,8 +319,8 @@ export const BlockchainApiController = {
309
319
  path: `/v1/account/${plainAddress}/balance`,
310
320
  headers: getHeaders(),
311
321
  params: {
322
+ ...getParams(),
312
323
  currency: 'usd',
313
- projectId: OptionsController.state.projectId,
314
324
  chainId: `${namespace}:${chain}`,
315
325
  forceUpdate: forceUpdate?.join(',')
316
326
  }
@@ -322,7 +332,7 @@ export const BlockchainApiController = {
322
332
  path: `/v1/profile/account/${name}`,
323
333
  headers: getHeaders(),
324
334
  params: {
325
- projectId: OptionsController.state.projectId,
335
+ ...getParams(),
326
336
  apiVersion: '2'
327
337
  }
328
338
  });
@@ -332,9 +342,7 @@ export const BlockchainApiController = {
332
342
  return await state.api.get<OnRampServiceProvider[]>({
333
343
  path: '/v1/onramp/providers',
334
344
  headers: getHeaders(),
335
- params: {
336
- projectId: OptionsController.state.projectId
337
- }
345
+ params: getParams()
338
346
  });
339
347
  },
340
348
 
@@ -367,7 +375,7 @@ export const BlockchainApiController = {
367
375
  path: '/v1/onramp/providers/properties',
368
376
  headers: getHeaders(),
369
377
  params: {
370
- projectId: OptionsController.state.projectId,
378
+ ...getParams(),
371
379
  type,
372
380
  excludeProviders: EXCLUDED_ONRAMP_PROVIDERS.join(','),
373
381
  ...params
@@ -379,6 +387,7 @@ export const BlockchainApiController = {
379
387
  return await state.api.post<OnRampQuote[]>({
380
388
  path: '/v1/onramp/multi/quotes',
381
389
  headers: getHeaders(),
390
+ params: getParams(),
382
391
  body: {
383
392
  projectId: OptionsController.state.projectId,
384
393
  ...body
@@ -391,6 +400,7 @@ export const BlockchainApiController = {
391
400
  return await state.api.post<BlockchainApiOnRampWidgetResponse>({
392
401
  path: '/v1/onramp/widget',
393
402
  headers: getHeaders(),
403
+ params: getParams(),
394
404
  body: {
395
405
  projectId: OptionsController.state.projectId,
396
406
  sessionData: {
@@ -13,11 +13,13 @@ import {
13
13
  type AccountType,
14
14
  type Connection,
15
15
  SolanaBaseAdapter,
16
+ BitcoinBaseAdapter,
16
17
  type Identity
17
18
  } from '@reown/appkit-common-react-native';
18
19
  import { StorageUtil } from '../utils/StorageUtil';
19
20
  import { BlockchainApiController } from './BlockchainApiController';
20
21
  import { SnackController } from './SnackController';
22
+ import { LogController } from './LogController';
21
23
  import { CoreHelperUtil } from '../utils/CoreHelperUtil';
22
24
 
23
25
  // -- Types --------------------------------------------- //
@@ -279,8 +281,11 @@ export const ConnectionsController = {
279
281
  const existingBalances = connection.balances.get(address) || [];
280
282
  // Check if this token already exists by contract address or symbol
281
283
  const existingIndex = existingBalances.findIndex(existingBalance => {
282
- if (balance.address) {
283
- return existingBalance.address === balance.address;
284
+ if (balance.address && existingBalance.address) {
285
+ return (
286
+ CoreHelperUtil.getPlainAddress(existingBalance.address) ===
287
+ CoreHelperUtil.getPlainAddress(balance.address)
288
+ );
284
289
  }
285
290
 
286
291
  return existingBalance.symbol === balance.symbol;
@@ -386,6 +391,15 @@ export const ConnectionsController = {
386
391
  return getActiveAddress(newConnection);
387
392
  },
388
393
 
394
+ getActiveNetworkId(namespace?: ChainNamespace) {
395
+ const connection = namespace
396
+ ? baseState.connections.get(namespace)
397
+ : getActiveConnection(baseState);
398
+ if (!connection) return undefined;
399
+
400
+ return connection.caipNetwork;
401
+ },
402
+
389
403
  async disconnect(namespace: ChainNamespace, isInternal = true) {
390
404
  const connection = baseState.connections.get(namespace);
391
405
  if (!connection) return;
@@ -449,7 +463,13 @@ export const ConnectionsController = {
449
463
 
450
464
  const adapter = baseState.connections.get(baseState.activeNamespace)?.adapter;
451
465
 
452
- if (adapter instanceof EVMAdapter && plainAddress && chainId) {
466
+ if (
467
+ (adapter instanceof EVMAdapter ||
468
+ adapter instanceof SolanaBaseAdapter ||
469
+ adapter instanceof BitcoinBaseAdapter) &&
470
+ plainAddress &&
471
+ chainId
472
+ ) {
453
473
  return adapter.signMessage(plainAddress, message, chainId);
454
474
  }
455
475
 
@@ -521,6 +541,10 @@ export const ConnectionsController = {
521
541
  });
522
542
  });
523
543
  } catch (error) {
544
+ LogController.sendError(error, 'ConnectionsController.ts', 'fetchBalance', {
545
+ address,
546
+ namespace
547
+ });
524
548
  SnackController.showError('Failed to get account balance');
525
549
  }
526
550
  },
@@ -2,6 +2,7 @@ import { subscribeKey as subKey } from 'valtio/utils';
2
2
  import { proxy, subscribe as sub } from 'valtio';
3
3
  import { BlockchainApiController } from './BlockchainApiController';
4
4
  import type { BlockchainApiEnsError } from '@reown/appkit-common-react-native';
5
+ import { LogController } from './LogController';
5
6
 
6
7
  // -- Types --------------------------------------------- //
7
8
 
@@ -32,6 +33,7 @@ export const EnsController = {
32
33
  try {
33
34
  return await BlockchainApiController.lookupEnsName(name);
34
35
  } catch (e) {
36
+ LogController.sendError(e, 'EnsController.ts', 'resolveName');
35
37
  const error = e as BlockchainApiEnsError;
36
38
  throw new Error(error?.reasons?.[0]?.description || 'Error resolving name');
37
39
  }
@@ -3,17 +3,25 @@ import { ApiController } from './ApiController';
3
3
  import { OptionsController } from './OptionsController';
4
4
  import { CoreHelperUtil } from '../utils/CoreHelperUtil';
5
5
  import { FetchUtil } from '../utils/FetchUtil';
6
- import type { Event, EventName } from '@reown/appkit-common-react-native';
6
+ import type {
7
+ Event,
8
+ EventName,
9
+ WalletImpressionItem,
10
+ WcWallet
11
+ } from '@reown/appkit-common-react-native';
7
12
 
8
13
  // -- Helpers ------------------------------------------- //
9
14
  const baseUrl = CoreHelperUtil.getAnalyticsUrl();
10
15
  const api = new FetchUtil({ baseUrl });
11
16
  const excluded = ['MODAL_CREATED'];
17
+ const IMPRESSION_TIMEOUT = 3000;
12
18
 
13
19
  // -- Types --------------------------------------------- //
14
20
  export interface EventsControllerState {
15
21
  timestamp: number;
16
22
  data: Event;
23
+ pendingWalletImpressions: WalletImpressionItem[];
24
+ pendingImpressionTimeout?: NodeJS.Timeout;
17
25
  }
18
26
 
19
27
  // -- State --------------------------------------------- //
@@ -22,7 +30,9 @@ const state = proxy<EventsControllerState>({
22
30
  data: {
23
31
  type: 'track',
24
32
  event: 'MODAL_CREATED' // just for init purposes
25
- }
33
+ },
34
+ pendingWalletImpressions: [],
35
+ pendingImpressionTimeout: undefined
26
36
  });
27
37
 
28
38
  // -- Controller ---------------------------------------- //
@@ -41,6 +51,53 @@ export const EventsController = {
41
51
  });
42
52
  },
43
53
 
54
+ trackWalletImpression(props: {
55
+ wallet: WcWallet;
56
+ view: 'Connect' | 'AllWallets';
57
+ displayIndex: number;
58
+ query?: string;
59
+ installed?: boolean;
60
+ }) {
61
+ state.pendingWalletImpressions.push({
62
+ name: props.wallet.name ?? 'Unknown',
63
+ walletRank: props.wallet.order,
64
+ explorerId: props.wallet.id,
65
+ certified: props.wallet.badge_type === 'certified',
66
+ displayIndex: props.displayIndex,
67
+ view: props.view,
68
+ query: props.query,
69
+ installed: props.installed
70
+ });
71
+
72
+ if (state.pendingImpressionTimeout) {
73
+ clearTimeout(state.pendingImpressionTimeout);
74
+ }
75
+
76
+ state.pendingImpressionTimeout = setTimeout(() => {
77
+ EventsController.sendWalletImpressions();
78
+ }, IMPRESSION_TIMEOUT);
79
+ },
80
+
81
+ sendWalletImpressions() {
82
+ if (state.pendingImpressionTimeout) {
83
+ clearTimeout(state.pendingImpressionTimeout);
84
+ state.pendingImpressionTimeout = undefined;
85
+ }
86
+
87
+ const impressions = state.pendingWalletImpressions;
88
+
89
+ if (impressions.length === 0) {
90
+ return;
91
+ }
92
+
93
+ state.pendingWalletImpressions = [];
94
+ EventsController.sendEvent({
95
+ type: 'track',
96
+ event: 'WALLET_IMPRESSION',
97
+ items: impressions
98
+ });
99
+ },
100
+
44
101
  async _sendAnalyticsEvent(data: EventsControllerState['data'], timestamp: number) {
45
102
  if (excluded.includes(data.event)) {
46
103
  return;
@@ -50,6 +107,7 @@ export const EventsController = {
50
107
  await api.post({
51
108
  path: '/e',
52
109
  headers: ApiController._getApiHeaders(),
110
+ params: ApiController._getApiParams(),
53
111
  body: {
54
112
  eventId: CoreHelperUtil.getUUID(),
55
113
  bundleId: CoreHelperUtil.getBundleId(),
@@ -71,5 +129,18 @@ export const EventsController = {
71
129
  if (OptionsController.state.enableAnalytics) {
72
130
  EventsController._sendAnalyticsEvent(data, timestamp);
73
131
  }
132
+ },
133
+
134
+ resetState() {
135
+ if (state.pendingImpressionTimeout) {
136
+ clearTimeout(state.pendingImpressionTimeout);
137
+ state.pendingImpressionTimeout = undefined;
138
+ }
139
+ state.pendingWalletImpressions = [];
140
+ state.data = {
141
+ type: 'track',
142
+ event: 'MODAL_CREATED'
143
+ };
144
+ state.timestamp = Date.now();
74
145
  }
75
146
  };
@@ -0,0 +1,250 @@
1
+ import { proxy } from 'valtio';
2
+ import { OptionsController } from './OptionsController';
3
+ import { sanitizeString, sanitizeStackTrace, sanitizeValue, sanitizeData } from '../utils/LogUtils';
4
+ import { CoreHelperUtil } from '../utils/CoreHelperUtil';
5
+
6
+ // -- Types --------------------------------------------- //
7
+ export type LogLevel = 'info' | 'warn' | 'error' | 'debug';
8
+
9
+ export interface LogEntry {
10
+ id: string;
11
+ timestamp: number;
12
+ level: LogLevel;
13
+ message: string;
14
+ fileName?: string;
15
+ functionName?: string;
16
+ data?: Record<string, unknown>;
17
+ }
18
+
19
+ export interface LogControllerState {
20
+ logs: LogEntry[];
21
+ }
22
+
23
+ // -- Constants ----------------------------------------- //
24
+ const MAX_LOGS_COUNT = 300; // Prevent memory issues
25
+
26
+ // -- State --------------------------------------------- //
27
+ const state = proxy<LogControllerState>({
28
+ logs: []
29
+ });
30
+
31
+ const generateLogId = (): string => {
32
+ return CoreHelperUtil.getUUID();
33
+ };
34
+
35
+ const logToConsole = (entry: LogEntry) => {
36
+ const { debug } = OptionsController.state;
37
+
38
+ if (!debug) {
39
+ return;
40
+ }
41
+
42
+ const location =
43
+ entry.fileName && entry.functionName
44
+ ? `[${entry.fileName}:${entry.functionName}]`
45
+ : entry.fileName
46
+ ? `[${entry.fileName}]`
47
+ : '';
48
+
49
+ const logMessage = `[AppKit] ${location} ${entry.message}`;
50
+
51
+ switch (entry.level) {
52
+ case 'error':
53
+ // eslint-disable-next-line no-console
54
+ console.error(logMessage);
55
+ break;
56
+ case 'warn':
57
+ console.warn(logMessage);
58
+ break;
59
+ case 'debug':
60
+ // eslint-disable-next-line no-console
61
+ console.debug(logMessage);
62
+ break;
63
+ case 'info':
64
+ default:
65
+ // eslint-disable-next-line no-console
66
+ console.log(logMessage);
67
+ break;
68
+ }
69
+ };
70
+
71
+ // -- Controller ---------------------------------------- //
72
+ export const LogController = {
73
+ state,
74
+
75
+ /**
76
+ * Destroy the LogController (cleanup resources)
77
+ */
78
+ destroy() {
79
+ // Clear all logs
80
+ state.logs = [];
81
+ },
82
+
83
+ /**
84
+ * Send a general log entry
85
+ */
86
+ sendLog(
87
+ level: LogLevel,
88
+ message: string,
89
+ fileName?: string,
90
+ functionName?: string,
91
+ data?: Record<string, unknown>
92
+ ) {
93
+ if (!OptionsController.state.debug) {
94
+ return;
95
+ }
96
+ const entry: LogEntry = {
97
+ id: generateLogId(),
98
+ timestamp: Date.now(),
99
+ level,
100
+ message: sanitizeString(message),
101
+ fileName,
102
+ functionName,
103
+ data: sanitizeData(data)
104
+ };
105
+
106
+ state.logs.push(entry);
107
+
108
+ // Enforce maximum log count
109
+ if (state.logs.length > MAX_LOGS_COUNT) {
110
+ state.logs = state.logs.slice(-MAX_LOGS_COUNT);
111
+ }
112
+
113
+ logToConsole(entry);
114
+ },
115
+
116
+ /**
117
+ * Send an error log entry - convenience method for try/catch blocks
118
+ */
119
+ sendError(
120
+ error: Error | string | unknown,
121
+ fileName?: string,
122
+ functionName?: string,
123
+ additionalData?: Record<string, unknown>
124
+ ) {
125
+ let message: string;
126
+ let data: Record<string, unknown> = sanitizeData(additionalData) || {};
127
+
128
+ if (error instanceof Error) {
129
+ message = error.message || 'Error occurred';
130
+ // Sanitize stack trace to remove sensitive file paths
131
+ data['stack'] = error.stack ? sanitizeStackTrace(error.stack) : undefined;
132
+ data['name'] = error.name;
133
+
134
+ // Sanitize any additional properties on the error object
135
+ const errorProps: Record<string, unknown> = {};
136
+ Object.getOwnPropertyNames(error).forEach(prop => {
137
+ if (prop !== 'message' && prop !== 'stack' && prop !== 'name') {
138
+ errorProps[prop] = (error as any)[prop];
139
+ }
140
+ });
141
+
142
+ if (Object.keys(errorProps).length > 0) {
143
+ Object.assign(data, sanitizeValue(errorProps) as Record<string, unknown>);
144
+ }
145
+ } else if (typeof error === 'string') {
146
+ message = error;
147
+ } else if (error && typeof error === 'object' && 'message' in error) {
148
+ // Handle error-like objects (e.g., RPC errors, custom error objects)
149
+ message = String((error as any).message) || 'Error occurred';
150
+ // Include all properties of the error object
151
+ Object.assign(data, sanitizeValue(error) as Record<string, unknown>);
152
+ } else {
153
+ message = 'Unknown error occurred';
154
+ // Sanitize the original error object
155
+ data['originalError'] = sanitizeValue(error);
156
+ }
157
+
158
+ // Note: sanitization happens in sendLog method
159
+ this.sendLog('error', message, fileName, functionName, data);
160
+ },
161
+
162
+ /**
163
+ * Send an info log entry
164
+ */
165
+ sendInfo(
166
+ message: string,
167
+ fileName?: string,
168
+ functionName?: string,
169
+ data?: Record<string, unknown>
170
+ ) {
171
+ this.sendLog('info', message, fileName, functionName, data);
172
+ },
173
+
174
+ /**
175
+ * Send a warning log entry
176
+ */
177
+ sendWarn(
178
+ message: string,
179
+ fileName?: string,
180
+ functionName?: string,
181
+ data?: Record<string, unknown>
182
+ ) {
183
+ this.sendLog('warn', message, fileName, functionName, data);
184
+ },
185
+
186
+ /**
187
+ * Send a debug log entry
188
+ */
189
+ sendDebug(
190
+ message: string,
191
+ fileName?: string,
192
+ functionName?: string,
193
+ data?: Record<string, unknown>
194
+ ) {
195
+ this.sendLog('debug', message, fileName, functionName, data);
196
+ },
197
+
198
+ /**
199
+ * Get all logs
200
+ */
201
+ getLogs(): LogEntry[] {
202
+ return [...state.logs];
203
+ },
204
+
205
+ /**
206
+ * Get logs by level
207
+ */
208
+ getLogsByLevel(level: LogLevel): LogEntry[] {
209
+ return state.logs.filter(log => log.level === level);
210
+ },
211
+
212
+ /**
213
+ * Get recent logs (last N entries)
214
+ */
215
+ getRecentLogs(count: number = 100): LogEntry[] {
216
+ return state.logs.slice(-count);
217
+ },
218
+
219
+ /**
220
+ * Clear all logs
221
+ */
222
+ clearLogs() {
223
+ state.logs = [];
224
+ },
225
+
226
+ /**
227
+ * Export logs as JSON string for debugging
228
+ */
229
+ exportLogs(): string {
230
+ return JSON.stringify(state.logs, null, 2);
231
+ },
232
+
233
+ /**
234
+ * Get logs count by level
235
+ */
236
+ getLogsStats(): Record<LogLevel, number> {
237
+ const stats: Record<LogLevel, number> = {
238
+ info: 0,
239
+ warn: 0,
240
+ error: 0,
241
+ debug: 0
242
+ };
243
+
244
+ state.logs.forEach(log => {
245
+ stats[log.level]++;
246
+ });
247
+
248
+ return stats;
249
+ }
250
+ };