@dynamic-labs-sdk/client 0.17.1 → 0.17.3

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.
Files changed (120) hide show
  1. package/dist/{InvalidParamError-3-1rSNtf.esm.js → InvalidParamError-C8bqZx25.esm.js} +59 -130
  2. package/dist/InvalidParamError-C8bqZx25.esm.js.map +1 -0
  3. package/dist/{InvalidParamError-zIxsXkiH.cjs.js → InvalidParamError-DvFYOkxL.cjs.js} +65 -187
  4. package/dist/InvalidParamError-DvFYOkxL.cjs.js.map +1 -0
  5. package/dist/{NotWaasWalletAccountError-DVIcEgHJ.esm.js → NotWaasWalletAccountError-C-_6uyUM.esm.js} +3 -3
  6. package/dist/{NotWaasWalletAccountError-DVIcEgHJ.esm.js.map → NotWaasWalletAccountError-C-_6uyUM.esm.js.map} +1 -1
  7. package/dist/{NotWaasWalletAccountError-B_Wl6sTh.cjs.js → NotWaasWalletAccountError-CHSFUjd9.cjs.js} +3 -3
  8. package/dist/{NotWaasWalletAccountError-B_Wl6sTh.cjs.js.map → NotWaasWalletAccountError-CHSFUjd9.cjs.js.map} +1 -1
  9. package/dist/client/core/createCore/createCore.d.ts.map +1 -1
  10. package/dist/client/core/types/DynamicCore.d.ts +20 -0
  11. package/dist/client/core/types/DynamicCore.d.ts.map +1 -1
  12. package/dist/client/core/types/DynamicCoreConfig.d.ts +1 -1
  13. package/dist/client/core/types/DynamicCoreConfig.d.ts.map +1 -1
  14. package/dist/client/types/DynamicClientConfig.d.ts +5 -0
  15. package/dist/client/types/DynamicClientConfig.d.ts.map +1 -1
  16. package/dist/core.cjs.js +24 -11
  17. package/dist/core.cjs.js.map +1 -1
  18. package/dist/core.esm.js +16 -6
  19. package/dist/core.esm.js.map +1 -1
  20. package/dist/exports/core.d.ts +10 -0
  21. package/dist/exports/core.d.ts.map +1 -1
  22. package/dist/{getNetworkProviderFromNetworkId-BJR1GciB.cjs.js → getNetworkProviderFromNetworkId-DK9fnM_Y.cjs.js} +432 -69
  23. package/dist/getNetworkProviderFromNetworkId-DK9fnM_Y.cjs.js.map +1 -0
  24. package/dist/{getNetworkProviderFromNetworkId-C7jp--76.esm.js → getNetworkProviderFromNetworkId-n7VUDpn0.esm.js} +374 -68
  25. package/dist/getNetworkProviderFromNetworkId-n7VUDpn0.esm.js.map +1 -0
  26. package/dist/{getSignedSessionId-DVpOgsL9.cjs.js → getSignedSessionId-B2-EYPik.cjs.js} +7 -17
  27. package/dist/getSignedSessionId-B2-EYPik.cjs.js.map +1 -0
  28. package/dist/{getSignedSessionId-Alfz9eul.esm.js → getSignedSessionId-CM3X3R5t.esm.js} +7 -17
  29. package/dist/getSignedSessionId-CM3X3R5t.esm.js.map +1 -0
  30. package/dist/{getVerifiedCredentialForWalletAccount-DLtDL1Gl.esm.js → getVerifiedCredentialForWalletAccount-Cs7AcMKQ.esm.js} +2 -2
  31. package/dist/{getVerifiedCredentialForWalletAccount-DLtDL1Gl.esm.js.map → getVerifiedCredentialForWalletAccount-Cs7AcMKQ.esm.js.map} +1 -1
  32. package/dist/{getVerifiedCredentialForWalletAccount-D25Vyxub.cjs.js → getVerifiedCredentialForWalletAccount-CyLnpS2G.cjs.js} +3 -2
  33. package/dist/{getVerifiedCredentialForWalletAccount-D25Vyxub.cjs.js.map → getVerifiedCredentialForWalletAccount-CyLnpS2G.cjs.js.map} +1 -1
  34. package/dist/index.cjs.js +182 -79
  35. package/dist/index.cjs.js.map +1 -1
  36. package/dist/index.esm.js +174 -71
  37. package/dist/index.esm.js.map +1 -1
  38. package/dist/{isMfaRequiredForAction-CYYU8V1B.cjs.js → isMfaRequiredForAction-BrRKwK_i.cjs.js} +2 -2
  39. package/dist/{isMfaRequiredForAction-CYYU8V1B.cjs.js.map → isMfaRequiredForAction-BrRKwK_i.cjs.js.map} +1 -1
  40. package/dist/{isMfaRequiredForAction-CPTFDCJp.esm.js → isMfaRequiredForAction-CM26tbT2.esm.js} +2 -2
  41. package/dist/{isMfaRequiredForAction-CPTFDCJp.esm.js.map → isMfaRequiredForAction-CM26tbT2.esm.js.map} +1 -1
  42. package/dist/modules/apiClient/apiClient.types.d.ts +7 -0
  43. package/dist/modules/apiClient/apiClient.types.d.ts.map +1 -1
  44. package/dist/modules/apiClient/constants.d.ts +2 -0
  45. package/dist/modules/apiClient/constants.d.ts.map +1 -1
  46. package/dist/modules/apiClient/createApiClient.d.ts.map +1 -1
  47. package/dist/modules/auth/getElevatedAccessToken/getElevatedAccessToken.d.ts +15 -8
  48. package/dist/modules/auth/getElevatedAccessToken/getElevatedAccessToken.d.ts.map +1 -1
  49. package/dist/modules/auth/logout/logout.d.ts.map +1 -1
  50. package/dist/modules/auth/passkeys/deletePasskey/deletePasskey.d.ts.map +1 -1
  51. package/dist/modules/auth/passkeys/serverRegisterPasskey/serverRegisterPasskey.d.ts.map +1 -1
  52. package/dist/modules/deviceRegistration/getDeviceSigner/getDeviceSigner.d.ts.map +1 -1
  53. package/dist/modules/initializeClient/initializeClient.d.ts.map +1 -1
  54. package/dist/modules/keychainMigration/migrateSessionKeyToKeychain/KeyMigrationError.d.ts +5 -0
  55. package/dist/modules/keychainMigration/migrateSessionKeyToKeychain/KeyMigrationError.d.ts.map +1 -0
  56. package/dist/modules/keychainMigration/migrateSessionKeyToKeychain/migrateSessionKeyToKeychain.d.ts +24 -0
  57. package/dist/modules/keychainMigration/migrateSessionKeyToKeychain/migrateSessionKeyToKeychain.d.ts.map +1 -0
  58. package/dist/modules/mfa/deleteMfaDevice/deleteMfaDevice.d.ts +6 -4
  59. package/dist/modules/mfa/deleteMfaDevice/deleteMfaDevice.d.ts.map +1 -1
  60. package/dist/modules/mfa/registerTotpMfaDevice/registerTotpMfaDevice.d.ts.map +1 -1
  61. package/dist/modules/sessionKeys/generateNonceSignature/generateNonceSignature.d.ts.map +1 -1
  62. package/dist/modules/sessionKeys/generateSessionKeys/generateSessionKeys.d.ts.map +1 -1
  63. package/dist/modules/sessionKeys/generateSessionSignature/generateSessionSignature.d.ts.map +1 -1
  64. package/dist/modules/sessionKeys/getSessionKeys/getSessionKeys.d.ts.map +1 -1
  65. package/dist/modules/sessionKeys/sessionKeys.types.d.ts +0 -2
  66. package/dist/modules/sessionKeys/sessionKeys.types.d.ts.map +1 -1
  67. package/dist/services/instrumentation/constants.d.ts +17 -0
  68. package/dist/services/instrumentation/constants.d.ts.map +1 -0
  69. package/dist/services/instrumentation/createInstrumentation/createInstrumentation.d.ts +18 -0
  70. package/dist/services/instrumentation/createInstrumentation/createInstrumentation.d.ts.map +1 -0
  71. package/dist/services/instrumentation/createInstrumentation/index.d.ts +2 -0
  72. package/dist/services/instrumentation/createInstrumentation/index.d.ts.map +1 -0
  73. package/dist/services/instrumentation/instrumentation.types.d.ts +44 -0
  74. package/dist/services/instrumentation/instrumentation.types.d.ts.map +1 -0
  75. package/dist/services/instrumentation/scrubParameters/index.d.ts +2 -0
  76. package/dist/services/instrumentation/scrubParameters/index.d.ts.map +1 -0
  77. package/dist/services/instrumentation/scrubParameters/scrubParameters.d.ts +8 -0
  78. package/dist/services/instrumentation/scrubParameters/scrubParameters.d.ts.map +1 -0
  79. package/dist/services/keychain/createIndexedDBKeychainService/KeyNotFoundError.d.ts +5 -0
  80. package/dist/services/keychain/createIndexedDBKeychainService/KeyNotFoundError.d.ts.map +1 -0
  81. package/dist/services/keychain/createIndexedDBKeychainService/createIndexedDBKeychainService.d.ts +7 -0
  82. package/dist/services/keychain/createIndexedDBKeychainService/createIndexedDBKeychainService.d.ts.map +1 -0
  83. package/dist/services/keychain/createIndexedDBKeychainService/createIndexedDBKeychainService.types.d.ts +6 -0
  84. package/dist/services/keychain/createIndexedDBKeychainService/createIndexedDBKeychainService.types.d.ts.map +1 -0
  85. package/dist/services/keychain/createIndexedDBKeychainService/index.d.ts +2 -0
  86. package/dist/services/keychain/createIndexedDBKeychainService/index.d.ts.map +1 -0
  87. package/dist/services/keychain/createIndexedDBKeychainService/utils/constants.d.ts +2 -0
  88. package/dist/services/keychain/createIndexedDBKeychainService/utils/constants.d.ts.map +1 -0
  89. package/dist/services/keychain/createIndexedDBKeychainService/utils/deleteIndexedDBItem.d.ts +2 -0
  90. package/dist/services/keychain/createIndexedDBKeychainService/utils/deleteIndexedDBItem.d.ts.map +1 -0
  91. package/dist/services/keychain/createIndexedDBKeychainService/utils/getIndexedDBItem.d.ts +3 -0
  92. package/dist/services/keychain/createIndexedDBKeychainService/utils/getIndexedDBItem.d.ts.map +1 -0
  93. package/dist/services/keychain/createIndexedDBKeychainService/utils/openDatabase.d.ts +2 -0
  94. package/dist/services/keychain/createIndexedDBKeychainService/utils/openDatabase.d.ts.map +1 -0
  95. package/dist/services/keychain/createIndexedDBKeychainService/utils/setIndexedDBItem.d.ts +3 -0
  96. package/dist/services/keychain/createIndexedDBKeychainService/utils/setIndexedDBItem.d.ts.map +1 -0
  97. package/dist/services/keychain/errors/KeychainNotConfiguredError.d.ts +5 -0
  98. package/dist/services/keychain/errors/KeychainNotConfiguredError.d.ts.map +1 -0
  99. package/dist/services/keychain/index.d.ts +3 -0
  100. package/dist/services/keychain/index.d.ts.map +1 -0
  101. package/dist/services/keychain/keychain.types.d.ts +9 -0
  102. package/dist/services/keychain/keychain.types.d.ts.map +1 -0
  103. package/dist/services/realtime/createRealtimeService/createRealtimeService.d.ts +11 -0
  104. package/dist/services/realtime/createRealtimeService/createRealtimeService.d.ts.map +1 -0
  105. package/dist/services/realtime/createRealtimeService/index.d.ts +2 -0
  106. package/dist/services/realtime/createRealtimeService/index.d.ts.map +1 -0
  107. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  108. package/dist/waas.cjs.js +4 -3
  109. package/dist/waas.cjs.js.map +1 -1
  110. package/dist/waas.esm.js +3 -3
  111. package/dist/waasCore.cjs.js +4 -3
  112. package/dist/waasCore.cjs.js.map +1 -1
  113. package/dist/waasCore.esm.js +3 -3
  114. package/package.json +2 -2
  115. package/dist/InvalidParamError-3-1rSNtf.esm.js.map +0 -1
  116. package/dist/InvalidParamError-zIxsXkiH.cjs.js.map +0 -1
  117. package/dist/getNetworkProviderFromNetworkId-BJR1GciB.cjs.js.map +0 -1
  118. package/dist/getNetworkProviderFromNetworkId-C7jp--76.esm.js.map +0 -1
  119. package/dist/getSignedSessionId-Alfz9eul.esm.js.map +0 -1
  120. package/dist/getSignedSessionId-DVpOgsL9.cjs.js.map +0 -1
package/dist/index.esm.js CHANGED
@@ -1,10 +1,10 @@
1
- import { A as randomString, B as version, C as InvalidExternalAuthError, D as isCookieEnabled, F as setDefaultClient, L as BaseError, N as NONCE_POOL_SIZE, O as assertDefined, P as getDefaultClient, R as getCore, S as LinkCredentialError, a as DYNAMIC_ICONIC_SPRITE_URL, b as MfaRateLimitedError, c as CHAINS_INFO_MAP, d as UnauthorizedError, g as createStorageKeySchema, j as CLIENT_SDK_NAME, k as ValueMustBeDefinedError, l as fetchAndStoreNonces, o as SDK_API_CORE_VERSION, s as getChainFromVerifiedCredentialChain, t as InvalidParamError, u as createApiClient, v as getNonce, w as APIError, x as MfaInvalidOtpError, y as SandboxMaximumThresholdReachedError, z as name } from "./InvalidParamError-3-1rSNtf.esm.js";
2
- import { A as isEqualShallow, C as isServerSideRendering, D as REFRESH_USER_STATE_FROM_COOKIE_TRACKER_KEY, E as INITIALIZE_STORAGE_SYNC_TRACKER_KEY, N as createLocalStorageAdapter, O as generateSessionKeys, S as createDeferredPromise, T as GENERATE_SESSION_KEYS_TRACKER_KEY, _ as NoNetworkProvidersError, a as updateWalletProviderKeysForVerifiedCredentials, c as createSignInMessageStatement, d as createVisit, f as hasExtension, g as WalletAlreadyLinkedToAnotherUserError, h as isCaptchaRequired, i as getNetworksData, j as createStorage, k as subscribeWithSelector, l as formatSignInMessage, m as consumeCaptchaToken, o as verifyMessageSignatureOwnership, p as setCaptchaToken, s as removeUnverifiedWalletAccount, t as getNetworkProviderFromNetworkId, u as setUnverifiedWalletAccounts, v as createLogger, w as FETCH_PROJECT_SETTINGS_TRACKER_KEY, x as CannotTrackError, y as createCrossTabBroadcast } from "./getNetworkProviderFromNetworkId-C7jp--76.esm.js";
3
- import { D as onceEvent, E as onEvent, O as setCookie, S as splitWalletProviderKey, T as offEvent, _ as getWalletAccounts, b as formatWalletAccountId, c as getWalletProviders, d as DYNAMIC_AUTH_COOKIE_NAME, f as getWalletProviderFromWalletAccount, g as NoWalletProviderFoundError, i as restoreUserSharesForAllWalletAccounts, l as checkAndRaiseWalletAccountsChangedEvent, n as getWalletProviderByKey, r as updateAuthFromVerifyResponse, t as getVerifiedCredentialForWalletAccount, u as emitWalletAccountsChangedEvent, w as emitEvent, x as normalizeAddress } from "./getVerifiedCredentialForWalletAccount-DLtDL1Gl.esm.js";
4
- import { n as refreshAuth, t as NotWaasWalletAccountError } from "./NotWaasWalletAccountError-DVIcEgHJ.esm.js";
5
- import { n as getMfaMethods, r as consumeMfaToken, t as isMfaRequiredForAction } from "./isMfaRequiredForAction-CPTFDCJp.esm.js";
1
+ import { A as NONCE_POOL_SIZE, D as randomString, E as ValueMustBeDefinedError, F as getCore, I as name, L as version, M as setDefaultClient, O as CLIENT_SDK_NAME, P as BaseError, S as getElevatedAccessToken, T as assertDefined, _ as MfaRateLimitedError, a as DYNAMIC_ICONIC_SPRITE_URL, b as InvalidExternalAuthError, c as CHAINS_INFO_MAP, d as UnauthorizedError, g as SandboxMaximumThresholdReachedError, h as getNonce, j as getDefaultClient, l as fetchAndStoreNonces, o as SDK_API_CORE_VERSION, s as getChainFromVerifiedCredentialChain, t as InvalidParamError, u as createApiClient, v as MfaInvalidOtpError, w as isCookieEnabled, x as APIError, y as LinkCredentialError } from "./InvalidParamError-C8bqZx25.esm.js";
2
+ import { A as getBuffer, C as CannotTrackError, D as INITIALIZE_STORAGE_SYNC_TRACKER_KEY, E as GENERATE_SESSION_KEYS_TRACKER_KEY, F as createLocalStorageAdapter, I as subscribeWithSelector, L as isEqualShallow, M as createStorageKeySchema, N as createStorage, O as REFRESH_USER_STATE_FROM_COOKIE_TRACKER_KEY, T as FETCH_PROJECT_SETTINGS_TRACKER_KEY, _ as NoNetworkProvidersError, a as updateWalletProviderKeysForVerifiedCredentials, b as createLogger, c as createSignInMessageStatement, d as createVisit, f as hasExtension, g as WalletAlreadyLinkedToAnotherUserError, h as isCaptchaRequired, i as getNetworksData, j as generateSessionKeys, k as isServerSideRendering, l as formatSignInMessage, m as consumeCaptchaToken, o as verifyMessageSignatureOwnership, p as setCaptchaToken, s as removeUnverifiedWalletAccount, t as getNetworkProviderFromNetworkId, u as setUnverifiedWalletAccounts, v as createRealtimeService, w as createDeferredPromise, x as createCrossTabBroadcast, y as createIndexedDBKeychainService } from "./getNetworkProviderFromNetworkId-n7VUDpn0.esm.js";
3
+ import { D as onceEvent, E as onEvent, O as setCookie, S as splitWalletProviderKey, T as offEvent, _ as getWalletAccounts, b as formatWalletAccountId, c as getWalletProviders, d as DYNAMIC_AUTH_COOKIE_NAME, f as getWalletProviderFromWalletAccount, g as NoWalletProviderFoundError, i as restoreUserSharesForAllWalletAccounts, l as checkAndRaiseWalletAccountsChangedEvent, n as getWalletProviderByKey, r as updateAuthFromVerifyResponse, t as getVerifiedCredentialForWalletAccount, u as emitWalletAccountsChangedEvent, w as emitEvent, x as normalizeAddress } from "./getVerifiedCredentialForWalletAccount-Cs7AcMKQ.esm.js";
4
+ import { n as refreshAuth, t as NotWaasWalletAccountError } from "./NotWaasWalletAccountError-C-_6uyUM.esm.js";
5
+ import { n as getMfaMethods, r as consumeMfaToken, t as isMfaRequiredForAction } from "./isMfaRequiredForAction-CM26tbT2.esm.js";
6
6
  import { assertPackageVersion } from "@dynamic-labs-sdk/assert-package-version";
7
- import { AuthModeEnum, ExchangeKeyEnum, JwtVerifiedCredentialFormatEnum, MFAAction, MfaBackupCodeAcknowledgement, ProviderEnum, WaasBackupOptionsEnum, WalletProviderEnum } from "@dynamic-labs/sdk-api-core";
7
+ import { AuthModeEnum, ExchangeKeyEnum, JwtVerifiedCredentialFormatEnum, MFAAction, MfaBackupCodeAcknowledgement, ProviderEnum, TokenScope, WaasBackupOptionsEnum, WalletProviderEnum } from "@dynamic-labs/sdk-api-core";
8
8
  import * as z from "zod/mini";
9
9
  import EventEmitter, { EventEmitter as EventEmitter$1 } from "eventemitter3";
10
10
  import { browserSupportsWebAuthn, startAuthentication, startRegistration } from "@simplewebauthn/browser";
@@ -203,6 +203,7 @@ const logout = async (client = getDefaultClient()) => {
203
203
  */
204
204
  if (isCookieEnabled(client)) setCookie(`${DYNAMIC_AUTH_COOKIE_NAME}=; Max-Age=-99999999; path=/; SameSite=Lax`);
205
205
  }
206
+ await core.keychain.removeKey("session");
206
207
  core.state.set({
207
208
  captchaToken: null,
208
209
  elevatedAccessTokens: [],
@@ -296,20 +297,6 @@ const setupCrossTabEventSync = (client) => {
296
297
  core.crossTabBroadcast.on("deviceRegistrationCompleted", handleCrossTabDeviceRegistrationCompleted);
297
298
  };
298
299
 
299
- //#endregion
300
- //#region src/modules/state/raiseStateEvents/raiseStateEvents.ts
301
- const raiseStateEvents = (client) => {
302
- getCore(client).state.subscribe((value, previous) => {
303
- Object.entries(stateChangeEvents).forEach(([key, event]) => {
304
- if (isEqualShallow(value[key], previous[key])) return;
305
- emitEvent({
306
- args: { [key]: value[key] },
307
- event
308
- }, client);
309
- });
310
- });
311
- };
312
-
313
300
  //#endregion
314
301
  //#region src/modules/wallets/unverifiedWalletAccounts/schema.ts
315
302
  const unverifiedWalletAccountSchema = z.object({
@@ -362,6 +349,87 @@ const sessionStorageKeySchema = createStorageKeySchema({
362
349
  })
363
350
  });
364
351
 
352
+ //#endregion
353
+ //#region src/modules/keychainMigration/migrateSessionKeyToKeychain/KeyMigrationError.ts
354
+ var KeyMigrationError = class extends BaseError {
355
+ constructor(expectedPublicKey, importedPublicKey) {
356
+ super({
357
+ cause: null,
358
+ code: "key_migration_public_key_mismatch",
359
+ docsUrl: null,
360
+ name: "KeyMigrationError",
361
+ shortMessage: `Public key mismatch after import: expected "${expectedPublicKey}", got "${importedPublicKey}"`
362
+ });
363
+ }
364
+ };
365
+
366
+ //#endregion
367
+ //#region src/modules/keychainMigration/migrateSessionKeyToKeychain/migrateSessionKeyToKeychain.ts
368
+ /**
369
+ * Migrates legacy session keys from the hydrated state into the IndexedDB keychain
370
+ * as non-extractable CryptoKey objects.
371
+ *
372
+ * Must run after hydrateStateWithStorage so that state.sessionKeys already holds
373
+ * the legacy base64 blob (or the new public key hex if already migrated).
374
+ *
375
+ * Idempotent: skips if the keychain already has a `session` key.
376
+ * Throws on failure — callers should handle errors (e.g. .catch(() => logout(client))).
377
+ */
378
+ const migrateSessionKeyToKeychain = async ({ keychain, logger, state, storage }) => {
379
+ if (isServerSideRendering()) return;
380
+ logger.debug("[migrateSessionKeyToKeychain] Checking for existing session key in keychain");
381
+ if (await keychain.hasKey("session")) {
382
+ logger.debug("[migrateSessionKeyToKeychain] Session key already exists in keychain, skipping migration");
383
+ return;
384
+ }
385
+ const encodedSessionKeys = state.get().sessionKeys;
386
+ if (!encodedSessionKeys) {
387
+ logger.debug("[migrateSessionKeyToKeychain] No session keys in state, nothing to migrate");
388
+ return;
389
+ }
390
+ let blob;
391
+ try {
392
+ blob = JSON.parse(getBuffer().from(encodedSessionKeys, "base64").toString());
393
+ } catch {
394
+ logger.debug("[migrateSessionKeyToKeychain] Session keys are not a legacy blob, skipping migration");
395
+ return;
396
+ }
397
+ const { privateKeyJwk, publicKey } = blob;
398
+ if (!privateKeyJwk || !publicKey) {
399
+ logger.debug("[migrateSessionKeyToKeychain] Legacy blob missing privateKeyJwk or publicKey, skipping migration");
400
+ return;
401
+ }
402
+ logger.debug("[migrateSessionKeyToKeychain] Found legacy session key, importing into keychain", { expectedPublicKey: publicKey });
403
+ const importedPublicKey = await keychain.importKey("session", privateKeyJwk);
404
+ logger.debug("[migrateSessionKeyToKeychain] Key imported", {
405
+ expectedPublicKey: publicKey,
406
+ importedPublicKey
407
+ });
408
+ if (importedPublicKey !== publicKey) throw new KeyMigrationError(publicKey, importedPublicKey);
409
+ logger.debug("[migrateSessionKeyToKeychain] Public key validated, updating state and storage");
410
+ state.set({ sessionKeys: importedPublicKey });
411
+ const currentSession = await storage.getItem(sessionStorageKeySchema);
412
+ if (currentSession) await storage.setItem(sessionStorageKeySchema, {
413
+ ...currentSession,
414
+ sessionKeys: importedPublicKey
415
+ });
416
+ logger.debug("[migrateSessionKeyToKeychain] Migration complete");
417
+ };
418
+
419
+ //#endregion
420
+ //#region src/modules/state/raiseStateEvents/raiseStateEvents.ts
421
+ const raiseStateEvents = (client) => {
422
+ getCore(client).state.subscribe((value, previous) => {
423
+ Object.entries(stateChangeEvents).forEach(([key, event]) => {
424
+ if (isEqualShallow(value[key], previous[key])) return;
425
+ emitEvent({
426
+ args: { [key]: value[key] },
427
+ event
428
+ }, client);
429
+ });
430
+ });
431
+ };
432
+
365
433
  //#endregion
366
434
  //#region src/modules/storageSync/hydrateStateWithStorage/hydrateStateWithStorage.ts
367
435
  const hydrateStateWithStorage = async (client) => {
@@ -477,6 +545,14 @@ const initializeClient = async (client = getDefaultClient()) => {
477
545
  setupCrossTabEventSync(client);
478
546
  const initializeStorageSyncPromise = initializeStorageSync(client);
479
547
  const fetchProjectSettingsPromise = initializeStorageSyncPromise.then(async () => {
548
+ await migrateSessionKeyToKeychain({
549
+ keychain: core.keychain,
550
+ logger: core.logger,
551
+ state: core.state,
552
+ storage: core.storage
553
+ }).catch(() => logout(client));
554
+ if (core.state.get().sessionKeys && !await core.keychain.hasKey("session")) await logout(client);
555
+ }).then(async () => {
480
556
  if (!core.state.get().projectSettings) await fetchProjectSettings(client);
481
557
  });
482
558
  fetchProjectSettingsPromise.then(() => prefetchNoncesIfNeeded(client)).catch((error) => {
@@ -625,6 +701,59 @@ const createWebFetch = () => {
625
701
  return window.fetch.bind(window);
626
702
  };
627
703
 
704
+ //#endregion
705
+ //#region src/services/instrumentation/constants.ts
706
+ const DEFAULT_PII_FIELDS = [
707
+ "password",
708
+ "token",
709
+ "secret",
710
+ "privateKey",
711
+ "mnemonic",
712
+ "seed",
713
+ "email",
714
+ "phone",
715
+ "ssn",
716
+ "address",
717
+ "authorization"
718
+ ];
719
+
720
+ //#endregion
721
+ //#region src/services/instrumentation/createInstrumentation/createInstrumentation.ts
722
+ const buildPiiFields = (customFields = []) => {
723
+ const merged = [...DEFAULT_PII_FIELDS, ...customFields];
724
+ return [...new Set(merged)];
725
+ };
726
+ /**
727
+ * Creates the instrumentation service that gates event emission behind an
728
+ * enabled flag and delegates to a pluggable transport.
729
+ *
730
+ * The transport is intentionally optional at creation time — it is wired in
731
+ * later via setTransport so the SDK can initialise without one. Events logged
732
+ * before a transport is set are simply dropped.
733
+ *
734
+ * Custom piiFields are merged with and deduplicated against the defaults so
735
+ * callers only need to list additional fields, not replicate the baseline.
736
+ */
737
+ const createInstrumentation = ({ config: inputConfig } = {}) => {
738
+ let transport;
739
+ const config = {
740
+ enabled: inputConfig?.enabled ?? true,
741
+ piiFields: buildPiiFields(inputConfig?.piiFields)
742
+ };
743
+ return {
744
+ config,
745
+ log: (event) => {
746
+ if (config.enabled) transport?.log(event);
747
+ },
748
+ setEnabled: (value) => {
749
+ config.enabled = value;
750
+ },
751
+ setTransport: (t) => {
752
+ transport = t;
753
+ }
754
+ };
755
+ };
756
+
628
757
  //#endregion
629
758
  //#region src/services/navigate/createNavigationHandler/createNavigationHandler.ts
630
759
  /**
@@ -840,9 +969,13 @@ const createCore = (config) => {
840
969
  const debouncedMutex = createDebouncedMutex();
841
970
  const eventEmitter = createEventEmitter();
842
971
  const initTrack = createAsyncTrack();
972
+ const sdkSessionId = randomString({ length: 32 });
973
+ const instrumentation = createInstrumentation({ config: config.instrumentation });
843
974
  const runtimeServices = createRuntimeServices();
844
975
  const passkey = config.coreConfig?.passkey ?? createWebPasskeyService();
976
+ const realtime = config.coreConfig?.realtime ?? createRealtimeService();
845
977
  const deviceSigner = config.coreConfig?.deviceSigner;
978
+ const keychain = config.coreConfig?.keychain ?? createIndexedDBKeychainService({ dbName: `dynamic_${config.environmentId}_keychain` });
846
979
  return {
847
980
  apiBaseUrl,
848
981
  crossTabBroadcast: config.coreConfig?.crossTabBroadcast ?? createCrossTabBroadcast({ channelName: `dynamic_${config.environmentId}_broadcast` }),
@@ -854,6 +987,8 @@ const createCore = (config) => {
854
987
  fetch,
855
988
  getApiHeaders: config.coreConfig?.getApiHeaders ?? (() => ({})),
856
989
  initTrack,
990
+ instrumentation,
991
+ keychain,
857
992
  logger,
858
993
  metadata: {
859
994
  ...config.metadata,
@@ -862,7 +997,9 @@ const createCore = (config) => {
862
997
  navigate,
863
998
  openDeeplink,
864
999
  passkey,
1000
+ realtime,
865
1001
  runtimeServices,
1002
+ sdkSessionId,
866
1003
  state,
867
1004
  storage,
868
1005
  transformers: config.transformers,
@@ -1285,47 +1422,6 @@ const signInWithExternalJwt = async ({ externalJwt, sessionPublicKey } = {}, cli
1285
1422
  return response;
1286
1423
  };
1287
1424
 
1288
- //#endregion
1289
- //#region src/modules/auth/getElevatedAccessToken/getElevatedAccessToken.ts
1290
- /**
1291
- * Gets an elevated access token by scope.
1292
- *
1293
- * This function retrieves an elevated access token that contains the specified scope.
1294
- * Expired tokens are automatically filtered out.
1295
- *
1296
- * If the token has `singleUse: true`, it will be automatically
1297
- * consumed (removed from state) after retrieval. Otherwise, it remains in state
1298
- * for future use.
1299
- *
1300
- * @param params - The parameters object.
1301
- * @param params.scope - The scope to match (e.g., 'wallet:export').
1302
- * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
1303
- * @returns The elevated access token if found and not expired, or undefined if not found or expired.
1304
- *
1305
- * @example
1306
- * ```typescript
1307
- * const token = getElevatedAccessToken({ scope: 'wallet:export' });
1308
- * if (token) {
1309
- * // Use the token
1310
- * // Token is automatically consumed if singleUse: true
1311
- * }
1312
- * ```
1313
- */
1314
- const getElevatedAccessToken = ({ scope }, client = getDefaultClient()) => {
1315
- const core = getCore(client);
1316
- const now = /* @__PURE__ */ new Date();
1317
- const elevatedAccessTokens = core.state.get().elevatedAccessTokens || [];
1318
- const validTokens = elevatedAccessTokens.filter((token$1) => !token$1.expiresAt || token$1.expiresAt > now);
1319
- if (validTokens.length !== elevatedAccessTokens.length) core.state.set({ elevatedAccessTokens: validTokens });
1320
- const token = validTokens.find((token$1) => token$1.scopes.includes(scope));
1321
- if (!token) return;
1322
- if (token.singleUse) {
1323
- const updatedTokens = validTokens.filter((t) => t !== token);
1324
- core.state.set({ elevatedAccessTokens: updatedTokens });
1325
- }
1326
- return token.token;
1327
- };
1328
-
1329
1425
  //#endregion
1330
1426
  //#region src/modules/auth/passkeys/deletePasskey/deletePasskey.ts
1331
1427
  /**
@@ -1337,7 +1433,10 @@ const getElevatedAccessToken = ({ scope }, client = getDefaultClient()) => {
1337
1433
  */
1338
1434
  const deletePasskey = async ({ passkeyId }, client = getDefaultClient()) => {
1339
1435
  const core = getCore(client);
1340
- await createApiClient({ includeMfaToken: true }, client).deletePasskey({
1436
+ await createApiClient({
1437
+ elevatedAccessTokenScope: TokenScope.Credentialunlink,
1438
+ includeMfaToken: true
1439
+ }, client).deletePasskey({
1341
1440
  deleteUserPasskeyRequest: { passkeyId },
1342
1441
  environmentId: core.environmentId
1343
1442
  });
@@ -1370,7 +1469,7 @@ const getPasskeyRegistrationOptions = async (client) => {
1370
1469
  //#region src/modules/auth/passkeys/serverRegisterPasskey/serverRegisterPasskey.ts
1371
1470
  const serverRegisterPasskey = async ({ registration, createMfaToken }, client) => {
1372
1471
  const core = getCore(client);
1373
- return await createApiClient({}, client).registerPasskey({
1472
+ return await createApiClient({ elevatedAccessTokenScope: TokenScope.Credentiallink }, client).registerPasskey({
1374
1473
  environmentId: core.environmentId,
1375
1474
  passkeyRegisterRequest: {
1376
1475
  ...registration,
@@ -3039,23 +3138,27 @@ const createNewMfaRecoveryCodes = async (client = getDefaultClient()) => {
3039
3138
  /**
3040
3139
  * Deletes a specific MFA device from the user's account.
3041
3140
  *
3042
- * This function removes a multi-factor authentication device such as
3043
- * a TOTP authenticator from the user's registered devices.
3141
+ * When an elevated access token for `credential:unlink` is available,
3142
+ * it is sent via the `x-dyn-elevated-access-token` header and the
3143
+ * MFA auth token is not required. Otherwise, `mfaAuthToken` must be
3144
+ * provided for backward compatibility with the legacy MFA flow.
3044
3145
  *
3045
3146
  * @param params.deviceId - The unique identifier of the MFA device to delete.
3046
- * @param params.mfaAuthToken - The MFA authentication token required for device deletion.
3147
+ * @param params.mfaAuthToken - The MFA authentication token. Optional when using elevated access tokens.
3047
3148
  * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
3048
3149
  * @returns A promise that resolves when the MFA device is successfully deleted.
3049
3150
  */
3050
3151
  const deleteMfaDevice = async ({ deviceId, mfaAuthToken }, client = getDefaultClient()) => {
3051
3152
  const core = getCore(client);
3052
- const apiClient = createApiClient({}, client);
3053
3153
  assertDefined(deviceId, "deviceId is required");
3054
- assertDefined(mfaAuthToken, "mfaAuthToken is required");
3055
- return apiClient.deleteMfaDevice({
3154
+ if (!getElevatedAccessToken({
3155
+ consume: false,
3156
+ scope: TokenScope.Credentialunlink
3157
+ }, client)) assertDefined(mfaAuthToken, "mfaAuthToken is required");
3158
+ return createApiClient({ elevatedAccessTokenScope: TokenScope.Credentialunlink }, client).deleteMfaDevice({
3056
3159
  environmentId: core.environmentId,
3057
3160
  mfaDeviceId: deviceId,
3058
- xMfaAuthToken: mfaAuthToken
3161
+ xMfaAuthToken: mfaAuthToken ?? ""
3059
3162
  });
3060
3163
  };
3061
3164
 
@@ -3142,7 +3245,7 @@ const isUserMissingMfaAuth = (client = getDefaultClient()) => {
3142
3245
  */
3143
3246
  const registerTotpMfaDevice = async (client = getDefaultClient()) => {
3144
3247
  const core = getCore(client);
3145
- return createApiClient({}, client).registerTotpMfaDevice({ environmentId: core.environmentId });
3248
+ return createApiClient({ elevatedAccessTokenScope: TokenScope.Credentiallink }, client).registerTotpMfaDevice({ environmentId: core.environmentId });
3146
3249
  };
3147
3250
 
3148
3251
  //#endregion