@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 +125 -3
- package/index.js +108 -4
- package/package.json +9 -7
- package/src/ReactNativeExtension/ReactNativeExtension.d.ts +3 -1
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
|
-
|
|
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(
|
|
420
|
+
core.manifest.setRedirectUrl(redirectUrl);
|
|
398
421
|
platformChannel.handle('openURL', url => __awaiter(void 0, void 0, void 0, function* () {
|
|
399
|
-
|
|
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.
|
|
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(
|
|
398
|
+
core.manifest.setRedirectUrl(redirectUrl);
|
|
394
399
|
platformChannel.handle('openURL', url => __awaiter(void 0, void 0, void 0, function* () {
|
|
395
|
-
|
|
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.
|
|
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.
|
|
20
|
-
"@dynamic-labs/client": "4.
|
|
21
|
-
"@dynamic-labs/logger": "4.
|
|
22
|
-
"@dynamic-labs/message-transport": "4.
|
|
23
|
-
"@dynamic-labs/webview-messages": "4.
|
|
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
|
};
|