@dynamic-labs/sdk-react-core 4.87.1 → 4.88.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 CHANGED
@@ -1,4 +1,24 @@
1
1
 
2
+ ## [4.88.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.87.2...v4.88.0) (2026-06-04)
3
+
4
+
5
+ ### Features
6
+
7
+ * **waas:** log out on iframe 401 ([#11456](https://github.com/dynamic-labs/dynamic-auth/issues/11456)) ([81b0161](https://github.com/dynamic-labs/dynamic-auth/commit/81b01617810af8f7f996fdbf406e020b9f98272b))
8
+
9
+
10
+ ### Bug Fixes
11
+
12
+ * **starknet:** zero-pad addresses returned by wallet connectors ([#11303](https://github.com/dynamic-labs/dynamic-auth/issues/11303)) ([ef5cda5](https://github.com/dynamic-labs/dynamic-auth/commit/ef5cda5a9933443195b3bd336db8947c2ec050b7))
13
+
14
+ ### [4.87.2](https://github.com/dynamic-labs/dynamic-auth/compare/v4.87.1...v4.87.2) (2026-06-03)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * allow for using v2 zerodev projects ([#11449](https://github.com/dynamic-labs/dynamic-auth/issues/11449)) ([9242698](https://github.com/dynamic-labs/dynamic-auth/commit/9242698670db92b03ad1afc776e674ec9a7e7e54))
20
+ * e2e: ensure MFA item is detached before logout ([#11452](https://github.com/dynamic-labs/dynamic-auth/issues/11452)) ([5a4c67e](https://github.com/dynamic-labs/dynamic-auth/commit/5a4c67e93b66a548346c1065fb373c675f0054a0))
21
+
2
22
  ### [4.87.1](https://github.com/dynamic-labs/dynamic-auth/compare/v4.87.0...v4.87.1) (2026-06-03)
3
23
 
4
24
 
package/package.cjs CHANGED
@@ -3,11 +3,11 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "4.87.1";
6
+ var version = "4.88.0";
7
7
  var dependencies = {
8
8
  "@dynamic-labs/sdk-api-core": "0.0.1015",
9
- "@dynamic-labs-sdk/client": "1.5.0",
10
- "@dynamic-labs-wallet/browser-wallet-client": "1.0.13",
9
+ "@dynamic-labs-sdk/client": "1.7.0",
10
+ "@dynamic-labs-wallet/browser-wallet-client": "1.0.16",
11
11
  "@dynamic-labs-wallet/forward-mpc-client": "0.10.1",
12
12
  "@hcaptcha/react-hcaptcha": "1.4.4",
13
13
  "@thumbmarkjs/thumbmarkjs": "0.16.0",
package/package.js CHANGED
@@ -1,9 +1,9 @@
1
1
  'use client'
2
- var version = "4.87.1";
2
+ var version = "4.88.0";
3
3
  var dependencies = {
4
4
  "@dynamic-labs/sdk-api-core": "0.0.1015",
5
- "@dynamic-labs-sdk/client": "1.5.0",
6
- "@dynamic-labs-wallet/browser-wallet-client": "1.0.13",
5
+ "@dynamic-labs-sdk/client": "1.7.0",
6
+ "@dynamic-labs-wallet/browser-wallet-client": "1.0.16",
7
7
  "@dynamic-labs-wallet/forward-mpc-client": "0.10.1",
8
8
  "@hcaptcha/react-hcaptcha": "1.4.4",
9
9
  "@thumbmarkjs/thumbmarkjs": "0.16.0",
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@dynamic-labs/sdk-react-core",
3
- "version": "4.87.1",
3
+ "version": "4.88.0",
4
4
  "dependencies": {
5
5
  "@dynamic-labs/sdk-api-core": "0.0.1015",
6
- "@dynamic-labs-sdk/client": "1.5.0",
7
- "@dynamic-labs-wallet/browser-wallet-client": "1.0.13",
6
+ "@dynamic-labs-sdk/client": "1.7.0",
7
+ "@dynamic-labs-wallet/browser-wallet-client": "1.0.16",
8
8
  "@dynamic-labs-wallet/forward-mpc-client": "0.10.1",
9
9
  "@hcaptcha/react-hcaptcha": "1.4.4",
10
10
  "@thumbmarkjs/thumbmarkjs": "0.16.0",
@@ -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.87.1",
21
- "@dynamic-labs/iconic": "4.87.1",
22
- "@dynamic-labs/locale": "4.87.1",
23
- "@dynamic-labs/logger": "4.87.1",
24
- "@dynamic-labs/multi-wallet": "4.87.1",
25
- "@dynamic-labs/rpc-providers": "4.87.1",
26
- "@dynamic-labs/store": "4.87.1",
27
- "@dynamic-labs/types": "4.87.1",
28
- "@dynamic-labs/utils": "4.87.1",
29
- "@dynamic-labs/wallet-book": "4.87.1",
30
- "@dynamic-labs/wallet-connector-core": "4.87.1",
20
+ "@dynamic-labs/assert-package-version": "4.88.0",
21
+ "@dynamic-labs/iconic": "4.88.0",
22
+ "@dynamic-labs/locale": "4.88.0",
23
+ "@dynamic-labs/logger": "4.88.0",
24
+ "@dynamic-labs/multi-wallet": "4.88.0",
25
+ "@dynamic-labs/rpc-providers": "4.88.0",
26
+ "@dynamic-labs/store": "4.88.0",
27
+ "@dynamic-labs/types": "4.88.0",
28
+ "@dynamic-labs/utils": "4.88.0",
29
+ "@dynamic-labs/wallet-book": "4.88.0",
30
+ "@dynamic-labs/wallet-connector-core": "4.88.0",
31
31
  "eventemitter3": "5.0.1"
32
32
  },
33
33
  "devDependencies": {
@@ -346,7 +346,12 @@ const InnerDynamicContextProvider = (props) => {
346
346
  //selected wallet to perform an action (become primary, unlink, etc)
347
347
  const [selectedWalletWithAction, setSelectedWalletWithAction] = React.useState(null);
348
348
  useSetWalletConnectorVerifiedCredentials.useSetWalletConnectorVerifiedCredentials(user !== null && user !== void 0 ? user : userWithMissingInfo, walletConnectorOptions);
349
- useSetWalletConnectorFetchers.useSetWalletConnectorFetchers(walletConnectorOptions, environmentId, projectSettings);
349
+ // handleLogOutWithReason is created later in this component (via useHandleLogout),
350
+ // but useSetWalletConnectorFetchers needs a logout callback now. Bridge the two
351
+ // with a ref: the WaaS connector only invokes onUnauthorized at runtime (when
352
+ // the iframe reports a 401), by which point the ref is populated.
353
+ const handleLogOutWithReasonRef = React.useRef();
354
+ useSetWalletConnectorFetchers.useSetWalletConnectorFetchers(walletConnectorOptions, environmentId, projectSettings, () => { var _a; return (_a = handleLogOutWithReasonRef.current) === null || _a === void 0 ? void 0 : _a.call(handleLogOutWithReasonRef, 'session-refresh-unauthorized'); });
350
355
  const { primaryWallet, showQrcodeModal, secondaryWallets, setPrimaryWallet, setShowQrcodeModal, wallets: linkedOrConnectedWallets, } = useWalletConnectors.useWalletConnectors({
351
356
  canHaveMultipleWalletsConnected: multiWallet || isBridgeFlow,
352
357
  connectedWallets,
@@ -402,6 +407,9 @@ const InnerDynamicContextProvider = (props) => {
402
407
  environmentId,
403
408
  handleLogOutWithReason,
404
409
  });
410
+ // Keep the ref current so the WaaS connector's onUnauthorized callback always
411
+ // calls the latest logout handler.
412
+ handleLogOutWithReasonRef.current = handleLogOutWithReason;
405
413
  // For some reason, calling useNonce in useGlobalLoading causes errors
406
414
  const nonce$1 = nonce.useNonce();
407
415
  const sdkHasLoaded = useGlobalLoading.useGlobalLoading({
@@ -1,7 +1,7 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../../../_virtual/_tslib.js';
3
3
  import { jsx, jsxs } from 'react/jsx-runtime';
4
- import { createContext, useEffect, useState, useMemo, useCallback } from 'react';
4
+ import { createContext, useEffect, useState, useMemo, useRef, useCallback } from 'react';
5
5
  import { I18nextProvider } from 'react-i18next';
6
6
  import { getIconicSpriteUrl } from '@dynamic-labs/iconic';
7
7
  import { Logger } from '@dynamic-labs/logger';
@@ -342,7 +342,12 @@ const InnerDynamicContextProvider = (props) => {
342
342
  //selected wallet to perform an action (become primary, unlink, etc)
343
343
  const [selectedWalletWithAction, setSelectedWalletWithAction] = useState(null);
344
344
  useSetWalletConnectorVerifiedCredentials(user !== null && user !== void 0 ? user : userWithMissingInfo, walletConnectorOptions);
345
- useSetWalletConnectorFetchers(walletConnectorOptions, environmentId, projectSettings);
345
+ // handleLogOutWithReason is created later in this component (via useHandleLogout),
346
+ // but useSetWalletConnectorFetchers needs a logout callback now. Bridge the two
347
+ // with a ref: the WaaS connector only invokes onUnauthorized at runtime (when
348
+ // the iframe reports a 401), by which point the ref is populated.
349
+ const handleLogOutWithReasonRef = useRef();
350
+ useSetWalletConnectorFetchers(walletConnectorOptions, environmentId, projectSettings, () => { var _a; return (_a = handleLogOutWithReasonRef.current) === null || _a === void 0 ? void 0 : _a.call(handleLogOutWithReasonRef, 'session-refresh-unauthorized'); });
346
351
  const { primaryWallet, showQrcodeModal, secondaryWallets, setPrimaryWallet, setShowQrcodeModal, wallets: linkedOrConnectedWallets, } = useWalletConnectors({
347
352
  canHaveMultipleWalletsConnected: multiWallet || isBridgeFlow,
348
353
  connectedWallets,
@@ -398,6 +403,9 @@ const InnerDynamicContextProvider = (props) => {
398
403
  environmentId,
399
404
  handleLogOutWithReason,
400
405
  });
406
+ // Keep the ref current so the WaaS connector's onUnauthorized callback always
407
+ // calls the latest logout handler.
408
+ handleLogOutWithReasonRef.current = handleLogOutWithReason;
401
409
  // For some reason, calling useNonce in useGlobalLoading causes errors
402
410
  const nonce = useNonce();
403
411
  const sdkHasLoaded = useGlobalLoading({
@@ -54,7 +54,7 @@ var normalizeWaasChainName = require('./normalizeWaasChainName.cjs');
54
54
  var normalizeWalletRequirements = require('./normalizeWalletRequirements.cjs');
55
55
 
56
56
  const dynamicWaasKey = 'dynamicwaas';
57
- const configWaasWalletConnector = ({ walletConnector, environmentId, apiBaseUrl, relayUrl, baseClientKeysharesRelayApiUrl, authMode = 'header', getSignedSessionId, getMfaToken, getWalletPassword, getSvmGasSponsorshipEnabled = () => false, getElevatedAccessToken, }) => {
57
+ const configWaasWalletConnector = ({ walletConnector, environmentId, apiBaseUrl, relayUrl, baseClientKeysharesRelayApiUrl, authMode = 'header', getSignedSessionId, getMfaToken, getWalletPassword, getSvmGasSponsorshipEnabled = () => false, getElevatedAccessToken, onUnauthorized, }) => {
58
58
  var _a;
59
59
  walletConnector.setEnvironmentId(environmentId);
60
60
  walletConnector.setBaseApiUrl((_a = (apiBaseUrl || apiUrl.DEFAULT_WAAS_API_URL)) === null || _a === void 0 ? void 0 : _a.replace('/api/v0', ''));
@@ -78,6 +78,10 @@ const configWaasWalletConnector = ({ walletConnector, environmentId, apiBaseUrl,
78
78
  if (getWalletPassword) {
79
79
  walletConnector.setGetWalletPasswordFunction(getWalletPassword);
80
80
  }
81
+ // Log the user out when the iframe reports a 401 (e.g. token forcibly revoked)
82
+ if (onUnauthorized) {
83
+ walletConnector.setOnUnauthorizedFunction(onUnauthorized);
84
+ }
81
85
  // Sync SVM gas sponsorship setting for SOL connectors
82
86
  const isSolConnector = walletConnector.connectedChain === 'SOL';
83
87
  const supportsSponsorshipSetting = 'setSvmGasSponsorshipEnabled' in walletConnector;
@@ -88,7 +92,7 @@ const configWaasWalletConnector = ({ walletConnector, environmentId, apiBaseUrl,
88
92
  };
89
93
  const useDynamicWaas = () => {
90
94
  var _a, _b, _c, _d, _e, _f, _g;
91
- const { setShowAuthFlow } = useInternalDynamicContext.useInternalDynamicContext();
95
+ const { setShowAuthFlow, handleLogOutWithReason } = useInternalDynamicContext.useInternalDynamicContext();
92
96
  const { addedWalletsIds, userWallets } = UserWalletsContext.useInternalUserWallets();
93
97
  const user = useUser.useUser();
94
98
  const apiBaseUrl = dynamicContextProps.useApiBaseUrl();
@@ -139,6 +143,7 @@ const useDynamicWaas = () => {
139
143
  getSignedSessionId: generateChainingSignature.generateChainingSignature,
140
144
  getSvmGasSponsorshipEnabled: () => svmGasSponsorshipEnabledRef.current,
141
145
  getWalletPassword,
146
+ onUnauthorized: () => handleLogOutWithReason('session-refresh-unauthorized'),
142
147
  relayUrl: relayUrl !== null && relayUrl !== void 0 ? relayUrl : '',
143
148
  walletConnector,
144
149
  });
@@ -152,6 +157,7 @@ const useDynamicWaas = () => {
152
157
  getElevatedAccessToken,
153
158
  getMfaToken,
154
159
  getWalletPassword,
160
+ handleLogOutWithReason,
155
161
  relayUrl,
156
162
  baseClientKeysharesRelayApiUrl,
157
163
  ]);
@@ -12,7 +12,7 @@ export type WalletCreationRequirement = {
12
12
  network?: string;
13
13
  };
14
14
  };
15
- export declare const configWaasWalletConnector: ({ walletConnector, environmentId, apiBaseUrl, relayUrl, baseClientKeysharesRelayApiUrl, authMode, getSignedSessionId, getMfaToken, getWalletPassword, getSvmGasSponsorshipEnabled, getElevatedAccessToken, }: {
15
+ export declare const configWaasWalletConnector: ({ walletConnector, environmentId, apiBaseUrl, relayUrl, baseClientKeysharesRelayApiUrl, authMode, getSignedSessionId, getMfaToken, getWalletPassword, getSvmGasSponsorshipEnabled, getElevatedAccessToken, onUnauthorized, }: {
16
16
  walletConnector: IDynamicWaasConnector;
17
17
  environmentId: string;
18
18
  apiBaseUrl: string;
@@ -28,6 +28,7 @@ export declare const configWaasWalletConnector: ({ walletConnector, environmentI
28
28
  getElevatedAccessToken?: (params: {
29
29
  scope: TokenScope;
30
30
  }) => Promise<string | undefined>;
31
+ onUnauthorized?: () => void | Promise<void>;
31
32
  }) => IDynamicWaasConnector;
32
33
  export declare const useDynamicWaas: () => {
33
34
  areWalletsReadyForSettings: () => boolean;
@@ -50,7 +50,7 @@ import { normalizeWaasChainName } from './normalizeWaasChainName.js';
50
50
  import { normalizeWalletRequirements } from './normalizeWalletRequirements.js';
51
51
 
52
52
  const dynamicWaasKey = 'dynamicwaas';
53
- const configWaasWalletConnector = ({ walletConnector, environmentId, apiBaseUrl, relayUrl, baseClientKeysharesRelayApiUrl, authMode = 'header', getSignedSessionId, getMfaToken, getWalletPassword, getSvmGasSponsorshipEnabled = () => false, getElevatedAccessToken, }) => {
53
+ const configWaasWalletConnector = ({ walletConnector, environmentId, apiBaseUrl, relayUrl, baseClientKeysharesRelayApiUrl, authMode = 'header', getSignedSessionId, getMfaToken, getWalletPassword, getSvmGasSponsorshipEnabled = () => false, getElevatedAccessToken, onUnauthorized, }) => {
54
54
  var _a;
55
55
  walletConnector.setEnvironmentId(environmentId);
56
56
  walletConnector.setBaseApiUrl((_a = (apiBaseUrl || DEFAULT_WAAS_API_URL)) === null || _a === void 0 ? void 0 : _a.replace('/api/v0', ''));
@@ -74,6 +74,10 @@ const configWaasWalletConnector = ({ walletConnector, environmentId, apiBaseUrl,
74
74
  if (getWalletPassword) {
75
75
  walletConnector.setGetWalletPasswordFunction(getWalletPassword);
76
76
  }
77
+ // Log the user out when the iframe reports a 401 (e.g. token forcibly revoked)
78
+ if (onUnauthorized) {
79
+ walletConnector.setOnUnauthorizedFunction(onUnauthorized);
80
+ }
77
81
  // Sync SVM gas sponsorship setting for SOL connectors
78
82
  const isSolConnector = walletConnector.connectedChain === 'SOL';
79
83
  const supportsSponsorshipSetting = 'setSvmGasSponsorshipEnabled' in walletConnector;
@@ -84,7 +88,7 @@ const configWaasWalletConnector = ({ walletConnector, environmentId, apiBaseUrl,
84
88
  };
85
89
  const useDynamicWaas = () => {
86
90
  var _a, _b, _c, _d, _e, _f, _g;
87
- const { setShowAuthFlow } = useInternalDynamicContext();
91
+ const { setShowAuthFlow, handleLogOutWithReason } = useInternalDynamicContext();
88
92
  const { addedWalletsIds, userWallets } = useInternalUserWallets();
89
93
  const user = useUser();
90
94
  const apiBaseUrl = useApiBaseUrl();
@@ -135,6 +139,7 @@ const useDynamicWaas = () => {
135
139
  getSignedSessionId: generateChainingSignature,
136
140
  getSvmGasSponsorshipEnabled: () => svmGasSponsorshipEnabledRef.current,
137
141
  getWalletPassword,
142
+ onUnauthorized: () => handleLogOutWithReason('session-refresh-unauthorized'),
138
143
  relayUrl: relayUrl !== null && relayUrl !== void 0 ? relayUrl : '',
139
144
  walletConnector,
140
145
  });
@@ -148,6 +153,7 @@ const useDynamicWaas = () => {
148
153
  getElevatedAccessToken,
149
154
  getMfaToken,
150
155
  getWalletPassword,
156
+ handleLogOutWithReason,
151
157
  relayUrl,
152
158
  baseClientKeysharesRelayApiUrl,
153
159
  ]);
@@ -117,7 +117,11 @@ require('../../../store/state/multichainBalances.cjs');
117
117
  require('@dynamic-labs/store');
118
118
  require('../../../shared/utils/functions/getInitialUrl/getInitialUrl.cjs');
119
119
 
120
- const useSetWalletConnectorFetchers = (walletOptions, environmentId, projectSettings) => {
120
+ const useSetWalletConnectorFetchers = (walletOptions, environmentId, projectSettings,
121
+ // Logs the user out when the iframe reports a 401. Passed in (rather than read
122
+ // from context) because this hook runs inside DynamicContextProvider itself,
123
+ // where the context value isn't available to consume.
124
+ onUnauthorized) => {
121
125
  var _a, _b, _c;
122
126
  const apiBaseUrl = dynamicContextProps.useApiBaseUrl();
123
127
  const { registerEmbeddedWalletSessionKey, removeSessionKey } = useEmbeddedWalletSessionKeys.useEmbeddedWalletSessionKeys({ environmentId, projectSettings });
@@ -142,6 +146,7 @@ const useSetWalletConnectorFetchers = (walletOptions, environmentId, projectSett
142
146
  getMfaToken,
143
147
  getSignedSessionId: generateChainingSignature.generateChainingSignature,
144
148
  getSvmGasSponsorshipEnabled: () => svmGasSponsorshipEnabledRef.current,
149
+ onUnauthorized,
145
150
  relayUrl: (_e = (_d = (_c = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.sdk) === null || _c === void 0 ? void 0 : _c.waas) === null || _d === void 0 ? void 0 : _d.relayUrl) !== null && _e !== void 0 ? _e : '',
146
151
  walletConnector: walletOption.walletConnector,
147
152
  });
@@ -1,3 +1,3 @@
1
1
  import { ProjectSettings } from '@dynamic-labs/sdk-api-core';
2
2
  import { WalletOption } from '../../../shared';
3
- export declare const useSetWalletConnectorFetchers: (walletOptions: WalletOption[] | undefined, environmentId: string, projectSettings: ProjectSettings | undefined) => void;
3
+ export declare const useSetWalletConnectorFetchers: (walletOptions: WalletOption[] | undefined, environmentId: string, projectSettings: ProjectSettings | undefined, onUnauthorized?: () => void | Promise<void>) => void;
@@ -113,7 +113,11 @@ import '../../../store/state/multichainBalances.js';
113
113
  import '@dynamic-labs/store';
114
114
  import '../../../shared/utils/functions/getInitialUrl/getInitialUrl.js';
115
115
 
116
- const useSetWalletConnectorFetchers = (walletOptions, environmentId, projectSettings) => {
116
+ const useSetWalletConnectorFetchers = (walletOptions, environmentId, projectSettings,
117
+ // Logs the user out when the iframe reports a 401. Passed in (rather than read
118
+ // from context) because this hook runs inside DynamicContextProvider itself,
119
+ // where the context value isn't available to consume.
120
+ onUnauthorized) => {
117
121
  var _a, _b, _c;
118
122
  const apiBaseUrl = useApiBaseUrl();
119
123
  const { registerEmbeddedWalletSessionKey, removeSessionKey } = useEmbeddedWalletSessionKeys({ environmentId, projectSettings });
@@ -138,6 +142,7 @@ const useSetWalletConnectorFetchers = (walletOptions, environmentId, projectSett
138
142
  getMfaToken,
139
143
  getSignedSessionId: generateChainingSignature,
140
144
  getSvmGasSponsorshipEnabled: () => svmGasSponsorshipEnabledRef.current,
145
+ onUnauthorized,
141
146
  relayUrl: (_e = (_d = (_c = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.sdk) === null || _c === void 0 ? void 0 : _c.waas) === null || _d === void 0 ? void 0 : _d.relayUrl) !== null && _e !== void 0 ? _e : '',
142
147
  walletConnector: walletOption.walletConnector,
143
148
  });
@@ -153,6 +153,7 @@ const useSyncDynamicWaas = () => {
153
153
  const { mutate: processSettings, isLoading: isProcessingSettings } = useWalletSettingsProcessor();
154
154
  const { initDelegationProcess, shouldPromptWalletDelegation } = useWalletDelegation.useWalletDelegation();
155
155
  const user = useOnboardingCompleteUser.useOnboardingCompleteUser();
156
+ const environmentId = dynamicContextProps.useEnvironmentId();
156
157
  const triggeredCreate = React.useRef(false);
157
158
  const triggeredSettingsProcessing = React.useRef(false);
158
159
  const hasWaasInitializedRef = React.useRef(false);
@@ -233,11 +234,22 @@ const useSyncDynamicWaas = () => {
233
234
  ? '[useSyncDynamicWaas] session id changed, initializing waas'
234
235
  : '[useSyncDynamicWaas] waas not initialized, initializing waas');
235
236
  initializingWaasRef.current = true;
237
+ const initStartedAt = Date.now();
236
238
  initializeWaas()
237
239
  .then(() => {
238
240
  logger.logger.debug('[useSyncDynamicWaas] waas initialized');
239
241
  hasWaasInitializedRef.current = true;
240
242
  sessionIdRef.current = sessionId;
243
+ // Host-observed time to get the WaaS iframe/client ready. Ships to
244
+ // Datadog (sliced by @version + environmentId) as the host-side
245
+ // companion to the iframe app's `waas_iframe_*` timing — used to
246
+ // quantify the per-page cost the bwc 0.x -> 1.x rewrite introduced.
247
+ logger.logger.instrument('WaaS host init', {
248
+ environmentId,
249
+ key: 'waas_host_init',
250
+ time: Date.now() - initStartedAt,
251
+ userId,
252
+ });
241
253
  })
242
254
  .catch((error) => {
243
255
  logger.logger.warn('[useSyncDynamicWaas] Error initializing waas', {
@@ -245,6 +257,13 @@ const useSyncDynamicWaas = () => {
245
257
  sessionId,
246
258
  userId,
247
259
  });
260
+ logger.logger.instrument('WaaS host init failed', {
261
+ environmentId,
262
+ key: 'waas_host_init_failed',
263
+ reason: error instanceof Error ? error.message : String(error),
264
+ time: Date.now() - initStartedAt,
265
+ userId,
266
+ });
248
267
  })
249
268
  .finally(() => {
250
269
  initializingWaasRef.current = false;
@@ -149,6 +149,7 @@ const useSyncDynamicWaas = () => {
149
149
  const { mutate: processSettings, isLoading: isProcessingSettings } = useWalletSettingsProcessor();
150
150
  const { initDelegationProcess, shouldPromptWalletDelegation } = useWalletDelegation();
151
151
  const user = useOnboardingCompleteUser();
152
+ const environmentId = useEnvironmentId();
152
153
  const triggeredCreate = useRef(false);
153
154
  const triggeredSettingsProcessing = useRef(false);
154
155
  const hasWaasInitializedRef = useRef(false);
@@ -229,11 +230,22 @@ const useSyncDynamicWaas = () => {
229
230
  ? '[useSyncDynamicWaas] session id changed, initializing waas'
230
231
  : '[useSyncDynamicWaas] waas not initialized, initializing waas');
231
232
  initializingWaasRef.current = true;
233
+ const initStartedAt = Date.now();
232
234
  initializeWaas()
233
235
  .then(() => {
234
236
  logger.debug('[useSyncDynamicWaas] waas initialized');
235
237
  hasWaasInitializedRef.current = true;
236
238
  sessionIdRef.current = sessionId;
239
+ // Host-observed time to get the WaaS iframe/client ready. Ships to
240
+ // Datadog (sliced by @version + environmentId) as the host-side
241
+ // companion to the iframe app's `waas_iframe_*` timing — used to
242
+ // quantify the per-page cost the bwc 0.x -> 1.x rewrite introduced.
243
+ logger.instrument('WaaS host init', {
244
+ environmentId,
245
+ key: 'waas_host_init',
246
+ time: Date.now() - initStartedAt,
247
+ userId,
248
+ });
237
249
  })
238
250
  .catch((error) => {
239
251
  logger.warn('[useSyncDynamicWaas] Error initializing waas', {
@@ -241,6 +253,13 @@ const useSyncDynamicWaas = () => {
241
253
  sessionId,
242
254
  userId,
243
255
  });
256
+ logger.instrument('WaaS host init failed', {
257
+ environmentId,
258
+ key: 'waas_host_init_failed',
259
+ reason: error instanceof Error ? error.message : String(error),
260
+ time: Date.now() - initStartedAt,
261
+ userId,
262
+ });
244
263
  })
245
264
  .finally(() => {
246
265
  initializingWaasRef.current = false;
@@ -15,4 +15,16 @@ export type CloudProviderBackupOptions = {
15
15
  provider: CloudBackupProvider;
16
16
  accountAddress: string;
17
17
  password?: string;
18
+ /**
19
+ * Optional consumer-supplied Google Drive access token. When provided (and
20
+ * already granted Drive scopes), the SDK uses it directly instead of falling
21
+ * back to the stored OAuth token — avoiding a second Google consent prompt.
22
+ *
23
+ * Especially useful for consumers using external auth: the user's Google
24
+ * account isn't linked in Dynamic, so there's no stored OAuth token to fall
25
+ * back on — they obtain a Drive-scoped token themselves and pass it here.
26
+ *
27
+ * Only applies to the GoogleDrive provider.
28
+ */
29
+ googleDriveAccessToken?: string;
18
30
  };
@@ -292,7 +292,7 @@ const useWalletBackup = (options) => {
292
292
  return true;
293
293
  }, [isGoogleLinked]);
294
294
  const backupToCloudProviderCore = React.useCallback((options, walletToBackup) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
295
- const { provider, password } = options;
295
+ const { provider, password, googleDriveAccessToken } = options;
296
296
  try {
297
297
  const waasConnector = getWaasWalletConnector(walletToBackup.chain);
298
298
  if (!waasConnector) {
@@ -304,6 +304,7 @@ const useWalletBackup = (options) => {
304
304
  if (provider === types.CloudBackupProvider.GoogleDrive) {
305
305
  yield waasConnector.backupKeySharesToGoogleDrive({
306
306
  accountAddress: walletToBackup.address,
307
+ googleDriveAccessToken,
307
308
  password,
308
309
  });
309
310
  }
@@ -288,7 +288,7 @@ const useWalletBackup = (options) => {
288
288
  return true;
289
289
  }, [isGoogleLinked]);
290
290
  const backupToCloudProviderCore = useCallback((options, walletToBackup) => __awaiter(void 0, void 0, void 0, function* () {
291
- const { provider, password } = options;
291
+ const { provider, password, googleDriveAccessToken } = options;
292
292
  try {
293
293
  const waasConnector = getWaasWalletConnector(walletToBackup.chain);
294
294
  if (!waasConnector) {
@@ -300,6 +300,7 @@ const useWalletBackup = (options) => {
300
300
  if (provider === CloudBackupProvider.GoogleDrive) {
301
301
  yield waasConnector.backupKeySharesToGoogleDrive({
302
302
  accountAddress: walletToBackup.address,
303
+ googleDriveAccessToken,
303
304
  password,
304
305
  });
305
306
  }