@virex-tech/paywallo-sdk 1.3.0 → 1.4.0

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.
package/dist/index.js CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,6 +30,25 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
33
+ // src/utils/uuid.ts
34
+ var uuid_exports = {};
35
+ __export(uuid_exports, {
36
+ generateUUID: () => generateUUID
37
+ });
38
+ function generateUUID() {
39
+ const template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
40
+ return template.replace(/[xy]/g, (c) => {
41
+ const r = Math.random() * 16 | 0;
42
+ const v = c === "x" ? r : r & 3 | 8;
43
+ return v.toString(16);
44
+ });
45
+ }
46
+ var init_uuid = __esm({
47
+ "src/utils/uuid.ts"() {
48
+ "use strict";
49
+ }
50
+ });
51
+
30
52
  // src/index.ts
31
53
  var index_exports = {};
32
54
  __export(index_exports, {
@@ -44,6 +66,7 @@ __export(index_exports, {
44
66
  IDENTITY_ERROR_CODES: () => IDENTITY_ERROR_CODES,
45
67
  IdentityError: () => IdentityError,
46
68
  IdentityManager: () => IdentityManager,
69
+ MetaBridge: () => MetaBridge,
47
70
  PAYWALL_ERROR_CODES: () => PAYWALL_ERROR_CODES,
48
71
  PURCHASE_ERROR_CODES: () => PURCHASE_ERROR_CODES,
49
72
  PaywallContext: () => PaywallContext,
@@ -71,6 +94,7 @@ __export(index_exports, {
71
94
  hasVariables: () => hasVariables,
72
95
  identityManager: () => identityManager,
73
96
  initLocalization: () => initLocalization,
97
+ metaBridge: () => metaBridge,
74
98
  nativeStoreKit: () => nativeStoreKit,
75
99
  networkMonitor: () => networkMonitor,
76
100
  offlineQueue: () => offlineQueue,
@@ -184,6 +208,9 @@ function createPurchaseError(code, message) {
184
208
  // src/domains/iap/NativeStoreKit.ts
185
209
  var import_react_native = require("react-native");
186
210
 
211
+ // src/domains/identity/IdentityManager.ts
212
+ var import_react_native_device_info = __toESM(require("react-native-device-info"));
213
+
187
214
  // src/domains/identity/IdentityError.ts
188
215
  var IdentityError = class extends PaywalloError {
189
216
  constructor(code, message) {
@@ -199,29 +226,12 @@ var IDENTITY_ERROR_CODES = {
199
226
  IDENTIFY_FAILED: "IDENTITY_IDENTIFY_FAILED"
200
227
  };
201
228
 
202
- // src/utils/uuid.ts
203
- function generateUUID() {
204
- const template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
205
- return template.replace(/[xy]/g, (c) => {
206
- const r = Math.random() * 16 | 0;
207
- const v = c === "x" ? r : r & 3 | 8;
208
- return v.toString(16);
209
- });
210
- }
229
+ // src/domains/identity/IdentityManager.ts
230
+ init_uuid();
211
231
 
212
232
  // src/core/storage/SecureStorage.ts
213
233
  var import_async_storage = __toESM(require("@react-native-async-storage/async-storage"));
214
- var _keychain = void 0;
215
- async function loadKeychain() {
216
- if (_keychain !== void 0) return _keychain;
217
- try {
218
- const mod = await import("react-native-keychain");
219
- _keychain = mod.default;
220
- } catch {
221
- _keychain = null;
222
- }
223
- return _keychain;
224
- }
234
+ var import_react_native_keychain = __toESM(require("react-native-keychain"));
225
235
  var KEYCHAIN_SERVICE_PREFIX = "com.paywallo.sdk.";
226
236
  var SecureStorage = class {
227
237
  // eslint-disable-next-line @typescript-eslint/no-useless-constructor
@@ -265,13 +275,11 @@ var SecureStorage = class {
265
275
  }
266
276
  }
267
277
  hasKeychainSupport() {
268
- return _keychain !== null && _keychain !== void 0;
278
+ return true;
269
279
  }
270
280
  async getFromKeychain(key) {
271
- const keychain = await loadKeychain();
272
- if (!keychain) return null;
273
281
  try {
274
- const result = await keychain.getGenericPassword({ service: `${KEYCHAIN_SERVICE_PREFIX}${key}` });
282
+ const result = await import_react_native_keychain.default.getGenericPassword({ service: `${KEYCHAIN_SERVICE_PREFIX}${key}` });
275
283
  if (result && result.password) {
276
284
  return result.password;
277
285
  }
@@ -281,20 +289,16 @@ var SecureStorage = class {
281
289
  }
282
290
  }
283
291
  async setToKeychain(key, value) {
284
- const keychain = await loadKeychain();
285
- if (!keychain) return false;
286
292
  try {
287
- await keychain.setGenericPassword("panel", value, { service: `${KEYCHAIN_SERVICE_PREFIX}${key}` });
293
+ await import_react_native_keychain.default.setGenericPassword("panel", value, { service: `${KEYCHAIN_SERVICE_PREFIX}${key}` });
288
294
  return true;
289
295
  } catch {
290
296
  return false;
291
297
  }
292
298
  }
293
299
  async removeFromKeychain(key) {
294
- const keychain = await loadKeychain();
295
- if (!keychain) return false;
296
300
  try {
297
- await keychain.resetGenericPassword({ service: `${KEYCHAIN_SERVICE_PREFIX}${key}` });
301
+ await import_react_native_keychain.default.resetGenericPassword({ service: `${KEYCHAIN_SERVICE_PREFIX}${key}` });
298
302
  return true;
299
303
  } catch {
300
304
  return false;
@@ -328,19 +332,8 @@ var IdentityManager = class {
328
332
  this.secureStorage = new SecureStorage(debug);
329
333
  await this.loadPersistedState();
330
334
  if (!this.deviceId) {
331
- let DeviceInfo = null;
332
335
  try {
333
- const mod = await import("react-native-device-info");
334
- DeviceInfo = mod.default;
335
- } catch {
336
- DeviceInfo = null;
337
- }
338
- try {
339
- if (DeviceInfo) {
340
- this.deviceId = await DeviceInfo.getUniqueId();
341
- } else {
342
- this.deviceId = generateUUID();
343
- }
336
+ this.deviceId = await import_react_native_device_info.default.getUniqueId();
344
337
  } catch {
345
338
  this.deviceId = generateUUID();
346
339
  }
@@ -569,20 +562,41 @@ var nativeStoreKit = {
569
562
  );
570
563
  }
571
564
  const distinctId = identityManager.getDistinctId();
572
- const result = await PaywalloStoreKitNative.purchase(productId, distinctId ?? null);
573
- if (!result || result.pending) {
574
- return null;
565
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
566
+ if (distinctId && !uuidRegex.test(distinctId) && PaywalloClient.getConfig()?.debug) {
567
+ console.warn("[Paywallo] distinctId is not a valid UUID for appAccountToken:", distinctId);
568
+ }
569
+ try {
570
+ const result = await PaywalloStoreKitNative.purchase(productId, distinctId ?? null);
571
+ if (!result || result.pending) {
572
+ return null;
573
+ }
574
+ return mapNativePurchase(result);
575
+ } catch (err) {
576
+ const message = err instanceof Error ? err.message : String(err);
577
+ if (message.toLowerCase().includes("cancel")) {
578
+ throw new PurchaseError(PURCHASE_ERROR_CODES.USER_CANCELLED, message, true);
579
+ }
580
+ throw new PurchaseError(PURCHASE_ERROR_CODES.PURCHASE_FAILED, message);
575
581
  }
576
- return mapNativePurchase(result);
577
582
  },
578
583
  async finishTransaction(transactionId) {
579
584
  if (!PaywalloStoreKitNative) return;
580
- await PaywalloStoreKitNative.finishTransaction(transactionId);
585
+ try {
586
+ await PaywalloStoreKitNative.finishTransaction(transactionId);
587
+ } catch (err) {
588
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] finishTransaction native error", err);
589
+ }
581
590
  },
582
591
  async getActiveTransactions() {
583
592
  if (!PaywalloStoreKitNative) return [];
584
- const results = await PaywalloStoreKitNative.getActiveTransactions();
585
- return results.map(mapNativePurchase);
593
+ try {
594
+ const results = await PaywalloStoreKitNative.getActiveTransactions();
595
+ return results.map(mapNativePurchase);
596
+ } catch (err) {
597
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] getActiveTransactions failed", err);
598
+ return [];
599
+ }
586
600
  }
587
601
  };
588
602
 
@@ -625,7 +639,8 @@ var IAPService = class {
625
639
  this.productsCache.set(product.productId, product);
626
640
  }
627
641
  return products;
628
- } catch (error) {
642
+ } catch (err) {
643
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] loadProducts failed", err);
629
644
  return [];
630
645
  }
631
646
  }
@@ -670,7 +685,8 @@ var IAPService = class {
670
685
  async finishTransaction(transactionId) {
671
686
  try {
672
687
  await nativeStoreKit.finishTransaction(transactionId);
673
- } catch (finishError) {
688
+ } catch (err) {
689
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] finishTransaction failed", err);
674
690
  }
675
691
  }
676
692
  async purchase(productId, options) {
@@ -685,23 +701,10 @@ var IAPService = class {
685
701
  if (!purchase) {
686
702
  return { success: false };
687
703
  }
688
- options?.onValidating?.();
689
- let validation = null;
690
- try {
691
- validation = await this.validateWithServer(purchase, productId, options);
692
- } catch (validationError) {
693
- return {
694
- success: false,
695
- error: new PurchaseError(PURCHASE_ERROR_CODES.VALIDATION_FAILED, validationError instanceof Error ? validationError.message : "Server validation failed")
696
- };
697
- }
698
- if (!validation?.success) {
699
- return {
700
- success: false,
701
- error: new PurchaseError(PURCHASE_ERROR_CODES.VALIDATION_FAILED, validation?.error ? `Server validation: ${validation.error}` : "Server validation failed")
702
- };
703
- }
704
704
  await this.finishTransaction(purchase.transactionId);
705
+ this.validateWithServer(purchase, productId, options).catch((err) => {
706
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] background validation failed", err);
707
+ });
705
708
  return { success: true, purchase };
706
709
  } catch (error) {
707
710
  const e = error instanceof PurchaseError ? error : new PurchaseError(PURCHASE_ERROR_CODES.PURCHASE_FAILED, error instanceof Error ? error.message : String(error));
@@ -739,13 +742,15 @@ var IAPService = class {
739
742
  if (r.status === "fulfilled" && r.value.success) {
740
743
  try {
741
744
  await nativeStoreKit.finishTransaction(tx.transactionId);
742
- } catch (finishError) {
745
+ } catch (err) {
746
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] finishTransaction failed", err);
743
747
  }
744
748
  validated.push(tx);
745
749
  }
746
750
  }
747
751
  return validated;
748
- } catch (error) {
752
+ } catch (err) {
753
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] restore failed", err);
749
754
  return [];
750
755
  }
751
756
  }
@@ -775,7 +780,8 @@ function usePaywallTracking() {
775
780
  ...opts.campaignId && { campaignId: opts.campaignId },
776
781
  ...sessionId && { sessionId }
777
782
  });
778
- } catch {
783
+ } catch (err) {
784
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] trackDismissed failed", err);
779
785
  }
780
786
  }, []);
781
787
  const trackProductSelected = (0, import_react.useCallback)((opts) => {
@@ -789,7 +795,8 @@ function usePaywallTracking() {
789
795
  ...opts.variantKey && { variantKey: opts.variantKey },
790
796
  ...opts.campaignId && { campaignId: opts.campaignId },
791
797
  ...sessionId && { sessionId }
792
- }).catch(() => {
798
+ }).catch((err) => {
799
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] trackProductSelected failed", err);
793
800
  });
794
801
  }, []);
795
802
  const trackPurchased = (0, import_react.useCallback)(async (opts) => {
@@ -805,7 +812,8 @@ function usePaywallTracking() {
805
812
  ...opts.campaignId && { campaignId: opts.campaignId },
806
813
  ...sessionId && { sessionId }
807
814
  });
808
- } catch {
815
+ } catch (err) {
816
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] trackPurchased failed", err);
809
817
  }
810
818
  }, []);
811
819
  return { trackDismissed, trackProductSelected, trackPurchased };
@@ -945,7 +953,8 @@ function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts
945
953
  const map = /* @__PURE__ */ new Map();
946
954
  for (const p of storeProducts) map.set(p.productId, p);
947
955
  setProducts(map);
948
- } catch {
956
+ } catch (err) {
957
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] loadProducts in paywall failed", err);
949
958
  setProducts(/* @__PURE__ */ new Map());
950
959
  }
951
960
  } else {
@@ -1473,7 +1482,12 @@ var PaywallErrorBoundary = class extends import_react6.Component {
1473
1482
  static getDerivedStateFromError() {
1474
1483
  return { hasError: true };
1475
1484
  }
1476
- componentDidCatch(_error) {
1485
+ componentDidCatch(error) {
1486
+ if (PaywalloClient.getConfig()?.debug) console.error("[Paywallo] Paywall render error:", error);
1487
+ try {
1488
+ PaywalloClient.getApiClient()?.reportError("PAYWALL_RENDER_ERROR", error.message);
1489
+ } catch {
1490
+ }
1477
1491
  }
1478
1492
  render() {
1479
1493
  return this.state.hasError ? null : this.props.children;
@@ -1753,7 +1767,8 @@ var AffiliateManager = class {
1753
1767
  );
1754
1768
  }
1755
1769
  }
1756
- log(..._args) {
1770
+ log(...args) {
1771
+ if (this.debug) console.log("[Paywallo:Affiliate]", ...args);
1757
1772
  }
1758
1773
  };
1759
1774
  var affiliateManager = new AffiliateManager();
@@ -2021,7 +2036,8 @@ var SubscriptionManagerClass = class {
2021
2036
  await this.cache.invalidate(this.cacheKey());
2022
2037
  await this.getSubscriptionStatus(true);
2023
2038
  }
2024
- log(..._args) {
2039
+ log(...args) {
2040
+ if (this.config?.debug) console.log("[Paywallo:Subscription]", ...args);
2025
2041
  }
2026
2042
  };
2027
2043
  var subscriptionManager = new SubscriptionManagerClass();
@@ -2074,12 +2090,18 @@ async function validatePurchase(client, appKey, platform, receipt, productId, tr
2074
2090
  },
2075
2091
  false
2076
2092
  );
2093
+ if (!response.ok) {
2094
+ throw new Error(`Server validation failed: HTTP ${response.status}`);
2095
+ }
2077
2096
  return response.data;
2078
2097
  }
2079
2098
  async function getSubscriptionStatus(client, baseUrl, appKey, distinctId) {
2080
2099
  const url = new URL(`${baseUrl}/purchases/status/${appKey}`);
2081
2100
  url.searchParams.set("distinctId", distinctId);
2082
2101
  const response = await client.get(url.toString());
2102
+ if (!response.ok) {
2103
+ throw new Error(`Subscription status check failed: HTTP ${response.status}`);
2104
+ }
2083
2105
  return response.data;
2084
2106
  }
2085
2107
  async function getEmergencyPaywall(client) {
@@ -2259,7 +2281,8 @@ var HttpClient = class {
2259
2281
  sleep(ms) {
2260
2282
  return new Promise((resolve) => setTimeout(resolve, ms));
2261
2283
  }
2262
- log(..._args) {
2284
+ log(...args) {
2285
+ if (this.config.debug) console.log("[Paywallo:Http]", ...args);
2263
2286
  }
2264
2287
  setDebug(debug) {
2265
2288
  this.config.debug = debug;
@@ -2285,8 +2308,6 @@ var NetworkMonitorClass = class {
2285
2308
  this.config = DEFAULT_NETWORK_CONFIG;
2286
2309
  this.listeners = /* @__PURE__ */ new Set();
2287
2310
  this.currentState = "unknown";
2288
- this.netInfoModule = null;
2289
- this.netInfoSubscription = null;
2290
2311
  this.appStateSubscription = null;
2291
2312
  this.initialized = false;
2292
2313
  this.checkIntervalId = null;
@@ -2302,13 +2323,6 @@ var NetworkMonitorClass = class {
2302
2323
  void this.setupFallbackDetection();
2303
2324
  this.setupAppStateListener();
2304
2325
  }
2305
- setupNetInfoListener() {
2306
- if (!this.netInfoModule) return;
2307
- this.netInfoSubscription = this.netInfoModule.addEventListener((state) => {
2308
- const newState = this.netInfoStateToNetworkState(state);
2309
- this.updateState(newState);
2310
- });
2311
- }
2312
2326
  async setupFallbackDetection() {
2313
2327
  await this.checkConnectivity();
2314
2328
  this.checkIntervalId = setInterval(() => {
@@ -2336,15 +2350,6 @@ var NetworkMonitorClass = class {
2336
2350
  this.updateState("offline");
2337
2351
  }
2338
2352
  }
2339
- netInfoStateToNetworkState(state) {
2340
- if (state.isConnected === null) {
2341
- return "unknown";
2342
- }
2343
- if (!state.isConnected) {
2344
- return "offline";
2345
- }
2346
- return "online";
2347
- }
2348
2353
  updateState(newState) {
2349
2354
  const previousState = this.currentState;
2350
2355
  if (previousState === newState) {
@@ -2387,10 +2392,6 @@ var NetworkMonitorClass = class {
2387
2392
  return this.currentState;
2388
2393
  }
2389
2394
  dispose() {
2390
- if (this.netInfoSubscription) {
2391
- this.netInfoSubscription();
2392
- this.netInfoSubscription = null;
2393
- }
2394
2395
  if (this.appStateSubscription) {
2395
2396
  this.appStateSubscription.remove();
2396
2397
  this.appStateSubscription = null;
@@ -2403,7 +2404,8 @@ var NetworkMonitorClass = class {
2403
2404
  this.initialized = false;
2404
2405
  this.currentState = "unknown";
2405
2406
  }
2406
- log(..._args) {
2407
+ log(...args) {
2408
+ if (this.config.debug) console.log("[Paywallo:Network]", ...args);
2407
2409
  }
2408
2410
  setDebug(debug) {
2409
2411
  this.config.debug = debug;
@@ -2413,6 +2415,7 @@ var networkMonitor = new NetworkMonitorClass();
2413
2415
 
2414
2416
  // src/core/queue/OfflineQueue.ts
2415
2417
  var import_async_storage2 = __toESM(require("@react-native-async-storage/async-storage"));
2418
+ init_uuid();
2416
2419
 
2417
2420
  // src/core/queue/deduplication.ts
2418
2421
  function normalizeForComparison(obj) {
@@ -2650,7 +2653,8 @@ var OfflineQueueClass = class {
2650
2653
  }
2651
2654
  }
2652
2655
  }
2653
- log(..._args) {
2656
+ log(...args) {
2657
+ if (this.config.debug) console.log("[Paywallo:Queue]", ...args);
2654
2658
  }
2655
2659
  setDebug(debug) {
2656
2660
  this.config.debug = debug;
@@ -2792,7 +2796,8 @@ var QueueProcessorClass = class {
2792
2796
  this.httpClient = null;
2793
2797
  this.initialized = false;
2794
2798
  }
2795
- log(..._args) {
2799
+ log(...args) {
2800
+ if (this.config.debug) console.log("[Paywallo:QueueProcessor]", ...args);
2796
2801
  }
2797
2802
  setDebug(debug) {
2798
2803
  this.config.debug = debug;
@@ -2874,13 +2879,12 @@ var ApiCache = class {
2874
2879
  };
2875
2880
 
2876
2881
  // src/core/ApiClient.ts
2877
- var SDK_VERSION = "1.0.0";
2878
- var DEFAULT_BASE_URL = "https://panel.lucasqueiroga.shop";
2882
+ var SDK_VERSION = "1.4.0";
2879
2883
  var _ApiClient = class _ApiClient {
2880
- constructor(appKey, debug = false, environment = "Production", offlineQueueEnabled = true, timeout = 3e4) {
2884
+ constructor(appKey, apiUrl, debug = false, environment = "Production", offlineQueueEnabled = true, timeout = 3e4) {
2881
2885
  this.cache = new ApiCache();
2882
2886
  this.appKey = appKey;
2883
- this.baseUrl = DEFAULT_BASE_URL;
2887
+ this.baseUrl = apiUrl;
2884
2888
  this.webUrl = deriveWebUrl(this.baseUrl);
2885
2889
  this.debug = debug;
2886
2890
  this.environment = environment;
@@ -2933,7 +2937,8 @@ var _ApiClient = class _ApiClient {
2933
2937
  sdkVersion: SDK_VERSION,
2934
2938
  platform: import_react_native9.Platform.OS
2935
2939
  }, true);
2936
- } catch {
2940
+ } catch (err) {
2941
+ if (this.debug) console.warn("[Paywallo:ApiClient] reportError failed", err);
2937
2942
  }
2938
2943
  }
2939
2944
  async trackEvent(eventName, distinctId, properties, timestamp) {
@@ -3165,7 +3170,8 @@ var _ApiClient = class _ApiClient {
3165
3170
  try {
3166
3171
  const value = JSON.stringify({ variant: flag.variant, payload: flag.payload, cachedAt: Date.now() });
3167
3172
  await secureStorage.set(`flag:${flagKey}:${distinctId}`, value);
3168
- } catch {
3173
+ } catch (err) {
3174
+ this.log("writeFlagToStorage failed", err);
3169
3175
  }
3170
3176
  }
3171
3177
  async postWithQueue(url, payload, label) {
@@ -3186,7 +3192,8 @@ var _ApiClient = class _ApiClient {
3186
3192
  throw error;
3187
3193
  }
3188
3194
  }
3189
- log(..._args) {
3195
+ log(...args) {
3196
+ if (this.debug) console.log("[Paywallo:ApiClient]", ...args);
3190
3197
  }
3191
3198
  };
3192
3199
  _ApiClient.FLAG_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
@@ -3354,43 +3361,67 @@ var AdvertisingIdManager = class {
3354
3361
  }
3355
3362
  };
3356
3363
 
3357
- // src/domains/identity/FacebookIdManager.ts
3364
+ // src/domains/identity/InstallTracker.ts
3365
+ var import_react_native14 = require("react-native");
3366
+ var import_async_storage3 = __toESM(require("@react-native-async-storage/async-storage"));
3367
+ var import_react_native_device_info2 = __toESM(require("react-native-device-info"));
3368
+
3369
+ // src/domains/identity/MetaBridge.ts
3370
+ var import_react_native11 = require("react-native");
3358
3371
  var TIMEOUT_MS = 2e3;
3359
- var FacebookIdManager = class {
3360
- async getAnonId() {
3372
+ var NativeBridge = import_react_native11.NativeModules.PaywalloFBBridge ?? null;
3373
+ var MetaBridge = class {
3374
+ async getAnonymousID() {
3375
+ if (!NativeBridge) return null;
3361
3376
  try {
3362
3377
  let timerId;
3363
- const timeoutPromise = new Promise((resolve) => {
3378
+ const timeout = new Promise((resolve) => {
3364
3379
  timerId = setTimeout(() => resolve(null), TIMEOUT_MS);
3365
3380
  });
3366
- const result = await Promise.race([this.fetchAnonId(), timeoutPromise]);
3381
+ const result = await Promise.race([NativeBridge.getAnonymousID(), timeout]);
3367
3382
  clearTimeout(timerId);
3368
3383
  return result;
3369
3384
  } catch {
3370
3385
  return null;
3371
3386
  }
3372
3387
  }
3373
- async fetchAnonId() {
3388
+ async logEvent(name, params = {}) {
3389
+ if (!NativeBridge) return;
3374
3390
  try {
3375
- const fbsdk = await import("react-native-fbsdk-next");
3376
- const anonId = await fbsdk.AppEventsLogger.getAnonymousID();
3377
- return anonId || null;
3391
+ await NativeBridge.logEvent(name, params);
3392
+ } catch {
3393
+ }
3394
+ }
3395
+ async logPurchase(amount, currency, params = {}) {
3396
+ if (!NativeBridge) return;
3397
+ try {
3398
+ await NativeBridge.logPurchase(amount, currency, params);
3399
+ } catch {
3400
+ }
3401
+ }
3402
+ setUserID(userId) {
3403
+ if (!NativeBridge) return;
3404
+ try {
3405
+ NativeBridge.setUserID(userId);
3406
+ } catch {
3407
+ }
3408
+ }
3409
+ flush() {
3410
+ if (!NativeBridge) return;
3411
+ try {
3412
+ NativeBridge.flush();
3378
3413
  } catch {
3379
- return null;
3380
3414
  }
3381
3415
  }
3382
3416
  };
3383
- var facebookIdManager = new FacebookIdManager();
3384
-
3385
- // src/domains/identity/InstallTracker.ts
3386
- var import_react_native13 = require("react-native");
3417
+ var metaBridge = new MetaBridge();
3387
3418
 
3388
3419
  // src/domains/identity/InstallReferrerManager.ts
3389
- var import_react_native11 = require("react-native");
3420
+ var import_react_native12 = require("react-native");
3390
3421
  var REFERRER_TIMEOUT_MS = 5e3;
3391
3422
  var InstallReferrerManager = class {
3392
3423
  async getReferrer() {
3393
- if (import_react_native11.Platform.OS !== "android") {
3424
+ if (import_react_native12.Platform.OS !== "android") {
3394
3425
  return this.emptyResult();
3395
3426
  }
3396
3427
  let timerId;
@@ -3450,7 +3481,8 @@ var InstallReferrerManager = class {
3450
3481
  var installReferrerManager = new InstallReferrerManager();
3451
3482
 
3452
3483
  // src/domains/session/SessionManager.ts
3453
- var import_react_native12 = require("react-native");
3484
+ var import_react_native13 = require("react-native");
3485
+ init_uuid();
3454
3486
 
3455
3487
  // src/domains/session/sessionTracking.ts
3456
3488
  async function trackSessionStart(apiClient, sessionId, sessionStartedAt) {
@@ -3618,7 +3650,7 @@ var SessionManager = class {
3618
3650
  if (this.appStateSubscription) {
3619
3651
  this.appStateSubscription.remove();
3620
3652
  }
3621
- this.appStateSubscription = import_react_native12.AppState.addEventListener("change", this.handleAppStateChange);
3653
+ this.appStateSubscription = import_react_native13.AppState.addEventListener("change", this.handleAppStateChange);
3622
3654
  }
3623
3655
  async handleForeground() {
3624
3656
  if (this.backgroundTimestamp) {
@@ -3679,7 +3711,8 @@ var SessionManager = class {
3679
3711
  );
3680
3712
  }
3681
3713
  }
3682
- log(..._args) {
3714
+ log(...args) {
3715
+ if (this.debug) console.log("[Paywallo:Session]", ...args);
3683
3716
  }
3684
3717
  };
3685
3718
  var sessionManager = new SessionManager();
@@ -3692,12 +3725,11 @@ var InstallTracker = class {
3692
3725
  }
3693
3726
  async trackIfNeeded(apiClient, requestATT = false) {
3694
3727
  const storage = new SecureStorage(this.debug);
3695
- const alreadyTracked = await storage.get("install_tracked");
3728
+ const alreadyTracked = await storage.get("@panel:install_tracked");
3696
3729
  if (alreadyTracked) return;
3697
3730
  let fallbackTracked = null;
3698
3731
  try {
3699
- const AsyncStorage3 = (await import("@react-native-async-storage/async-storage")).default;
3700
- fallbackTracked = await AsyncStorage3.getItem("@paywallo:install_tracked");
3732
+ fallbackTracked = await import_async_storage3.default.getItem("@paywallo:install_tracked");
3701
3733
  } catch {
3702
3734
  }
3703
3735
  if (fallbackTracked) return;
@@ -3705,16 +3737,10 @@ var InstallTracker = class {
3705
3737
  const sessionId = sessionManager.getSessionId();
3706
3738
  const installedAt = Date.now();
3707
3739
  if (!distinctId) return;
3708
- let deviceInfo = null;
3709
- try {
3710
- const mod = await import("react-native-device-info");
3711
- deviceInfo = mod.default;
3712
- } catch {
3713
- deviceInfo = null;
3714
- }
3740
+ const deviceInfo = import_react_native_device_info2.default;
3715
3741
  let deviceData = {};
3716
3742
  try {
3717
- const screen = import_react_native13.Dimensions.get("screen");
3743
+ const screen = import_react_native14.Dimensions.get("screen");
3718
3744
  const screenWidth = Math.round(screen.width ?? 0);
3719
3745
  const screenHeight = Math.round(screen.height ?? 0);
3720
3746
  const locale = Intl.DateTimeFormat().resolvedOptions().locale ?? "unknown";
@@ -3723,6 +3749,38 @@ var InstallTracker = class {
3723
3749
  const osVersion = deviceInfo?.getSystemVersion() || "unknown";
3724
3750
  const appVersion = deviceInfo?.getVersion() || "unknown";
3725
3751
  const buildNumber = deviceInfo?.getBuildNumber() || "0";
3752
+ let carrier = "unknown";
3753
+ try {
3754
+ carrier = await deviceInfo?.getCarrier?.() ?? "unknown";
3755
+ } catch {
3756
+ }
3757
+ let totalDisk = 0;
3758
+ try {
3759
+ totalDisk = Number(await deviceInfo?.getTotalDiskCapacity?.()) || 0;
3760
+ } catch {
3761
+ }
3762
+ let freeDisk = 0;
3763
+ try {
3764
+ freeDisk = Number(await deviceInfo?.getFreeDiskStorage?.()) || 0;
3765
+ } catch {
3766
+ }
3767
+ let totalRam = 0;
3768
+ try {
3769
+ totalRam = Number(await deviceInfo?.getTotalMemory?.()) || 0;
3770
+ } catch {
3771
+ }
3772
+ let brand = "unknown";
3773
+ try {
3774
+ brand = deviceInfo?.getBrand?.() ?? "unknown";
3775
+ } catch {
3776
+ }
3777
+ let installerPackage = null;
3778
+ try {
3779
+ if (import_react_native14.Platform.OS === "android") {
3780
+ installerPackage = await deviceInfo?.getInstallerPackageName?.() ?? null;
3781
+ }
3782
+ } catch {
3783
+ }
3726
3784
  deviceData = {
3727
3785
  deviceModel,
3728
3786
  osVersion,
@@ -3731,22 +3789,40 @@ var InstallTracker = class {
3731
3789
  ...screenWidth > 0 && { screenWidth },
3732
3790
  ...screenHeight > 0 && { screenHeight },
3733
3791
  timezone,
3734
- locale
3792
+ locale,
3793
+ ...carrier !== "unknown" && { carrier },
3794
+ ...totalDisk > 0 && { totalDisk },
3795
+ ...freeDisk > 0 && { freeDisk },
3796
+ ...totalRam > 0 && { totalRam },
3797
+ ...brand !== "unknown" && { brand },
3798
+ ...installerPackage && { installerPackage }
3735
3799
  };
3736
3800
  } catch {
3737
3801
  }
3738
3802
  const [fbAnonId, referrer, adIds] = await Promise.all([
3739
- facebookIdManager.getAnonId(),
3803
+ metaBridge.getAnonymousID(),
3740
3804
  installReferrerManager.getReferrer(),
3741
3805
  this.advertisingIdManager.collect(requestATT)
3742
3806
  ]);
3807
+ let effectiveAnonId = fbAnonId;
3808
+ if (!effectiveAnonId) {
3809
+ const stored = await storage.get("@panel:anon_id");
3810
+ if (stored) {
3811
+ effectiveAnonId = stored;
3812
+ } else {
3813
+ const { generateUUID: generateUUID2 } = await Promise.resolve().then(() => (init_uuid(), uuid_exports));
3814
+ effectiveAnonId = `PW_${generateUUID2()}`;
3815
+ await storage.set("@panel:anon_id", effectiveAnonId).catch(() => {
3816
+ });
3817
+ }
3818
+ }
3743
3819
  try {
3744
3820
  await apiClient.trackEvent("$app_installed", distinctId, {
3745
3821
  installedAt,
3746
- platform: import_react_native13.Platform.OS,
3822
+ platform: import_react_native14.Platform.OS,
3747
3823
  ...sessionId && { sessionId },
3748
3824
  ...deviceData,
3749
- ...fbAnonId && { fbAnonId },
3825
+ ...effectiveAnonId && { fbAnonId: effectiveAnonId },
3750
3826
  ...referrer.rawReferrer && { installReferrer: referrer.rawReferrer },
3751
3827
  ...referrer.trackingId && { referrerTrackingId: referrer.trackingId },
3752
3828
  ...referrer.fbclid && { referrerFbclid: referrer.fbclid },
@@ -3758,15 +3834,49 @@ var InstallTracker = class {
3758
3834
  ...adIds.gaid && { gaid: adIds.gaid },
3759
3835
  attStatus: adIds.attStatus
3760
3836
  });
3761
- const stored = await storage.set("install_tracked", String(installedAt));
3837
+ if (import_react_native14.Platform.OS === "ios") {
3838
+ void this.callDeferredMatch(apiClient, deviceData, adIds, effectiveAnonId).catch(() => {
3839
+ });
3840
+ }
3841
+ await storage.set("@panel:install_tracked", String(installedAt));
3762
3842
  try {
3763
- const AsyncStorage3 = (await import("@react-native-async-storage/async-storage")).default;
3764
- await AsyncStorage3.setItem("@paywallo:install_tracked", String(installedAt));
3843
+ await import_async_storage3.default.setItem("@paywallo:install_tracked", String(installedAt));
3765
3844
  } catch {
3766
3845
  }
3767
3846
  } catch {
3768
3847
  }
3769
3848
  }
3849
+ async callDeferredMatch(apiClient, deviceData, adIds, anonId) {
3850
+ const storage = new SecureStorage(this.debug);
3851
+ const alreadyMatched = await storage.get("@panel:deferred_match_done");
3852
+ if (alreadyMatched) return;
3853
+ const controller = new AbortController();
3854
+ const timer = setTimeout(() => controller.abort(), 5e3);
3855
+ try {
3856
+ const baseUrl = apiClient.getBaseUrl();
3857
+ const appKey = apiClient.appKey;
3858
+ await fetch(`${baseUrl}/api/v1/attribution/deferred-match`, {
3859
+ method: "POST",
3860
+ headers: { "Content-Type": "application/json", "X-App-Key": appKey },
3861
+ body: JSON.stringify({
3862
+ idfv: adIds.idfv,
3863
+ deviceModel: deviceData.deviceModel,
3864
+ osVersion: deviceData.osVersion,
3865
+ screenWidth: deviceData.screenWidth,
3866
+ screenHeight: deviceData.screenHeight,
3867
+ timezone: deviceData.timezone,
3868
+ locale: deviceData.locale,
3869
+ fbAnonId: anonId
3870
+ }),
3871
+ signal: controller.signal
3872
+ });
3873
+ await storage.set("@panel:deferred_match_done", "1").catch(() => {
3874
+ });
3875
+ } catch {
3876
+ } finally {
3877
+ clearTimeout(timer);
3878
+ }
3879
+ }
3770
3880
  };
3771
3881
 
3772
3882
  // src/core/PaywalloClient.ts
@@ -3858,9 +3968,12 @@ var _PaywalloClientClass = class _PaywalloClientClass {
3858
3968
  this.networkCleanup = networkMonitor.addListener((state) => {
3859
3969
  if (state !== "online") return;
3860
3970
  if (this.config && this.apiClient) return;
3971
+ if (this.initPromise) return;
3861
3972
  this.initPromise = this.initWithRetry(config);
3862
3973
  this.initPromise.catch(() => {
3863
3974
  this.reportInitFailure(config, null, "NETWORK_RECOVERY_FAILED");
3975
+ }).finally(() => {
3976
+ if (!this.isReady()) this.initPromise = null;
3864
3977
  });
3865
3978
  });
3866
3979
  }
@@ -3872,12 +3985,13 @@ var _PaywalloClientClass = class _PaywalloClientClass {
3872
3985
  }
3873
3986
  reportInitFailure(config, error, reason) {
3874
3987
  try {
3875
- const tempClient = new ApiClient(config.appKey, config.debug);
3988
+ const tempClient = new ApiClient(config.appKey, config.apiUrl ?? "https://paywallo.com.br", config.debug);
3876
3989
  void tempClient.reportError("INIT_FAILED", reason, {
3877
3990
  attempts: this.initAttempts,
3878
3991
  error: error instanceof Error ? error.message : String(error)
3879
3992
  });
3880
- } catch {
3993
+ } catch (err) {
3994
+ if (config.debug) console.warn("[Paywallo] reportInitFailure error", err);
3881
3995
  }
3882
3996
  }
3883
3997
  reportInitSuccess(config, attempts) {
@@ -3885,7 +3999,8 @@ var _PaywalloClientClass = class _PaywalloClientClass {
3885
3999
  if (this.apiClient) {
3886
4000
  void this.apiClient.reportError("INIT_RECOVERED", `Succeeded after ${attempts} retries`, { attempts });
3887
4001
  }
3888
- } catch {
4002
+ } catch (err) {
4003
+ if (config.debug) console.warn("[Paywallo] reportInitSuccess error", err);
3889
4004
  }
3890
4005
  }
3891
4006
  async resolveSessionFlags(keys, apiClient, distinctId) {
@@ -3910,7 +4025,7 @@ var _PaywalloClientClass = class _PaywalloClientClass {
3910
4025
  () => offlineQueue.clearItemsWithInvalidAppKey(config.appKey)
3911
4026
  )
3912
4027
  ]);
3913
- this.apiClient = new ApiClient(config.appKey, config.debug, environment, offlineQueueEnabled, config.timeout);
4028
+ this.apiClient = new ApiClient(config.appKey, config.apiUrl ?? "https://paywallo.com.br", config.debug, environment, offlineQueueEnabled, config.timeout);
3914
4029
  queueProcessor.initialize(this.apiClient.getHttpClient(), { debug: config.debug });
3915
4030
  affiliateManager.initialize(this.apiClient, config.debug);
3916
4031
  subscriptionManager.init({
@@ -4395,9 +4510,7 @@ function usePurchase() {
4395
4510
  setError(null);
4396
4511
  try {
4397
4512
  const iapService = getIAPService();
4398
- const result = await iapService.purchase(productId, {
4399
- onValidating: () => setState("validating")
4400
- });
4513
+ const result = await iapService.purchase(productId);
4401
4514
  if (result.success && result.purchase) {
4402
4515
  setState("idle");
4403
4516
  return {
@@ -4453,9 +4566,7 @@ function usePurchase() {
4453
4566
  purchase,
4454
4567
  restore,
4455
4568
  error,
4456
- isLoading: state === "loading",
4457
- isPurchasing: state === "purchasing" || state === "validating",
4458
- isValidating: state === "validating",
4569
+ isPurchasing: state === "purchasing",
4459
4570
  isRestoring: state === "restoring"
4460
4571
  };
4461
4572
  }
@@ -4496,6 +4607,9 @@ function useSubscription() {
4496
4607
  void subscriptionManager.getSubscriptionStatus().then((s) => {
4497
4608
  setStatus(s);
4498
4609
  setIsLoading(false);
4610
+ }).catch((err) => {
4611
+ setError(err instanceof Error ? err : new Error(String(err)));
4612
+ setIsLoading(false);
4499
4613
  });
4500
4614
  const removeListener = subscriptionManager.addListener((newStatus) => {
4501
4615
  setStatus(newStatus);
@@ -4517,7 +4631,7 @@ function useSubscription() {
4517
4631
 
4518
4632
  // src/PaywalloProvider.tsx
4519
4633
  var import_react18 = require("react");
4520
- var import_react_native14 = require("react-native");
4634
+ var import_react_native15 = require("react-native");
4521
4635
 
4522
4636
  // src/hooks/useCampaignPreload.ts
4523
4637
  var import_react14 = require("react");
@@ -4675,7 +4789,8 @@ function useProductLoader() {
4675
4789
  const map = /* @__PURE__ */ new Map();
4676
4790
  for (const p of loaded) map.set(p.productId, p);
4677
4791
  setProducts(map);
4678
- } catch (error) {
4792
+ } catch (err) {
4793
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] refreshProducts failed", err);
4679
4794
  } finally {
4680
4795
  setIsLoadingProducts(false);
4681
4796
  }
@@ -4715,6 +4830,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
4715
4830
  clearPreloadedWebView();
4716
4831
  resolvePreloadedPaywall({ presented: true, purchased: true, cancelled: false, restored: false });
4717
4832
  } catch (error) {
4833
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] preloaded purchase failed", error);
4718
4834
  setShowingPreloadedWebView(false);
4719
4835
  clearPreloadedWebView();
4720
4836
  resolvePreloadedPaywall({ presented: true, purchased: false, cancelled: false, restored: false });
@@ -4735,6 +4851,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
4735
4851
  clearPreloadedWebView();
4736
4852
  resolvePreloadedPaywall({ presented: true, purchased: false, cancelled: false, restored: true });
4737
4853
  } catch (error) {
4854
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] preloaded restore failed", error);
4738
4855
  setShowingPreloadedWebView(false);
4739
4856
  clearPreloadedWebView();
4740
4857
  resolvePreloadedPaywall({ presented: true, purchased: false, cancelled: false, restored: false });
@@ -4903,8 +5020,8 @@ function PaywalloProvider({ children, config }) {
4903
5020
  });
4904
5021
  }, []);
4905
5022
  const { showingPreloadedWebView, presentPreloadedWebView, resolvePreloadedPaywall, handlePreloadedWebViewReady: baseHandlePreloadedWebViewReady, handlePreloadedClose: baseHandlePreloadedClose, setShowingPreloadedWebView, presentedAtRef } = usePaywallPresenter(preloadedWebView, setPreloadedWebView);
4906
- const SCREEN_HEIGHT3 = (0, import_react18.useMemo)(() => import_react_native14.Dimensions.get("window").height, []);
4907
- const slideAnim = (0, import_react18.useRef)(new import_react_native14.Animated.Value(SCREEN_HEIGHT3)).current;
5023
+ const SCREEN_HEIGHT3 = (0, import_react18.useMemo)(() => import_react_native15.Dimensions.get("window").height, []);
5024
+ const slideAnim = (0, import_react18.useRef)(new import_react_native15.Animated.Value(SCREEN_HEIGHT3)).current;
4908
5025
  const handlePreloadedWebViewReady = (0, import_react18.useCallback)(() => {
4909
5026
  if (PaywalloClient.getConfig()?.debug) {
4910
5027
  console.info(`[Paywallo WEBVIEW] loaded \u2014 placement: ${preloadedWebView?.placement}`);
@@ -4913,7 +5030,7 @@ function PaywalloProvider({ children, config }) {
4913
5030
  }, [config?.debug, preloadedWebView?.placement, baseHandlePreloadedWebViewReady]);
4914
5031
  const handlePreloadedClose = (0, import_react18.useCallback)(() => {
4915
5032
  const placement = preloadedWebView?.placement;
4916
- import_react_native14.Animated.timing(slideAnim, { toValue: SCREEN_HEIGHT3, duration: 200, easing: import_react_native14.Easing.in(import_react_native14.Easing.cubic), useNativeDriver: true }).start(() => {
5033
+ import_react_native15.Animated.timing(slideAnim, { toValue: SCREEN_HEIGHT3, duration: 200, easing: import_react_native15.Easing.in(import_react_native15.Easing.cubic), useNativeDriver: true }).start(() => {
4917
5034
  baseHandlePreloadedClose();
4918
5035
  if (placement) triggerRepreload(placement);
4919
5036
  });
@@ -5129,7 +5246,7 @@ function PaywalloProvider({ children, config }) {
5129
5246
  (0, import_react18.useLayoutEffect)(() => {
5130
5247
  if (showingPreloadedWebView) {
5131
5248
  slideAnim.setValue(SCREEN_HEIGHT3);
5132
- import_react_native14.Animated.timing(slideAnim, { toValue: 0, duration: 200, easing: import_react_native14.Easing.out(import_react_native14.Easing.cubic), useNativeDriver: true }).start();
5249
+ import_react_native15.Animated.timing(slideAnim, { toValue: 0, duration: 200, easing: import_react_native15.Easing.out(import_react_native15.Easing.cubic), useNativeDriver: true }).start();
5133
5250
  }
5134
5251
  }, [showingPreloadedWebView, slideAnim, SCREEN_HEIGHT3]);
5135
5252
  const preloadStyle = [
@@ -5139,7 +5256,7 @@ function PaywalloProvider({ children, config }) {
5139
5256
  ];
5140
5257
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(PaywalloContext.Provider, { value: contextValue, children: [
5141
5258
  children,
5142
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PaywallErrorBoundary, { children: !!preloadedWebView?.craftData && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native14.Animated.View, { style: preloadStyle, pointerEvents: showingPreloadedWebView ? "auto" : "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5259
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PaywallErrorBoundary, { children: !!preloadedWebView?.craftData && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native15.Animated.View, { style: preloadStyle, pointerEvents: showingPreloadedWebView ? "auto" : "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5143
5260
  PaywallWebView,
5144
5261
  {
5145
5262
  paywallId: preloadedWebView.paywallId,
@@ -5169,7 +5286,7 @@ function PaywalloProvider({ children, config }) {
5169
5286
  ) })
5170
5287
  ] });
5171
5288
  }
5172
- var styles3 = import_react_native14.StyleSheet.create({
5289
+ var styles3 = import_react_native15.StyleSheet.create({
5173
5290
  preloadOverlay: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: "#ffffff" },
5174
5291
  hidden: { zIndex: -1, opacity: 0, width: 1, height: 1, overflow: "hidden" },
5175
5292
  visible: { zIndex: 9999, opacity: 1 }
@@ -5312,6 +5429,7 @@ var index_default = Paywallo;
5312
5429
  IDENTITY_ERROR_CODES,
5313
5430
  IdentityError,
5314
5431
  IdentityManager,
5432
+ MetaBridge,
5315
5433
  PAYWALL_ERROR_CODES,
5316
5434
  PURCHASE_ERROR_CODES,
5317
5435
  PaywallContext,
@@ -5338,6 +5456,7 @@ var index_default = Paywallo;
5338
5456
  hasVariables,
5339
5457
  identityManager,
5340
5458
  initLocalization,
5459
+ metaBridge,
5341
5460
  nativeStoreKit,
5342
5461
  networkMonitor,
5343
5462
  offlineQueue,