@dynamic-labs/sdk-react-core 4.88.5 → 4.89.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/CHANGELOG.md +24 -1
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +12 -12
- package/src/lib/context/DynamicContext/types/DynamicContextProps.d.ts +1 -1
- package/src/lib/context/WalletGroupContext/WalletGroupContext.cjs +7 -0
- package/src/lib/context/WalletGroupContext/WalletGroupContext.js +7 -0
- package/src/lib/store/state/dynamicContextProps/defaultDynamicSettings.cjs +1 -1
- package/src/lib/store/state/dynamicContextProps/defaultDynamicSettings.d.ts +1 -1
- package/src/lib/store/state/dynamicContextProps/defaultDynamicSettings.js +1 -1
- package/src/lib/utils/hooks/useWalletItemActions/useHandleWalletItem/useHandleWalletItem.cjs +12 -28
- package/src/lib/utils/hooks/useWalletItemActions/useHandleWalletItem/useHandleWalletItem.js +13 -29
- package/src/lib/widgets/DynamicBridgeWidget/DynamicBridgeWidget.cjs +22 -10
- package/src/lib/widgets/DynamicBridgeWidget/DynamicBridgeWidget.js +23 -11
- package/src/lib/widgets/DynamicWidget/views/MoonPayOnramp/CryptoTokenSelectScreen/CryptoTokenSelectScreen.d.ts +14 -0
- package/src/lib/widgets/DynamicWidget/views/MoonPayOnramp/CryptoTokenSelectScreen/index.d.ts +1 -0
- package/src/lib/widgets/DynamicWidget/views/MoonPayOnramp/isTrustedImageUrl.d.ts +7 -0
- package/src/lib/widgets/DynamicWidget/views/MoonPayOnramp/useMoonPayOnramp.d.ts +30 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
|
|
2
|
+
## [4.89.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.88.6...v4.89.0) (2026-06-16)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **moonpay:** add useMoonPayOnramp hook ([#11405](https://github.com/dynamic-labs/dynamic-auth/issues/11405)) ([48cb62f](https://github.com/dynamic-labs/dynamic-auth/commit/48cb62fefecb511fcba9359ee6f6096dfef0b125))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* get wallet metadata from wallet-book when its present ([#11566](https://github.com/dynamic-labs/dynamic-auth/issues/11566)) ([a1a8ad5](https://github.com/dynamic-labs/dynamic-auth/commit/a1a8ad53c063157b189aea138fa338fcc67dc4dd))
|
|
13
|
+
* **waas:** instant logout — clear key share host-side, background iframe cleanup ([#11583](https://github.com/dynamic-labs/dynamic-auth/issues/11583)) ([0ab3378](https://github.com/dynamic-labs/dynamic-auth/commit/0ab3378efdbbe233069b17fad62b0c126397bc3a))
|
|
14
|
+
* **wagmi-connector:** await disconnect before connect to defuse SyncDynamicWagmi race DYNT-549 ([#11579](https://github.com/dynamic-labs/dynamic-auth/issues/11579)) ([6ac7c0e](https://github.com/dynamic-labs/dynamic-auth/commit/6ac7c0e02ed863342047bc5a1e60be3a66b8a425)), closes [#11131](https://github.com/dynamic-labs/dynamic-auth/issues/11131) [#11513](https://github.com/dynamic-labs/dynamic-auth/issues/11513) [#11516](https://github.com/dynamic-labs/dynamic-auth/issues/11516) [#11496](https://github.com/dynamic-labs/dynamic-auth/issues/11496) [#11513](https://github.com/dynamic-labs/dynamic-auth/issues/11513) [/github.com/dynamic-labs/dynamic-auth/blob/main/packages/wagmi-connector/src/lib/hooks/useConnectorId/useConnectorId.ts#L19-L26](https://github.com/dynamic-labs//github.com/dynamic-labs/dynamic-auth/blob/main/packages/wagmi-connector/src/lib/hooks/useConnectorId/useConnectorId.ts/issues/L19-L26) [#11131](https://github.com/dynamic-labs/dynamic-auth/issues/11131) [#11516](https://github.com/dynamic-labs/dynamic-auth/issues/11516) [#11513](https://github.com/dynamic-labs/dynamic-auth/issues/11513)
|
|
15
|
+
* **react-native:** resolve intermittent "Wallet with id <uuid> not found" after login ([#11575](https://github.com/dynamic-labs/dynamic-auth/issues/11575)) ([9d7a246](https://github.com/dynamic-labs/dynamic-auth/commit/9d7a246167927b9339dc33c10977c6d12783ab88))
|
|
16
|
+
|
|
17
|
+
### [4.88.6](https://github.com/dynamic-labs/dynamic-auth/compare/v4.88.5...v4.88.6) (2026-06-13)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* **DynamicBridgeWidget:** prevent bridge chain sync from reverting manual wallet switches ([#11560](https://github.com/dynamic-labs/dynamic-auth/issues/11560)) ([40c4973](https://github.com/dynamic-labs/dynamic-auth/commit/40c4973761b3e887577664f72f89d1d6ba285ea3))
|
|
23
|
+
* resolve EOA wallet client on the correct chain for EIP-7702 smart wallets ([#11564](https://github.com/dynamic-labs/dynamic-auth/issues/11564)) ([893b083](https://github.com/dynamic-labs/dynamic-auth/commit/893b0837a450ec683ccd09f2bb54204b77b6bd50))
|
|
24
|
+
|
|
2
25
|
### [4.88.5](https://github.com/dynamic-labs/dynamic-auth/compare/v4.88.4...v4.88.5) (2026-06-11)
|
|
3
26
|
|
|
4
27
|
|
|
@@ -6502,4 +6525,4 @@ Enjoy!
|
|
|
6502
6525
|
### Bug Fixes
|
|
6503
6526
|
|
|
6504
6527
|
* **view-context:** refactor view context to have initial view ([#2268](https://github.com/dynamic-labs/DynamicAuth/issues/2268)) ([0afe6ae](https://github.com/dynamic-labs/DynamicAuth/commit/0afe6ae469f62fd16fd8471322f9295957f607f6))
|
|
6505
|
-
* **wcv2:** upgrade universal p
|
|
6528
|
+
* **wcv2:** upgrade universal p
|
package/package.cjs
CHANGED
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/sdk-react-core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.89.0",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@dynamic-labs/sdk-api-core": "0.0.1015",
|
|
6
6
|
"@dynamic-labs-sdk/client": "1.8.2",
|
|
@@ -17,17 +17,17 @@
|
|
|
17
17
|
"yup": "0.32.11",
|
|
18
18
|
"react-international-phone": "4.5.0",
|
|
19
19
|
"bs58": "5.0.0",
|
|
20
|
-
"@dynamic-labs/assert-package-version": "4.
|
|
21
|
-
"@dynamic-labs/iconic": "4.
|
|
22
|
-
"@dynamic-labs/locale": "4.
|
|
23
|
-
"@dynamic-labs/logger": "4.
|
|
24
|
-
"@dynamic-labs/multi-wallet": "4.
|
|
25
|
-
"@dynamic-labs/rpc-providers": "4.
|
|
26
|
-
"@dynamic-labs/store": "4.
|
|
27
|
-
"@dynamic-labs/types": "4.
|
|
28
|
-
"@dynamic-labs/utils": "4.
|
|
29
|
-
"@dynamic-labs/wallet-book": "4.
|
|
30
|
-
"@dynamic-labs/wallet-connector-core": "4.
|
|
20
|
+
"@dynamic-labs/assert-package-version": "4.89.0",
|
|
21
|
+
"@dynamic-labs/iconic": "4.89.0",
|
|
22
|
+
"@dynamic-labs/locale": "4.89.0",
|
|
23
|
+
"@dynamic-labs/logger": "4.89.0",
|
|
24
|
+
"@dynamic-labs/multi-wallet": "4.89.0",
|
|
25
|
+
"@dynamic-labs/rpc-providers": "4.89.0",
|
|
26
|
+
"@dynamic-labs/store": "4.89.0",
|
|
27
|
+
"@dynamic-labs/types": "4.89.0",
|
|
28
|
+
"@dynamic-labs/utils": "4.89.0",
|
|
29
|
+
"@dynamic-labs/wallet-book": "4.89.0",
|
|
30
|
+
"@dynamic-labs/wallet-connector-core": "4.89.0",
|
|
31
31
|
"eventemitter3": "5.0.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
@@ -119,7 +119,7 @@ export interface DynamicContextProps {
|
|
|
119
119
|
/**
|
|
120
120
|
* If true, the Metamask SDK will be used to connect to the wallet.
|
|
121
121
|
* If false, the injected eip6963 provider will be used and WalletConnect for mobile.
|
|
122
|
-
* @default
|
|
122
|
+
* @default false
|
|
123
123
|
*/
|
|
124
124
|
useMetamaskSdk?: boolean;
|
|
125
125
|
};
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
var React = require('react');
|
|
8
|
+
var utils = require('@dynamic-labs/utils');
|
|
8
9
|
var createProviderHook = require('../../shared/utils/functions/createProviderHook/createProviderHook.cjs');
|
|
9
10
|
var getWalletGroupType = require('../../utils/functions/getWalletGroupType/getWalletGroupType.cjs');
|
|
10
11
|
var useWalletItemActions = require('../../utils/hooks/useWalletItemActions/useWalletItemActions.cjs');
|
|
@@ -22,6 +23,12 @@ const WalletGroupContextProvider = ({ children, }) => {
|
|
|
22
23
|
const { handleWalletItemClick } = useWalletItemActions.useWalletItemActions();
|
|
23
24
|
const navigateToWalletGroup = React__default["default"].useCallback((walletGroup, { onSelectWallet } = {}) => {
|
|
24
25
|
setSelectedWalletGroup(walletGroup);
|
|
26
|
+
// On mobile the walletconnect group (EVM + SOL root connectors) should
|
|
27
|
+
// go straight to the WC wallet picker, not a chain-selection step.
|
|
28
|
+
if (utils.isMobile() && walletGroup.key === 'walletconnect') {
|
|
29
|
+
pushView('wallet-connect-mobile-wallets-list');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
25
32
|
const walletGroupType = getWalletGroupType.getWalletGroupType(walletGroup);
|
|
26
33
|
const mapGroupTypeToView = {
|
|
27
34
|
'multi-chain': 'wallet-group',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React__default from 'react';
|
|
4
|
+
import { isMobile } from '@dynamic-labs/utils';
|
|
4
5
|
import { createProviderHook } from '../../shared/utils/functions/createProviderHook/createProviderHook.js';
|
|
5
6
|
import { getWalletGroupType } from '../../utils/functions/getWalletGroupType/getWalletGroupType.js';
|
|
6
7
|
import { useWalletItemActions } from '../../utils/hooks/useWalletItemActions/useWalletItemActions.js';
|
|
@@ -14,6 +15,12 @@ const WalletGroupContextProvider = ({ children, }) => {
|
|
|
14
15
|
const { handleWalletItemClick } = useWalletItemActions();
|
|
15
16
|
const navigateToWalletGroup = React__default.useCallback((walletGroup, { onSelectWallet } = {}) => {
|
|
16
17
|
setSelectedWalletGroup(walletGroup);
|
|
18
|
+
// On mobile the walletconnect group (EVM + SOL root connectors) should
|
|
19
|
+
// go straight to the WC wallet picker, not a chain-selection step.
|
|
20
|
+
if (isMobile() && walletGroup.key === 'walletconnect') {
|
|
21
|
+
pushView('wallet-connect-mobile-wallets-list');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
17
24
|
const walletGroupType = getWalletGroupType(walletGroup);
|
|
18
25
|
const mapGroupTypeToView = {
|
|
19
26
|
'multi-chain': 'wallet-group',
|
|
@@ -23,7 +23,7 @@ const defaultDynamicSettings = {
|
|
|
23
23
|
shadowDOMEnabled: true,
|
|
24
24
|
showLockedWalletView: false,
|
|
25
25
|
tokensFilter: (tokens) => tokens,
|
|
26
|
-
useMetamaskSdk:
|
|
26
|
+
useMetamaskSdk: false,
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
exports.PUBLIC_PROJECT_LIVE_ENVIRONMENT_ID = PUBLIC_PROJECT_LIVE_ENVIRONMENT_ID;
|
|
@@ -16,5 +16,5 @@ export declare const defaultDynamicSettings: {
|
|
|
16
16
|
shadowDOMEnabled: true;
|
|
17
17
|
showLockedWalletView: false;
|
|
18
18
|
tokensFilter: (tokens: import("@dynamic-labs/sdk-api-core").TokenBalance[]) => import("@dynamic-labs/sdk-api-core").TokenBalance[];
|
|
19
|
-
useMetamaskSdk:
|
|
19
|
+
useMetamaskSdk: false;
|
|
20
20
|
};
|
|
@@ -19,7 +19,7 @@ const defaultDynamicSettings = {
|
|
|
19
19
|
shadowDOMEnabled: true,
|
|
20
20
|
showLockedWalletView: false,
|
|
21
21
|
tokensFilter: (tokens) => tokens,
|
|
22
|
-
useMetamaskSdk:
|
|
22
|
+
useMetamaskSdk: false,
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
export { PUBLIC_PROJECT_LIVE_ENVIRONMENT_ID, defaultDynamicSettings };
|
package/src/lib/utils/hooks/useWalletItemActions/useHandleWalletItem/useHandleWalletItem.cjs
CHANGED
|
@@ -13,7 +13,6 @@ var MockContext = require('../../../../context/MockContext/MockContext.cjs');
|
|
|
13
13
|
var ViewContext = require('../../../../context/ViewContext/ViewContext.cjs');
|
|
14
14
|
var dynamicEvents = require('../../../../events/dynamicEvents.cjs');
|
|
15
15
|
var logger = require('../../../../shared/logger.cjs');
|
|
16
|
-
var authMode = require('../../../../store/state/authMode/authMode.cjs');
|
|
17
16
|
var localStorage = require('../../../constants/localStorage.cjs');
|
|
18
17
|
require('@dynamic-labs/sdk-api-core');
|
|
19
18
|
require('../../../constants/values.cjs');
|
|
@@ -41,8 +40,8 @@ var isSelectedWalletAlreadyConnected = require('../../../functions/isSelectedWal
|
|
|
41
40
|
const useHandleWalletItem = ({ allowAlreadyConnectedWallet, onQrCodeConnect, onConnectOnly, onCustodialWallet, onInstalledExtension, }) => {
|
|
42
41
|
const { setMultiWalletWidgetState, setShowAuthFlow, setSelectedWalletConnectorKey, walletConnectorOptions, setQrcodeUri, setDesktopUri, user, linkedWallets, setLegacyIsVerifying, } = useInternalDynamicContext.useInternalDynamicContext();
|
|
43
42
|
const { mockedSDK } = MockContext.useMockContext();
|
|
44
|
-
const { setError
|
|
45
|
-
const { pushView,
|
|
43
|
+
const { setError } = ErrorContext.useErrorContext();
|
|
44
|
+
const { pushView, replaceView } = ViewContext.useViewContext();
|
|
46
45
|
const handleCustodialWalletClick = (walletConnector) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
47
46
|
logger.logger.debug('handleCustodialWalletClick', walletConnector);
|
|
48
47
|
const twoStepAuthentication = requiresTwoStepAuthentication.requiresTwoStepAuthentication(walletConnector);
|
|
@@ -189,31 +188,16 @@ const useHandleWalletItem = ({ allowAlreadyConnectedWallet, onQrCodeConnect, onC
|
|
|
189
188
|
yield walletConnector.endSession();
|
|
190
189
|
}
|
|
191
190
|
setLegacyIsVerifying(false);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
setSelectedWalletConnectorKey({
|
|
203
|
-
chain: walletConnector.connectedChain,
|
|
204
|
-
key: walletConnector.key,
|
|
205
|
-
});
|
|
206
|
-
pushView('pending-connect');
|
|
207
|
-
yield walletConnector.chooseAccountsToConnect();
|
|
208
|
-
}
|
|
209
|
-
catch (error) {
|
|
210
|
-
if (error instanceof utils.UserRejectedRequestError) {
|
|
211
|
-
setErrorMessage('connection_rejected', undefined, 'wallet-account-select');
|
|
212
|
-
clearStackAndPushInitialView();
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
191
|
+
// Historical MM-only account-picker hook point. Until #11056 the dedicated
|
|
192
|
+
// MetaMaskConnector overrode chooseAccountsToConnect() as a no-op
|
|
193
|
+
// (`return []`), so this block never prompted. #11056 deleted that
|
|
194
|
+
// connector and both replacement paths (metamask-evm SDK connector and the
|
|
195
|
+
// generic injected fallback) inherit the base implementation, which calls
|
|
196
|
+
// wallet_requestPermissions and ALWAYS pops the MetaMask approval UI —
|
|
197
|
+
// blocking flows that re-connect an already-connected MM (external-wallet
|
|
198
|
+
// funding's duplicate-wallet detection, account-switch flows) on a popup
|
|
199
|
+
// that never resolves. Restore the long-standing no-op behavior by not
|
|
200
|
+
// calling it at all.
|
|
217
201
|
const supportsMultiAccount = walletConnectorCore.connectorRequiresDisconnectionForNewConnection(walletConnector);
|
|
218
202
|
const isNotInstalledWithQrCodeSupport = walletConnector.isWalletConnect ||
|
|
219
203
|
(!walletConnector.isInstalledOnBrowser() &&
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { __awaiter } from '../../../../../../_virtual/_tslib.js';
|
|
3
|
-
import { StorageService, isMobile
|
|
3
|
+
import { StorageService, isMobile } from '@dynamic-labs/utils';
|
|
4
4
|
import { isPhantomRedirectConnector, connectorRequiresDisconnectionForNewConnection } from '@dynamic-labs/wallet-connector-core';
|
|
5
5
|
import '../../../../context/DynamicContext/useDynamicContext/useDynamicContext.js';
|
|
6
6
|
import { useInternalDynamicContext } from '../../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext/useInternalDynamicContext.js';
|
|
@@ -9,7 +9,6 @@ import { useMockContext } from '../../../../context/MockContext/MockContext.js';
|
|
|
9
9
|
import { useViewContext } from '../../../../context/ViewContext/ViewContext.js';
|
|
10
10
|
import { dynamicEvents } from '../../../../events/dynamicEvents.js';
|
|
11
11
|
import { logger } from '../../../../shared/logger.js';
|
|
12
|
-
import { getAuthMode } from '../../../../store/state/authMode/authMode.js';
|
|
13
12
|
import { PHANTOM_SIGNATURE_STATE } from '../../../constants/localStorage.js';
|
|
14
13
|
import '@dynamic-labs/sdk-api-core';
|
|
15
14
|
import '../../../constants/values.js';
|
|
@@ -37,8 +36,8 @@ import { isSelectedWalletAlreadyConnected } from '../../../functions/isSelectedW
|
|
|
37
36
|
const useHandleWalletItem = ({ allowAlreadyConnectedWallet, onQrCodeConnect, onConnectOnly, onCustodialWallet, onInstalledExtension, }) => {
|
|
38
37
|
const { setMultiWalletWidgetState, setShowAuthFlow, setSelectedWalletConnectorKey, walletConnectorOptions, setQrcodeUri, setDesktopUri, user, linkedWallets, setLegacyIsVerifying, } = useInternalDynamicContext();
|
|
39
38
|
const { mockedSDK } = useMockContext();
|
|
40
|
-
const { setError
|
|
41
|
-
const { pushView,
|
|
39
|
+
const { setError } = useErrorContext();
|
|
40
|
+
const { pushView, replaceView } = useViewContext();
|
|
42
41
|
const handleCustodialWalletClick = (walletConnector) => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
42
|
logger.debug('handleCustodialWalletClick', walletConnector);
|
|
44
43
|
const twoStepAuthentication = requiresTwoStepAuthentication(walletConnector);
|
|
@@ -185,31 +184,16 @@ const useHandleWalletItem = ({ allowAlreadyConnectedWallet, onQrCodeConnect, onC
|
|
|
185
184
|
yield walletConnector.endSession();
|
|
186
185
|
}
|
|
187
186
|
setLegacyIsVerifying(false);
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
//
|
|
191
|
-
//
|
|
192
|
-
//
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
setSelectedWalletConnectorKey({
|
|
199
|
-
chain: walletConnector.connectedChain,
|
|
200
|
-
key: walletConnector.key,
|
|
201
|
-
});
|
|
202
|
-
pushView('pending-connect');
|
|
203
|
-
yield walletConnector.chooseAccountsToConnect();
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
if (error instanceof UserRejectedRequestError) {
|
|
207
|
-
setErrorMessage('connection_rejected', undefined, 'wallet-account-select');
|
|
208
|
-
clearStackAndPushInitialView();
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
187
|
+
// Historical MM-only account-picker hook point. Until #11056 the dedicated
|
|
188
|
+
// MetaMaskConnector overrode chooseAccountsToConnect() as a no-op
|
|
189
|
+
// (`return []`), so this block never prompted. #11056 deleted that
|
|
190
|
+
// connector and both replacement paths (metamask-evm SDK connector and the
|
|
191
|
+
// generic injected fallback) inherit the base implementation, which calls
|
|
192
|
+
// wallet_requestPermissions and ALWAYS pops the MetaMask approval UI —
|
|
193
|
+
// blocking flows that re-connect an already-connected MM (external-wallet
|
|
194
|
+
// funding's duplicate-wallet detection, account-switch flows) on a popup
|
|
195
|
+
// that never resolves. Restore the long-standing no-op behavior by not
|
|
196
|
+
// calling it at all.
|
|
213
197
|
const supportsMultiAccount = connectorRequiresDisconnectionForNewConnection(walletConnector);
|
|
214
198
|
const isNotInstalledWithQrCodeSupport = walletConnector.isWalletConnect ||
|
|
215
199
|
(!walletConnector.isInstalledOnBrowser() &&
|
|
@@ -123,6 +123,16 @@ const DynamicBridgeWidget = ({ className, variant = 'modal', iconVariant = 'chai
|
|
|
123
123
|
const { showAuthFlow, setShowBridgeWidget, bridgeChains, setShowAuthFlow, connectedWallets, sdkHasLoaded, primaryWallet, setPrimaryWallet, } = useInternalDynamicContext.useInternalDynamicContext();
|
|
124
124
|
const { widgetRef, inlineControlsRef } = DynamicBridgeWidgetContext.useDynamicBridgeWidgetContext();
|
|
125
125
|
const { t } = reactI18next.useTranslation();
|
|
126
|
+
// Use refs so the bridgeChains effect only fires when bridgeChains changes,
|
|
127
|
+
// not when the user manually switches the primary wallet.
|
|
128
|
+
// setPrimaryWallet is a useCallback that recreates on every primaryWalletId
|
|
129
|
+
// change, so it must also be a ref to avoid retriggering the effect.
|
|
130
|
+
const primaryWalletRef = React.useRef(primaryWallet);
|
|
131
|
+
primaryWalletRef.current = primaryWallet;
|
|
132
|
+
const connectedWalletsRef = React.useRef(connectedWallets);
|
|
133
|
+
connectedWalletsRef.current = connectedWallets;
|
|
134
|
+
const setPrimaryWalletRef = React.useRef(setPrimaryWallet);
|
|
135
|
+
setPrimaryWalletRef.current = setPrimaryWallet;
|
|
126
136
|
const closeOnOutsideClick = React.useCallback((e) => {
|
|
127
137
|
var _a;
|
|
128
138
|
const target = e.composedPath().shift();
|
|
@@ -134,20 +144,22 @@ const DynamicBridgeWidget = ({ className, variant = 'modal', iconVariant = 'chai
|
|
|
134
144
|
}, [inlineControlsRef, variant, showAuthFlow, setShowBridgeWidget]);
|
|
135
145
|
index.useOnClickOutside(widgetRef, closeOnOutsideClick);
|
|
136
146
|
React.useEffect(() => {
|
|
147
|
+
const currentPrimaryWallet = primaryWalletRef.current;
|
|
148
|
+
const currentConnectedWallets = connectedWalletsRef.current;
|
|
137
149
|
// no need to update primary wallet if it's already set to the correct chain
|
|
138
|
-
if (!
|
|
150
|
+
if (!currentPrimaryWallet ||
|
|
139
151
|
!bridgeChains ||
|
|
140
|
-
|
|
141
|
-
|
|
152
|
+
currentConnectedWallets.length <= 1 ||
|
|
153
|
+
currentPrimaryWallet.chain === bridgeChains[0].chain) {
|
|
142
154
|
return;
|
|
143
155
|
}
|
|
144
156
|
// find a connected wallet that matches the primary bridge chain
|
|
145
|
-
const newPrimaryWallet =
|
|
157
|
+
const newPrimaryWallet = currentConnectedWallets.find((wallet) => wallet.chain === bridgeChains[0].chain);
|
|
146
158
|
// if a new primary wallet is found, update the primary wallet
|
|
147
159
|
if (newPrimaryWallet) {
|
|
148
160
|
logger.logger.debug('[DynamicBridgeWidget] bridgeChains changed - updating primary wallet', {
|
|
149
161
|
bridgeChains,
|
|
150
|
-
connectedWallets:
|
|
162
|
+
connectedWallets: currentConnectedWallets.map((wallet) => ({
|
|
151
163
|
address: wallet.address,
|
|
152
164
|
chain: wallet.chain,
|
|
153
165
|
id: wallet.id,
|
|
@@ -158,14 +170,14 @@ const DynamicBridgeWidget = ({ className, variant = 'modal', iconVariant = 'chai
|
|
|
158
170
|
id: newPrimaryWallet.id,
|
|
159
171
|
},
|
|
160
172
|
oldPrimaryWallet: {
|
|
161
|
-
address:
|
|
162
|
-
chain:
|
|
163
|
-
id:
|
|
173
|
+
address: currentPrimaryWallet.address,
|
|
174
|
+
chain: currentPrimaryWallet.chain,
|
|
175
|
+
id: currentPrimaryWallet.id,
|
|
164
176
|
},
|
|
165
177
|
});
|
|
166
|
-
|
|
178
|
+
setPrimaryWalletRef.current(newPrimaryWallet.id);
|
|
167
179
|
}
|
|
168
|
-
}, [bridgeChains
|
|
180
|
+
}, [bridgeChains]);
|
|
169
181
|
return (jsxRuntime.jsxs(ShadowDOM.ShadowDOM, { id: 'dynamic-bridge-widget', className: 'dynamic-widget__container', children: [jsxRuntime.jsx(InlineWidget.InlineWidget, { ref: inlineControlsRef, className: className, dataTestId: 'BridgeWidgetNav', children: bridgeChains === null || bridgeChains === void 0 ? void 0 : bridgeChains.map(({ chain }) => {
|
|
170
182
|
const ChainIcon = getChainIcon.getChainIcon(chain);
|
|
171
183
|
if (!sdkHasLoaded) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { useCallback, useEffect } from 'react';
|
|
3
|
+
import { useRef, useCallback, useEffect } from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { WalletIcon } from '@dynamic-labs/wallet-book';
|
|
6
6
|
import '../../components/Accordion/components/AccordionItem/AccordionItem.js';
|
|
@@ -119,6 +119,16 @@ const DynamicBridgeWidget = ({ className, variant = 'modal', iconVariant = 'chai
|
|
|
119
119
|
const { showAuthFlow, setShowBridgeWidget, bridgeChains, setShowAuthFlow, connectedWallets, sdkHasLoaded, primaryWallet, setPrimaryWallet, } = useInternalDynamicContext();
|
|
120
120
|
const { widgetRef, inlineControlsRef } = useDynamicBridgeWidgetContext();
|
|
121
121
|
const { t } = useTranslation();
|
|
122
|
+
// Use refs so the bridgeChains effect only fires when bridgeChains changes,
|
|
123
|
+
// not when the user manually switches the primary wallet.
|
|
124
|
+
// setPrimaryWallet is a useCallback that recreates on every primaryWalletId
|
|
125
|
+
// change, so it must also be a ref to avoid retriggering the effect.
|
|
126
|
+
const primaryWalletRef = useRef(primaryWallet);
|
|
127
|
+
primaryWalletRef.current = primaryWallet;
|
|
128
|
+
const connectedWalletsRef = useRef(connectedWallets);
|
|
129
|
+
connectedWalletsRef.current = connectedWallets;
|
|
130
|
+
const setPrimaryWalletRef = useRef(setPrimaryWallet);
|
|
131
|
+
setPrimaryWalletRef.current = setPrimaryWallet;
|
|
122
132
|
const closeOnOutsideClick = useCallback((e) => {
|
|
123
133
|
var _a;
|
|
124
134
|
const target = e.composedPath().shift();
|
|
@@ -130,20 +140,22 @@ const DynamicBridgeWidget = ({ className, variant = 'modal', iconVariant = 'chai
|
|
|
130
140
|
}, [inlineControlsRef, variant, showAuthFlow, setShowBridgeWidget]);
|
|
131
141
|
useOnClickOutside(widgetRef, closeOnOutsideClick);
|
|
132
142
|
useEffect(() => {
|
|
143
|
+
const currentPrimaryWallet = primaryWalletRef.current;
|
|
144
|
+
const currentConnectedWallets = connectedWalletsRef.current;
|
|
133
145
|
// no need to update primary wallet if it's already set to the correct chain
|
|
134
|
-
if (!
|
|
146
|
+
if (!currentPrimaryWallet ||
|
|
135
147
|
!bridgeChains ||
|
|
136
|
-
|
|
137
|
-
|
|
148
|
+
currentConnectedWallets.length <= 1 ||
|
|
149
|
+
currentPrimaryWallet.chain === bridgeChains[0].chain) {
|
|
138
150
|
return;
|
|
139
151
|
}
|
|
140
152
|
// find a connected wallet that matches the primary bridge chain
|
|
141
|
-
const newPrimaryWallet =
|
|
153
|
+
const newPrimaryWallet = currentConnectedWallets.find((wallet) => wallet.chain === bridgeChains[0].chain);
|
|
142
154
|
// if a new primary wallet is found, update the primary wallet
|
|
143
155
|
if (newPrimaryWallet) {
|
|
144
156
|
logger.debug('[DynamicBridgeWidget] bridgeChains changed - updating primary wallet', {
|
|
145
157
|
bridgeChains,
|
|
146
|
-
connectedWallets:
|
|
158
|
+
connectedWallets: currentConnectedWallets.map((wallet) => ({
|
|
147
159
|
address: wallet.address,
|
|
148
160
|
chain: wallet.chain,
|
|
149
161
|
id: wallet.id,
|
|
@@ -154,14 +166,14 @@ const DynamicBridgeWidget = ({ className, variant = 'modal', iconVariant = 'chai
|
|
|
154
166
|
id: newPrimaryWallet.id,
|
|
155
167
|
},
|
|
156
168
|
oldPrimaryWallet: {
|
|
157
|
-
address:
|
|
158
|
-
chain:
|
|
159
|
-
id:
|
|
169
|
+
address: currentPrimaryWallet.address,
|
|
170
|
+
chain: currentPrimaryWallet.chain,
|
|
171
|
+
id: currentPrimaryWallet.id,
|
|
160
172
|
},
|
|
161
173
|
});
|
|
162
|
-
|
|
174
|
+
setPrimaryWalletRef.current(newPrimaryWallet.id);
|
|
163
175
|
}
|
|
164
|
-
}, [bridgeChains
|
|
176
|
+
}, [bridgeChains]);
|
|
165
177
|
return (jsxs(ShadowDOM, { id: 'dynamic-bridge-widget', className: 'dynamic-widget__container', children: [jsx(InlineWidget, { ref: inlineControlsRef, className: className, dataTestId: 'BridgeWidgetNav', children: bridgeChains === null || bridgeChains === void 0 ? void 0 : bridgeChains.map(({ chain }) => {
|
|
166
178
|
const ChainIcon = getChainIcon(chain);
|
|
167
179
|
if (!sdkHasLoaded) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
export type CryptoToken = {
|
|
3
|
+
code: string;
|
|
4
|
+
icon?: string;
|
|
5
|
+
name: string;
|
|
6
|
+
};
|
|
7
|
+
type CryptoTokenSelectScreenProps = {
|
|
8
|
+
onClose: () => void;
|
|
9
|
+
onSelectToken: (tokenCode: string) => void;
|
|
10
|
+
tokens: CryptoToken[];
|
|
11
|
+
currentToken: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const CryptoTokenSelectScreen: FC<CryptoTokenSelectScreenProps>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CryptoTokenSelectScreen, type CryptoToken, } from './CryptoTokenSelectScreen';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates that an externally-sourced image URL is safe to render as an
|
|
3
|
+
* `<img src>`. Token icon URLs come from the MoonPay currencies API response,
|
|
4
|
+
* so they are treated as untrusted input: only absolute HTTPS URLs are allowed,
|
|
5
|
+
* which rules out `javascript:`, `data:`, and other non-network schemes.
|
|
6
|
+
*/
|
|
7
|
+
export declare const isTrustedImageUrl: (url: string | undefined) => url is string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useInternalDynamicContext } from '../../../../context/DynamicContext/useDynamicContext';
|
|
2
|
+
import type { CryptoToken } from './CryptoTokenSelectScreen';
|
|
3
|
+
export type UseMoonPayOnrampParams = {
|
|
4
|
+
/** Pre-select a token; falls back to the first available currency when invalid. */
|
|
5
|
+
initialToken?: string;
|
|
6
|
+
merchantName?: string;
|
|
7
|
+
/** Override the wallet address; defaults to the primary wallet address. */
|
|
8
|
+
walletAddressOverride?: string;
|
|
9
|
+
/** Called with the signed MoonPay URL instead of opening a popup. */
|
|
10
|
+
onPaymentCreated?: (paymentUrl: string) => void;
|
|
11
|
+
};
|
|
12
|
+
export type UseMoonPayOnrampReturn = {
|
|
13
|
+
primaryWallet: ReturnType<typeof useInternalDynamicContext>['primaryWallet'];
|
|
14
|
+
availableTokens: CryptoToken[];
|
|
15
|
+
tokensLoading: boolean;
|
|
16
|
+
tokensError: boolean;
|
|
17
|
+
selectedToken: string;
|
|
18
|
+
setSelectedToken: (tokenCode: string) => void;
|
|
19
|
+
isOpening: boolean;
|
|
20
|
+
error: string | null;
|
|
21
|
+
effectiveWalletAddress: string;
|
|
22
|
+
openMoonPay: () => void;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Owns the MoonPay onramp data + actions: fetching supported currencies for the
|
|
26
|
+
* connected wallet's chain, tracking the selected token, and opening the signed
|
|
27
|
+
* MoonPay URL (validated against *.moonpay.com over HTTPS). The presentational
|
|
28
|
+
* MoonPayOnramp view consumes this hook.
|
|
29
|
+
*/
|
|
30
|
+
export declare const useMoonPayOnramp: ({ initialToken, merchantName, walletAddressOverride, onPaymentCreated, }: UseMoonPayOnrampParams) => UseMoonPayOnrampReturn;
|