@dynamic-labs/waas 5.9.6 → 5.10.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 +14 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +11 -11
- package/src/DynamicWaasMixin.cjs +47 -7
- package/src/DynamicWaasMixin.d.ts +12 -0
- package/src/DynamicWaasMixin.js +47 -7
- package/utils/generateUUID.cjs +23 -0
- package/utils/generateUUID.d.ts +1 -0
- package/utils/generateUUID.js +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
|
|
2
|
+
## [5.10.0](https://github.com/dynamic-labs/dynamic-auth/compare/v5.9.6...v5.10.0) (2026-10-09)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* 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))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* **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))
|
|
13
|
+
* **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))
|
|
14
|
+
* **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))
|
|
15
|
+
|
|
2
16
|
### [5.9.6](https://github.com/dynamic-labs/dynamic-auth/compare/v5.9.5...v5.9.6) (2026-10-06)
|
|
3
17
|
|
|
4
18
|
### [5.9.5](https://github.com/dynamic-labs/dynamic-auth/compare/v5.9.4...v5.9.5) (2026-10-06)
|
package/package.cjs
CHANGED
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/waas",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Dynamic Labs, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,19 +17,19 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@dynamic-labs-sdk/client": "1.37.0",
|
|
20
|
-
"@dynamic-labs/assert-package-version": "5.
|
|
20
|
+
"@dynamic-labs/assert-package-version": "5.10.0",
|
|
21
21
|
"@dynamic-labs/sdk-api-core": "0.70.0",
|
|
22
|
-
"@dynamic-labs-wallet/browser-wallet-client": "1.1.
|
|
23
|
-
"@dynamic-labs-wallet/core": "1.1.
|
|
22
|
+
"@dynamic-labs-wallet/browser-wallet-client": "1.1.33",
|
|
23
|
+
"@dynamic-labs-wallet/core": "1.1.29",
|
|
24
24
|
"@dynamic-labs-wallet/forward-mpc-client": "1.0.2",
|
|
25
25
|
"zod": "4.0.5",
|
|
26
|
-
"@dynamic-labs/ethereum-core": "5.
|
|
27
|
-
"@dynamic-labs/logger": "5.
|
|
28
|
-
"@dynamic-labs/solana-core": "5.
|
|
29
|
-
"@dynamic-labs/sui-core": "5.
|
|
30
|
-
"@dynamic-labs/utils": "5.
|
|
31
|
-
"@dynamic-labs/wallet-book": "5.
|
|
32
|
-
"@dynamic-labs/wallet-connector-core": "5.
|
|
26
|
+
"@dynamic-labs/ethereum-core": "5.10.0",
|
|
27
|
+
"@dynamic-labs/logger": "5.10.0",
|
|
28
|
+
"@dynamic-labs/solana-core": "5.10.0",
|
|
29
|
+
"@dynamic-labs/sui-core": "5.10.0",
|
|
30
|
+
"@dynamic-labs/utils": "5.10.0",
|
|
31
|
+
"@dynamic-labs/wallet-book": "5.10.0",
|
|
32
|
+
"@dynamic-labs/wallet-connector-core": "5.10.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {}
|
|
35
35
|
}
|
package/src/DynamicWaasMixin.cjs
CHANGED
|
@@ -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() {
|
|
@@ -729,13 +741,14 @@ 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
|
|
734
|
-
const
|
|
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
|
-
|
|
751
|
+
return walletClient.updatePassword({
|
|
739
752
|
accountAddress: wallet.accountAddress,
|
|
740
753
|
authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
|
|
741
754
|
existingPassword: resolvedExistingPassword,
|
|
@@ -745,6 +758,7 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
745
758
|
signedSessionId,
|
|
746
759
|
});
|
|
747
760
|
})));
|
|
761
|
+
assertPasswordUpdateActivated(results);
|
|
748
762
|
});
|
|
749
763
|
}
|
|
750
764
|
setPassword(_a) {
|
|
@@ -757,11 +771,11 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
757
771
|
throw new utils.DynamicError('Signed session ID is required', 'signed_session_id_is_required');
|
|
758
772
|
}
|
|
759
773
|
const wallets = yield walletClient.getAllWallets();
|
|
760
|
-
const passwordUpdateBatchId =
|
|
761
|
-
yield Promise.all(wallets.map((wallet) => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
774
|
+
const passwordUpdateBatchId = generateUUID.generateUUID();
|
|
775
|
+
const results = yield Promise.all(wallets.map((wallet) => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
762
776
|
var _b, _c;
|
|
763
777
|
const signedSessionId = yield this.getSignedSessionId();
|
|
764
|
-
|
|
778
|
+
return walletClient.setPassword({
|
|
765
779
|
accountAddress: wallet.accountAddress,
|
|
766
780
|
authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
|
|
767
781
|
newPassword,
|
|
@@ -770,6 +784,7 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
770
784
|
signedSessionId,
|
|
771
785
|
});
|
|
772
786
|
})));
|
|
787
|
+
assertPasswordUpdateActivated(results);
|
|
773
788
|
});
|
|
774
789
|
}
|
|
775
790
|
signRawMessage(_a) {
|
|
@@ -825,6 +840,31 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
825
840
|
});
|
|
826
841
|
});
|
|
827
842
|
}
|
|
843
|
+
/**
|
|
844
|
+
* Re-locks every password-encrypted wallet: the iframe clears its stored
|
|
845
|
+
* decrypted client key shares, so the next wallet operation prompts for
|
|
846
|
+
* the wallet password again.
|
|
847
|
+
*/
|
|
848
|
+
lockWallets() {
|
|
849
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
850
|
+
var _a;
|
|
851
|
+
const walletClient = yield this.getWaasWalletClient();
|
|
852
|
+
return walletClient.lockWallets({ authToken: (_a = this.getAuthToken) === null || _a === void 0 ? void 0 : _a.call(this) });
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* Same re-lock semantics as `lockWallets`, scoped to a single wallet.
|
|
857
|
+
*/
|
|
858
|
+
lockWallet(_a) {
|
|
859
|
+
return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress }) {
|
|
860
|
+
var _b;
|
|
861
|
+
const walletClient = yield this.getWaasWalletClient();
|
|
862
|
+
return walletClient.lockWallets({
|
|
863
|
+
accountAddress,
|
|
864
|
+
authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
|
|
865
|
+
});
|
|
866
|
+
});
|
|
867
|
+
}
|
|
828
868
|
getWalletRecoveryState(_a) {
|
|
829
869
|
return _tslib.__awaiter(this, arguments, void 0, function* ({ accountAddress, }) {
|
|
830
870
|
var _b, _c;
|
|
@@ -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>;
|
package/src/DynamicWaasMixin.js
CHANGED
|
@@ -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() {
|
|
@@ -725,13 +737,14 @@ 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
|
|
730
|
-
const
|
|
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
|
-
|
|
747
|
+
return walletClient.updatePassword({
|
|
735
748
|
accountAddress: wallet.accountAddress,
|
|
736
749
|
authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
|
|
737
750
|
existingPassword: resolvedExistingPassword,
|
|
@@ -741,6 +754,7 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
741
754
|
signedSessionId,
|
|
742
755
|
});
|
|
743
756
|
})));
|
|
757
|
+
assertPasswordUpdateActivated(results);
|
|
744
758
|
});
|
|
745
759
|
}
|
|
746
760
|
setPassword(_a) {
|
|
@@ -753,11 +767,11 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
753
767
|
throw new DynamicError('Signed session ID is required', 'signed_session_id_is_required');
|
|
754
768
|
}
|
|
755
769
|
const wallets = yield walletClient.getAllWallets();
|
|
756
|
-
const passwordUpdateBatchId =
|
|
757
|
-
yield Promise.all(wallets.map((wallet) => __awaiter(this, void 0, void 0, function* () {
|
|
770
|
+
const passwordUpdateBatchId = generateUUID();
|
|
771
|
+
const results = yield Promise.all(wallets.map((wallet) => __awaiter(this, void 0, void 0, function* () {
|
|
758
772
|
var _b, _c;
|
|
759
773
|
const signedSessionId = yield this.getSignedSessionId();
|
|
760
|
-
|
|
774
|
+
return walletClient.setPassword({
|
|
761
775
|
accountAddress: wallet.accountAddress,
|
|
762
776
|
authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
|
|
763
777
|
newPassword,
|
|
@@ -766,6 +780,7 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
766
780
|
signedSessionId,
|
|
767
781
|
});
|
|
768
782
|
})));
|
|
783
|
+
assertPasswordUpdateActivated(results);
|
|
769
784
|
});
|
|
770
785
|
}
|
|
771
786
|
signRawMessage(_a) {
|
|
@@ -821,6 +836,31 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
821
836
|
});
|
|
822
837
|
});
|
|
823
838
|
}
|
|
839
|
+
/**
|
|
840
|
+
* Re-locks every password-encrypted wallet: the iframe clears its stored
|
|
841
|
+
* decrypted client key shares, so the next wallet operation prompts for
|
|
842
|
+
* the wallet password again.
|
|
843
|
+
*/
|
|
844
|
+
lockWallets() {
|
|
845
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
846
|
+
var _a;
|
|
847
|
+
const walletClient = yield this.getWaasWalletClient();
|
|
848
|
+
return walletClient.lockWallets({ authToken: (_a = this.getAuthToken) === null || _a === void 0 ? void 0 : _a.call(this) });
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Same re-lock semantics as `lockWallets`, scoped to a single wallet.
|
|
853
|
+
*/
|
|
854
|
+
lockWallet(_a) {
|
|
855
|
+
return __awaiter(this, arguments, void 0, function* ({ accountAddress }) {
|
|
856
|
+
var _b;
|
|
857
|
+
const walletClient = yield this.getWaasWalletClient();
|
|
858
|
+
return walletClient.lockWallets({
|
|
859
|
+
accountAddress,
|
|
860
|
+
authToken: (_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this),
|
|
861
|
+
});
|
|
862
|
+
});
|
|
863
|
+
}
|
|
824
864
|
getWalletRecoveryState(_a) {
|
|
825
865
|
return __awaiter(this, arguments, void 0, function* ({ accountAddress, }) {
|
|
826
866
|
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 };
|