@dynamic-labs/waas 5.9.6 → 5.11.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,26 @@
1
1
 
2
+ ## [5.11.0](https://github.com/dynamic-labs/dynamic-auth/compare/v5.10.0...v5.11.0) (2026-10-14)
3
+
4
+
5
+ ### Bug Fixes
6
+
7
+ * **react-native:** fall back to a TEE-backed key when StrongBox key generation fails on Android ([#12484](https://github.com/dynamic-labs/dynamic-auth/issues/12484)) ([6884ef1](https://github.com/dynamic-labs/dynamic-auth/commit/6884ef1665e4b18d1b8fdb54ee7cd06861b47fc9))
8
+ * support WaaS password overrides in WebView ([#12509](https://github.com/dynamic-labs/dynamic-auth/issues/12509)) ([fc67fcc](https://github.com/dynamic-labs/dynamic-auth/commit/fc67fccb99be7c0cc8df81a2513ccd3a04db9a61))
9
+
10
+ ## [5.10.0](https://github.com/dynamic-labs/dynamic-auth/compare/v5.9.6...v5.10.0) (2026-10-09)
11
+
12
+
13
+ ### Features
14
+
15
+ * add lockWallets/lockWallet to re-lock password-encrypted WaaS wallets ([#12461](https://github.com/dynamic-labs/dynamic-auth/issues/12461)) ([090f544](https://github.com/dynamic-labs/dynamic-auth/commit/090f544150f4359bbfd9c0ffb4c450868adb6759))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **logger:** scope server error forwarding per instance ([#12477](https://github.com/dynamic-labs/dynamic-auth/issues/12477)) ([baa8c78](https://github.com/dynamic-labs/dynamic-auth/commit/baa8c780f4ef3cc35d62c363e03e74412ece91b9))
21
+ * **waas:** fall back when crypto.randomUUID is unavailable ([#12435](https://github.com/dynamic-labs/dynamic-auth/issues/12435)) ([5756f53](https://github.com/dynamic-labs/dynamic-auth/commit/5756f53423bd8316bce97e46ce38fc923fd5d574))
22
+ * **waas:** include every wallet in password update batches ([#12462](https://github.com/dynamic-labs/dynamic-auth/issues/12462)) ([80218f7](https://github.com/dynamic-labs/dynamic-auth/commit/80218f702dadfee9673cec4037889449bcd5ceb6))
23
+
2
24
  ### [5.9.6](https://github.com/dynamic-labs/dynamic-auth/compare/v5.9.5...v5.9.6) (2026-10-06)
3
25
 
4
26
  ### [5.9.5](https://github.com/dynamic-labs/dynamic-auth/compare/v5.9.4...v5.9.5) (2026-10-06)
package/package.cjs CHANGED
@@ -3,6 +3,6 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "5.9.6";
6
+ var version = "5.11.0";
7
7
 
8
8
  exports.version = version;
package/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  'use client'
2
- var version = "5.9.6";
2
+ var version = "5.11.0";
3
3
 
4
4
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/waas",
3
- "version": "5.9.6",
3
+ "version": "5.11.0",
4
4
  "type": "module",
5
5
  "author": "Dynamic Labs, Inc.",
6
6
  "license": "MIT",
@@ -16,20 +16,20 @@
16
16
  "./package.json": "./package.json"
17
17
  },
18
18
  "dependencies": {
19
- "@dynamic-labs-sdk/client": "1.37.0",
20
- "@dynamic-labs/assert-package-version": "5.9.6",
21
- "@dynamic-labs/sdk-api-core": "0.70.0",
22
- "@dynamic-labs-wallet/browser-wallet-client": "1.1.27",
23
- "@dynamic-labs-wallet/core": "1.1.27",
19
+ "@dynamic-labs-sdk/client": "1.39.1",
20
+ "@dynamic-labs/assert-package-version": "5.11.0",
21
+ "@dynamic-labs/sdk-api-core": "0.92.0",
22
+ "@dynamic-labs-wallet/browser-wallet-client": "1.1.33",
23
+ "@dynamic-labs-wallet/core": "1.1.33",
24
24
  "@dynamic-labs-wallet/forward-mpc-client": "1.0.2",
25
25
  "zod": "4.0.5",
26
- "@dynamic-labs/ethereum-core": "5.9.6",
27
- "@dynamic-labs/logger": "5.9.6",
28
- "@dynamic-labs/solana-core": "5.9.6",
29
- "@dynamic-labs/sui-core": "5.9.6",
30
- "@dynamic-labs/utils": "5.9.6",
31
- "@dynamic-labs/wallet-book": "5.9.6",
32
- "@dynamic-labs/wallet-connector-core": "5.9.6"
26
+ "@dynamic-labs/ethereum-core": "5.11.0",
27
+ "@dynamic-labs/logger": "5.11.0",
28
+ "@dynamic-labs/solana-core": "5.11.0",
29
+ "@dynamic-labs/sui-core": "5.11.0",
30
+ "@dynamic-labs/utils": "5.11.0",
31
+ "@dynamic-labs/wallet-book": "5.11.0",
32
+ "@dynamic-labs/wallet-connector-core": "5.11.0"
33
33
  },
34
34
  "peerDependencies": {}
35
35
  }
@@ -11,11 +11,23 @@ var _package = require('../package.cjs');
11
11
  var constants = require('../utils/constants.cjs');
12
12
  var createWaasClientSecureStorage = require('../utils/createWaasClientSecureStorage.cjs');
13
13
  var instrumentation = require('../utils/instrumentation.cjs');
14
+ var generateUUID = require('../utils/generateUUID.cjs');
14
15
  var tokenHasPendingAuthScope = require('../utils/tokenHasPendingAuthScope.cjs');
15
16
 
16
17
  // Fallback error code used when a thrown value carries no code, or when
17
18
  // formatting the error itself fails.
18
19
  const UNKNOWN_ERROR_CODE = 'unknown';
20
+ const PASSWORD_UPDATE_ACTIVATED_STATUS = 'activated';
21
+ const PASSWORD_UPDATE_NOT_ACTIVATED_CODE = 'password_update_not_activated';
22
+ // The server activates a password-update batch on the last wallet's check-in. Unless a
23
+ // wallet reports 'activated', the new password never took effect. A missing status is
24
+ // not proof of activation, so it fails closed too.
25
+ const assertPasswordUpdateActivated = (results) => {
26
+ const isActivated = results.some((result) => (result === null || result === void 0 ? void 0 : result.passwordUpdateStatus) === PASSWORD_UPDATE_ACTIVATED_STATUS);
27
+ if (!isActivated) {
28
+ throw new utils.DynamicError('Password update was not applied to all wallets. Please try again.', PASSWORD_UPDATE_NOT_ACTIVATED_CODE);
29
+ }
30
+ };
19
31
  // This class is common across all waas connectors
20
32
  class WaasExportHandler {
21
33
  constructor() {
@@ -717,7 +729,7 @@ const withDynamicWaas = (BaseClass) => {
717
729
  });
718
730
  }
719
731
  updatePassword(_a) {
720
- return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress, existingPassword, newPassword, }) {
732
+ return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress, existingPassword, newPassword, passwordOverrides, }) {
721
733
  if (!accountAddress) {
722
734
  throw new utils.DynamicError('Account address is required', 'account_address_is_required');
723
735
  }
@@ -729,22 +741,16 @@ const withDynamicWaas = (BaseClass) => {
729
741
  if (!this.getSignedSessionId) {
730
742
  throw new utils.DynamicError('Signed session ID is required', 'signed_session_id_is_required');
731
743
  }
744
+ // The server only activates the batch once every wallet of the user has
745
+ // checked in, so wallets that are not password-encrypted yet are included too.
732
746
  const wallets = yield walletClient.getAllWallets();
733
- const encryptedWallets = wallets.filter((w) => { var _a; return (_a = w.clientKeySharesBackupInfo) === null || _a === void 0 ? void 0 : _a.passwordEncrypted; });
734
- const passwordUpdateBatchId = crypto.randomUUID();
735
- yield Promise.all(encryptedWallets.map((wallet) => _tslib.__awaiter(this, void 0, void 0, function* () {
747
+ const passwordUpdateBatchId = generateUUID.generateUUID();
748
+ const results = yield Promise.all(wallets.map((wallet) => _tslib.__awaiter(this, void 0, void 0, function* () {
736
749
  var _b, _c;
737
750
  const signedSessionId = yield this.getSignedSessionId();
738
- yield walletClient.updatePassword({
739
- accountAddress: wallet.accountAddress,
740
- authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
741
- existingPassword: resolvedExistingPassword,
742
- newPassword,
743
- passwordUpdateBatchId,
744
- sessionPublicKey: yield ((_c = this.getSessionPublicKey) === null || _c === void 0 ? void 0 : _c.call(this)),
745
- signedSessionId,
746
- });
751
+ return walletClient.updatePassword(Object.assign(Object.assign({ accountAddress: wallet.accountAddress, authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this), existingPassword: resolvedExistingPassword, newPassword }, (passwordOverrides ? { passwordOverrides } : {})), { passwordUpdateBatchId, sessionPublicKey: yield ((_c = this.getSessionPublicKey) === null || _c === void 0 ? void 0 : _c.call(this)), signedSessionId }));
747
752
  })));
753
+ assertPasswordUpdateActivated(results);
748
754
  });
749
755
  }
750
756
  setPassword(_a) {
@@ -757,11 +763,11 @@ const withDynamicWaas = (BaseClass) => {
757
763
  throw new utils.DynamicError('Signed session ID is required', 'signed_session_id_is_required');
758
764
  }
759
765
  const wallets = yield walletClient.getAllWallets();
760
- const passwordUpdateBatchId = crypto.randomUUID();
761
- yield Promise.all(wallets.map((wallet) => _tslib.__awaiter(this, void 0, void 0, function* () {
766
+ const passwordUpdateBatchId = generateUUID.generateUUID();
767
+ const results = yield Promise.all(wallets.map((wallet) => _tslib.__awaiter(this, void 0, void 0, function* () {
762
768
  var _b, _c;
763
769
  const signedSessionId = yield this.getSignedSessionId();
764
- yield walletClient.setPassword({
770
+ return walletClient.setPassword({
765
771
  accountAddress: wallet.accountAddress,
766
772
  authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
767
773
  newPassword,
@@ -770,6 +776,7 @@ const withDynamicWaas = (BaseClass) => {
770
776
  signedSessionId,
771
777
  });
772
778
  })));
779
+ assertPasswordUpdateActivated(results);
773
780
  });
774
781
  }
775
782
  signRawMessage(_a) {
@@ -825,6 +832,31 @@ const withDynamicWaas = (BaseClass) => {
825
832
  });
826
833
  });
827
834
  }
835
+ /**
836
+ * Re-locks every password-encrypted wallet: the iframe clears its stored
837
+ * decrypted client key shares, so the next wallet operation prompts for
838
+ * the wallet password again.
839
+ */
840
+ lockWallets() {
841
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
842
+ var _a;
843
+ const walletClient = yield this.getWaasWalletClient();
844
+ return walletClient.lockWallets({ authToken: (_a = this.getAuthToken) === null || _a === void 0 ? void 0 : _a.call(this) });
845
+ });
846
+ }
847
+ /**
848
+ * Same re-lock semantics as `lockWallets`, scoped to a single wallet.
849
+ */
850
+ lockWallet(_a) {
851
+ return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress }) {
852
+ var _b;
853
+ const walletClient = yield this.getWaasWalletClient();
854
+ return walletClient.lockWallets({
855
+ accountAddress,
856
+ authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
857
+ });
858
+ });
859
+ }
828
860
  getWalletRecoveryState(_a) {
829
861
  return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress, }) {
830
862
  var _b, _c;
@@ -191,7 +191,7 @@ export declare const withDynamicWaas: <T extends abstract new (...args: any[]) =
191
191
  accountAddress: string;
192
192
  password?: string;
193
193
  }): Promise<void>;
194
- updatePassword({ accountAddress, existingPassword, newPassword, }: UpdatePasswordParams): Promise<void>;
194
+ updatePassword({ accountAddress, existingPassword, newPassword, passwordOverrides, }: UpdatePasswordParams): Promise<void>;
195
195
  setPassword({ accountAddress, newPassword, }: {
196
196
  accountAddress: string;
197
197
  newPassword: string;
@@ -206,6 +206,18 @@ export declare const withDynamicWaas: <T extends abstract new (...args: any[]) =
206
206
  accountAddress: string;
207
207
  password?: string;
208
208
  }): Promise<import("@dynamic-labs-wallet/browser-wallet-client").GetWalletResponse>;
209
+ /**
210
+ * Re-locks every password-encrypted wallet: the iframe clears its stored
211
+ * decrypted client key shares, so the next wallet operation prompts for
212
+ * the wallet password again.
213
+ */
214
+ lockWallets(): Promise<void>;
215
+ /**
216
+ * Same re-lock semantics as `lockWallets`, scoped to a single wallet.
217
+ */
218
+ lockWallet({ accountAddress }: {
219
+ accountAddress: string;
220
+ }): Promise<void>;
209
221
  getWalletRecoveryState({ accountAddress, }: {
210
222
  accountAddress: string;
211
223
  }): Promise<import("@dynamic-labs-wallet/browser-wallet-client").WalletRecoveryState>;
@@ -7,11 +7,23 @@ import { version } from '../package.js';
7
7
  import { DEFAULT_BASE_API_URL, DEFAULT_BASE_MPC_RELAY_API_URL } from '../utils/constants.js';
8
8
  import { createWaasClientSecureStorage } from '../utils/createWaasClientSecureStorage.js';
9
9
  import { InstrumentationTimer } from '../utils/instrumentation.js';
10
+ import { generateUUID } from '../utils/generateUUID.js';
10
11
  import { tokenHasPendingAuthScope } from '../utils/tokenHasPendingAuthScope.js';
11
12
 
12
13
  // Fallback error code used when a thrown value carries no code, or when
13
14
  // formatting the error itself fails.
14
15
  const UNKNOWN_ERROR_CODE = 'unknown';
16
+ const PASSWORD_UPDATE_ACTIVATED_STATUS = 'activated';
17
+ const PASSWORD_UPDATE_NOT_ACTIVATED_CODE = 'password_update_not_activated';
18
+ // The server activates a password-update batch on the last wallet's check-in. Unless a
19
+ // wallet reports 'activated', the new password never took effect. A missing status is
20
+ // not proof of activation, so it fails closed too.
21
+ const assertPasswordUpdateActivated = (results) => {
22
+ const isActivated = results.some((result) => (result === null || result === void 0 ? void 0 : result.passwordUpdateStatus) === PASSWORD_UPDATE_ACTIVATED_STATUS);
23
+ if (!isActivated) {
24
+ throw new DynamicError('Password update was not applied to all wallets. Please try again.', PASSWORD_UPDATE_NOT_ACTIVATED_CODE);
25
+ }
26
+ };
15
27
  // This class is common across all waas connectors
16
28
  class WaasExportHandler {
17
29
  constructor() {
@@ -713,7 +725,7 @@ const withDynamicWaas = (BaseClass) => {
713
725
  });
714
726
  }
715
727
  updatePassword(_a) {
716
- return __awaiter(this, arguments, void 0, function* ({ accountAddress, existingPassword, newPassword, }) {
728
+ return __awaiter(this, arguments, void 0, function* ({ accountAddress, existingPassword, newPassword, passwordOverrides, }) {
717
729
  if (!accountAddress) {
718
730
  throw new DynamicError('Account address is required', 'account_address_is_required');
719
731
  }
@@ -725,22 +737,16 @@ const withDynamicWaas = (BaseClass) => {
725
737
  if (!this.getSignedSessionId) {
726
738
  throw new DynamicError('Signed session ID is required', 'signed_session_id_is_required');
727
739
  }
740
+ // The server only activates the batch once every wallet of the user has
741
+ // checked in, so wallets that are not password-encrypted yet are included too.
728
742
  const wallets = yield walletClient.getAllWallets();
729
- const encryptedWallets = wallets.filter((w) => { var _a; return (_a = w.clientKeySharesBackupInfo) === null || _a === void 0 ? void 0 : _a.passwordEncrypted; });
730
- const passwordUpdateBatchId = crypto.randomUUID();
731
- yield Promise.all(encryptedWallets.map((wallet) => __awaiter(this, void 0, void 0, function* () {
743
+ const passwordUpdateBatchId = generateUUID();
744
+ const results = yield Promise.all(wallets.map((wallet) => __awaiter(this, void 0, void 0, function* () {
732
745
  var _b, _c;
733
746
  const signedSessionId = yield this.getSignedSessionId();
734
- yield walletClient.updatePassword({
735
- accountAddress: wallet.accountAddress,
736
- authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
737
- existingPassword: resolvedExistingPassword,
738
- newPassword,
739
- passwordUpdateBatchId,
740
- sessionPublicKey: yield ((_c = this.getSessionPublicKey) === null || _c === void 0 ? void 0 : _c.call(this)),
741
- signedSessionId,
742
- });
747
+ return walletClient.updatePassword(Object.assign(Object.assign({ accountAddress: wallet.accountAddress, authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this), existingPassword: resolvedExistingPassword, newPassword }, (passwordOverrides ? { passwordOverrides } : {})), { passwordUpdateBatchId, sessionPublicKey: yield ((_c = this.getSessionPublicKey) === null || _c === void 0 ? void 0 : _c.call(this)), signedSessionId }));
743
748
  })));
749
+ assertPasswordUpdateActivated(results);
744
750
  });
745
751
  }
746
752
  setPassword(_a) {
@@ -753,11 +759,11 @@ const withDynamicWaas = (BaseClass) => {
753
759
  throw new DynamicError('Signed session ID is required', 'signed_session_id_is_required');
754
760
  }
755
761
  const wallets = yield walletClient.getAllWallets();
756
- const passwordUpdateBatchId = crypto.randomUUID();
757
- yield Promise.all(wallets.map((wallet) => __awaiter(this, void 0, void 0, function* () {
762
+ const passwordUpdateBatchId = generateUUID();
763
+ const results = yield Promise.all(wallets.map((wallet) => __awaiter(this, void 0, void 0, function* () {
758
764
  var _b, _c;
759
765
  const signedSessionId = yield this.getSignedSessionId();
760
- yield walletClient.setPassword({
766
+ return walletClient.setPassword({
761
767
  accountAddress: wallet.accountAddress,
762
768
  authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
763
769
  newPassword,
@@ -766,6 +772,7 @@ const withDynamicWaas = (BaseClass) => {
766
772
  signedSessionId,
767
773
  });
768
774
  })));
775
+ assertPasswordUpdateActivated(results);
769
776
  });
770
777
  }
771
778
  signRawMessage(_a) {
@@ -821,6 +828,31 @@ const withDynamicWaas = (BaseClass) => {
821
828
  });
822
829
  });
823
830
  }
831
+ /**
832
+ * Re-locks every password-encrypted wallet: the iframe clears its stored
833
+ * decrypted client key shares, so the next wallet operation prompts for
834
+ * the wallet password again.
835
+ */
836
+ lockWallets() {
837
+ return __awaiter(this, void 0, void 0, function* () {
838
+ var _a;
839
+ const walletClient = yield this.getWaasWalletClient();
840
+ return walletClient.lockWallets({ authToken: (_a = this.getAuthToken) === null || _a === void 0 ? void 0 : _a.call(this) });
841
+ });
842
+ }
843
+ /**
844
+ * Same re-lock semantics as `lockWallets`, scoped to a single wallet.
845
+ */
846
+ lockWallet(_a) {
847
+ return __awaiter(this, arguments, void 0, function* ({ accountAddress }) {
848
+ var _b;
849
+ const walletClient = yield this.getWaasWalletClient();
850
+ return walletClient.lockWallets({
851
+ accountAddress,
852
+ authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
853
+ });
854
+ });
855
+ }
824
856
  getWalletRecoveryState(_a) {
825
857
  return __awaiter(this, arguments, void 0, function* ({ accountAddress, }) {
826
858
  var _b, _c;
@@ -0,0 +1,23 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ // crypto.randomUUID is unavailable on older webviews (< Chrome 92) and in
7
+ // non-secure contexts; fall back to a getRandomValues-based v4 UUID there.
8
+ const generateUUID = () => {
9
+ const cryptoProvider = globalThis.crypto;
10
+ if (typeof (cryptoProvider === null || cryptoProvider === void 0 ? void 0 : cryptoProvider.randomUUID) === 'function') {
11
+ return cryptoProvider.randomUUID();
12
+ }
13
+ if (typeof (cryptoProvider === null || cryptoProvider === void 0 ? void 0 : cryptoProvider.getRandomValues) !== 'function') {
14
+ throw new TypeError('Secure UUID generation is unavailable');
15
+ }
16
+ const bytes = cryptoProvider.getRandomValues(new Uint8Array(16));
17
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
18
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
19
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
20
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
21
+ };
22
+
23
+ exports.generateUUID = generateUUID;
@@ -0,0 +1 @@
1
+ export declare const generateUUID: () => string;
@@ -0,0 +1,19 @@
1
+ 'use client'
2
+ // crypto.randomUUID is unavailable on older webviews (< Chrome 92) and in
3
+ // non-secure contexts; fall back to a getRandomValues-based v4 UUID there.
4
+ const generateUUID = () => {
5
+ const cryptoProvider = globalThis.crypto;
6
+ if (typeof (cryptoProvider === null || cryptoProvider === void 0 ? void 0 : cryptoProvider.randomUUID) === 'function') {
7
+ return cryptoProvider.randomUUID();
8
+ }
9
+ if (typeof (cryptoProvider === null || cryptoProvider === void 0 ? void 0 : cryptoProvider.getRandomValues) !== 'function') {
10
+ throw new TypeError('Secure UUID generation is unavailable');
11
+ }
12
+ const bytes = cryptoProvider.getRandomValues(new Uint8Array(16));
13
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
14
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
15
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
16
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
17
+ };
18
+
19
+ export { generateUUID };