@dynamic-labs/react-native-extension 4.48.2 → 4.50.1

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/index.cjs CHANGED
@@ -15,7 +15,25 @@ var expoWebBrowser = require('expo-web-browser');
15
15
  var expoSecureStore = require('expo-secure-store');
16
16
  var reactNativePasskeyStamper = require('@turnkey/react-native-passkey-stamper');
17
17
 
18
- var version = "4.48.2";
18
+ function _interopNamespace(e) {
19
+ if (e && e.__esModule) return e;
20
+ var n = Object.create(null);
21
+ if (e) {
22
+ Object.keys(e).forEach(function (k) {
23
+ if (k !== 'default') {
24
+ var d = Object.getOwnPropertyDescriptor(e, k);
25
+ Object.defineProperty(n, k, d.get ? d : {
26
+ enumerable: true,
27
+ get: function () { return e[k]; }
28
+ });
29
+ }
30
+ });
31
+ }
32
+ n["default"] = e;
33
+ return Object.freeze(n);
34
+ }
35
+
36
+ var version = "4.50.1";
19
37
 
20
38
  function _extends() {
21
39
  return _extends = Object.assign ? Object.assign.bind() : function (n) {
@@ -391,23 +409,127 @@ const setupPasskeyHandler = core => {
391
409
  }));
392
410
  };
393
411
 
412
+ const log = (...args) => logger.logVerboseTroubleshootingMessage('[react-native-extension] setupPlatformHandler', ...args);
394
413
  const setupPlatformHandler = core => {
395
414
  const platformChannel = messageTransport.createRequestChannel(core.messageTransport);
415
+ const redirectUrl = expoLinking.createURL('');
416
+ log('Setting up platform handler', {
417
+ redirectUrl
418
+ });
396
419
  core.manifest.setPlatform('react-native');
397
- core.manifest.setRedirectUrl(expoLinking.createURL(''));
420
+ core.manifest.setRedirectUrl(redirectUrl);
398
421
  platformChannel.handle('openURL', url => __awaiter(void 0, void 0, void 0, function* () {
399
- yield expoLinking.openURL(url);
422
+ log('openURL called', {
423
+ url
424
+ });
425
+ try {
426
+ yield expoLinking.openURL(url);
427
+ } catch (error) {
428
+ // Re-throw the error so it propagates through the message transport
429
+ // This ensures that if opening the URL fails, the connection promise rejects
430
+ log('openURL failed', {
431
+ error,
432
+ url
433
+ });
434
+ throw error;
435
+ }
400
436
  }));
401
437
  platformChannel.handle('openAuthenticationWindow', _a => __awaiter(void 0, [_a], void 0, function* ({
402
438
  url,
403
439
  redirectUrl
404
440
  }) {
441
+ log('openAuthenticationWindow called', {
442
+ redirectUrl,
443
+ url
444
+ });
405
445
  const result = yield expoWebBrowser.openAuthSessionAsync(url, redirectUrl);
446
+ log('openAuthenticationWindow result', {
447
+ result
448
+ });
406
449
  // When not a success, result can only have a type which is a string describing
407
450
  // what happened in a single word.
408
451
  if (result.type !== 'success') throw new Error(result.type);
409
452
  return result.url;
410
453
  }));
454
+ platformChannel.handle('downloadFile', _b => __awaiter(void 0, [_b], void 0, function* ({
455
+ base64Content,
456
+ fileName,
457
+ mimeType
458
+ }) {
459
+ /**
460
+ * Because this is an iOS and Android only package, we need to import
461
+ * dynamically to avoid react-native-web build errors.
462
+ */
463
+ const {
464
+ saveDocuments
465
+ } = yield Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@react-native-documents/picker')); });
466
+ const {
467
+ CachesDirectoryPath,
468
+ exists,
469
+ unlink,
470
+ writeFile
471
+ } = yield Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('react-native-fs')); });
472
+ /**
473
+ * On native platforms you first need to create a file in the app directory
474
+ * so we can then request the file to be moved by the user to the OS file system.
475
+ */
476
+ const fileUri = `file://${CachesDirectoryPath}/${fileName}`;
477
+ /**
478
+ * Remove the file from the app directory.
479
+ */
480
+ const clearFile = () => __awaiter(void 0, void 0, void 0, function* () {
481
+ const fileExists = yield exists(fileUri);
482
+ if (fileExists) {
483
+ yield unlink(fileUri);
484
+ }
485
+ });
486
+ /**
487
+ * Remove the file from the app directory if it exists.
488
+ */
489
+ yield clearFile();
490
+ try {
491
+ yield writeFile(fileUri, base64Content, {
492
+ encoding: 'base64',
493
+ mimeType
494
+ });
495
+ yield saveDocuments({
496
+ copy: false,
497
+ fileName,
498
+ mimeType,
499
+ sourceUris: [fileUri]
500
+ });
501
+ } finally {
502
+ /**
503
+ * Remove the file after it has been saved
504
+ */
505
+ yield clearFile();
506
+ }
507
+ }));
508
+ // Handle incoming deep links (e.g., wallet redirect flows like Phantom)
509
+ const handleIncomingUrl = url => {
510
+ log('handleIncomingUrl called', {
511
+ hasUrl: Boolean(url),
512
+ url,
513
+ urlParams: url ? new URL(url).searchParams.toString() : null
514
+ });
515
+ if (url) {
516
+ platformChannel.emit('incomingUrl', url);
517
+ }
518
+ };
519
+ expoLinking.getInitialURL().then(url => {
520
+ log('getInitialURL resolved', {
521
+ url
522
+ });
523
+ handleIncomingUrl(url);
524
+ });
525
+ expoLinking.addEventListener('url', ({
526
+ url
527
+ }) => {
528
+ log('addEventListener url event', {
529
+ url
530
+ });
531
+ handleIncomingUrl(url);
532
+ });
411
533
  };
412
534
 
413
535
  const assertValidSource = source => {
package/index.js CHANGED
@@ -6,12 +6,12 @@ import { Logger } from '@dynamic-labs/logger';
6
6
  import { messageTransportDataJsonReviver, parseMessageTransportData, messageTransportDataJsonReplacer, createRequestChannel } from '@dynamic-labs/message-transport';
7
7
  import { jsx } from 'react/jsx-runtime';
8
8
  import { Passkey } from 'react-native-passkey';
9
- import { createURL, openURL } from 'expo-linking';
9
+ import { createURL, getInitialURL, addEventListener, openURL } from 'expo-linking';
10
10
  import { openAuthSessionAsync } from 'expo-web-browser';
11
11
  import { getItemAsync, deleteItemAsync, setItemAsync } from 'expo-secure-store';
12
12
  import { createPasskey, PasskeyStamper } from '@turnkey/react-native-passkey-stamper';
13
13
 
14
- var version = "4.48.2";
14
+ var version = "4.50.1";
15
15
 
16
16
  function _extends() {
17
17
  return _extends = Object.assign ? Object.assign.bind() : function (n) {
@@ -387,23 +387,127 @@ const setupPasskeyHandler = core => {
387
387
  }));
388
388
  };
389
389
 
390
+ const log = (...args) => logger.logVerboseTroubleshootingMessage('[react-native-extension] setupPlatformHandler', ...args);
390
391
  const setupPlatformHandler = core => {
391
392
  const platformChannel = createRequestChannel(core.messageTransport);
393
+ const redirectUrl = createURL('');
394
+ log('Setting up platform handler', {
395
+ redirectUrl
396
+ });
392
397
  core.manifest.setPlatform('react-native');
393
- core.manifest.setRedirectUrl(createURL(''));
398
+ core.manifest.setRedirectUrl(redirectUrl);
394
399
  platformChannel.handle('openURL', url => __awaiter(void 0, void 0, void 0, function* () {
395
- yield openURL(url);
400
+ log('openURL called', {
401
+ url
402
+ });
403
+ try {
404
+ yield openURL(url);
405
+ } catch (error) {
406
+ // Re-throw the error so it propagates through the message transport
407
+ // This ensures that if opening the URL fails, the connection promise rejects
408
+ log('openURL failed', {
409
+ error,
410
+ url
411
+ });
412
+ throw error;
413
+ }
396
414
  }));
397
415
  platformChannel.handle('openAuthenticationWindow', _a => __awaiter(void 0, [_a], void 0, function* ({
398
416
  url,
399
417
  redirectUrl
400
418
  }) {
419
+ log('openAuthenticationWindow called', {
420
+ redirectUrl,
421
+ url
422
+ });
401
423
  const result = yield openAuthSessionAsync(url, redirectUrl);
424
+ log('openAuthenticationWindow result', {
425
+ result
426
+ });
402
427
  // When not a success, result can only have a type which is a string describing
403
428
  // what happened in a single word.
404
429
  if (result.type !== 'success') throw new Error(result.type);
405
430
  return result.url;
406
431
  }));
432
+ platformChannel.handle('downloadFile', _b => __awaiter(void 0, [_b], void 0, function* ({
433
+ base64Content,
434
+ fileName,
435
+ mimeType
436
+ }) {
437
+ /**
438
+ * Because this is an iOS and Android only package, we need to import
439
+ * dynamically to avoid react-native-web build errors.
440
+ */
441
+ const {
442
+ saveDocuments
443
+ } = yield import('@react-native-documents/picker');
444
+ const {
445
+ CachesDirectoryPath,
446
+ exists,
447
+ unlink,
448
+ writeFile
449
+ } = yield import('react-native-fs');
450
+ /**
451
+ * On native platforms you first need to create a file in the app directory
452
+ * so we can then request the file to be moved by the user to the OS file system.
453
+ */
454
+ const fileUri = `file://${CachesDirectoryPath}/${fileName}`;
455
+ /**
456
+ * Remove the file from the app directory.
457
+ */
458
+ const clearFile = () => __awaiter(void 0, void 0, void 0, function* () {
459
+ const fileExists = yield exists(fileUri);
460
+ if (fileExists) {
461
+ yield unlink(fileUri);
462
+ }
463
+ });
464
+ /**
465
+ * Remove the file from the app directory if it exists.
466
+ */
467
+ yield clearFile();
468
+ try {
469
+ yield writeFile(fileUri, base64Content, {
470
+ encoding: 'base64',
471
+ mimeType
472
+ });
473
+ yield saveDocuments({
474
+ copy: false,
475
+ fileName,
476
+ mimeType,
477
+ sourceUris: [fileUri]
478
+ });
479
+ } finally {
480
+ /**
481
+ * Remove the file after it has been saved
482
+ */
483
+ yield clearFile();
484
+ }
485
+ }));
486
+ // Handle incoming deep links (e.g., wallet redirect flows like Phantom)
487
+ const handleIncomingUrl = url => {
488
+ log('handleIncomingUrl called', {
489
+ hasUrl: Boolean(url),
490
+ url,
491
+ urlParams: url ? new URL(url).searchParams.toString() : null
492
+ });
493
+ if (url) {
494
+ platformChannel.emit('incomingUrl', url);
495
+ }
496
+ };
497
+ getInitialURL().then(url => {
498
+ log('getInitialURL resolved', {
499
+ url
500
+ });
501
+ handleIncomingUrl(url);
502
+ });
503
+ addEventListener('url', ({
504
+ url
505
+ }) => {
506
+ log('addEventListener url event', {
507
+ url
508
+ });
509
+ handleIncomingUrl(url);
510
+ });
407
511
  };
408
512
 
409
513
  const assertValidSource = source => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/react-native-extension",
3
- "version": "4.48.2",
3
+ "version": "4.50.1",
4
4
  "main": "./index.cjs",
5
5
  "module": "./index.js",
6
6
  "types": "./src/index.d.ts",
@@ -16,11 +16,11 @@
16
16
  "dependencies": {
17
17
  "react-native-passkey": "3.1.0",
18
18
  "@turnkey/react-native-passkey-stamper": "1.1.3",
19
- "@dynamic-labs/assert-package-version": "4.48.2",
20
- "@dynamic-labs/client": "4.48.2",
21
- "@dynamic-labs/logger": "4.48.2",
22
- "@dynamic-labs/message-transport": "4.48.2",
23
- "@dynamic-labs/webview-messages": "4.48.2"
19
+ "@dynamic-labs/assert-package-version": "4.50.1",
20
+ "@dynamic-labs/client": "4.50.1",
21
+ "@dynamic-labs/logger": "4.50.1",
22
+ "@dynamic-labs/message-transport": "4.50.1",
23
+ "@dynamic-labs/webview-messages": "4.50.1"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "react": ">=18.0.0 <20.0.0",
@@ -28,6 +28,8 @@
28
28
  "react-native-webview": "^13.6.4",
29
29
  "expo-linking": ">=6.2.2",
30
30
  "expo-web-browser": ">=12.0.0",
31
- "expo-secure-store": ">=12.0.0"
31
+ "expo-secure-store": ">=12.0.0",
32
+ "@react-native-documents/picker": "^11.0.0",
33
+ "react-native-fs": ">=2.20.0"
32
34
  }
33
35
  }
@@ -11,7 +11,9 @@ export type ReactNativeExtensionProps = {
11
11
  */
12
12
  webviewDebuggingEnabled?: boolean;
13
13
  /**
14
- * The origin of the app.
14
+ * The web origin of the app (e.g., 'https://demo.dynamic.xyz').
15
+ * Used for SIWE messages, fetch Origin headers, and passkey operations.
16
+ * Note: Deep link redirects use the auto-configured redirectUrl from expo-linking.
15
17
  */
16
18
  appOrigin?: string;
17
19
  };