@dynamic-labs/waas 4.88.5 → 4.89.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -1
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +9 -9
- package/src/DynamicWaasMixin.cjs +53 -7
- package/src/DynamicWaasMixin.d.ts +23 -0
- package/src/DynamicWaasMixin.js +53 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
|
|
2
|
+
## [4.89.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.88.6...v4.89.0) (2026-06-16)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **moonpay:** add useMoonPayOnramp hook ([#11405](https://github.com/dynamic-labs/dynamic-auth/issues/11405)) ([48cb62f](https://github.com/dynamic-labs/dynamic-auth/commit/48cb62fefecb511fcba9359ee6f6096dfef0b125))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* get wallet metadata from wallet-book when its present ([#11566](https://github.com/dynamic-labs/dynamic-auth/issues/11566)) ([a1a8ad5](https://github.com/dynamic-labs/dynamic-auth/commit/a1a8ad53c063157b189aea138fa338fcc67dc4dd))
|
|
13
|
+
* **waas:** instant logout — clear key share host-side, background iframe cleanup ([#11583](https://github.com/dynamic-labs/dynamic-auth/issues/11583)) ([0ab3378](https://github.com/dynamic-labs/dynamic-auth/commit/0ab3378efdbbe233069b17fad62b0c126397bc3a))
|
|
14
|
+
* **wagmi-connector:** await disconnect before connect to defuse SyncDynamicWagmi race DYNT-549 ([#11579](https://github.com/dynamic-labs/dynamic-auth/issues/11579)) ([6ac7c0e](https://github.com/dynamic-labs/dynamic-auth/commit/6ac7c0e02ed863342047bc5a1e60be3a66b8a425)), closes [#11131](https://github.com/dynamic-labs/dynamic-auth/issues/11131) [#11513](https://github.com/dynamic-labs/dynamic-auth/issues/11513) [#11516](https://github.com/dynamic-labs/dynamic-auth/issues/11516) [#11496](https://github.com/dynamic-labs/dynamic-auth/issues/11496) [#11513](https://github.com/dynamic-labs/dynamic-auth/issues/11513) [/github.com/dynamic-labs/dynamic-auth/blob/main/packages/wagmi-connector/src/lib/hooks/useConnectorId/useConnectorId.ts#L19-L26](https://github.com/dynamic-labs//github.com/dynamic-labs/dynamic-auth/blob/main/packages/wagmi-connector/src/lib/hooks/useConnectorId/useConnectorId.ts/issues/L19-L26) [#11131](https://github.com/dynamic-labs/dynamic-auth/issues/11131) [#11516](https://github.com/dynamic-labs/dynamic-auth/issues/11516) [#11513](https://github.com/dynamic-labs/dynamic-auth/issues/11513)
|
|
15
|
+
* **react-native:** resolve intermittent "Wallet with id <uuid> not found" after login ([#11575](https://github.com/dynamic-labs/dynamic-auth/issues/11575)) ([9d7a246](https://github.com/dynamic-labs/dynamic-auth/commit/9d7a246167927b9339dc33c10977c6d12783ab88))
|
|
16
|
+
|
|
17
|
+
### [4.88.6](https://github.com/dynamic-labs/dynamic-auth/compare/v4.88.5...v4.88.6) (2026-06-13)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* **DynamicBridgeWidget:** prevent bridge chain sync from reverting manual wallet switches ([#11560](https://github.com/dynamic-labs/dynamic-auth/issues/11560)) ([40c4973](https://github.com/dynamic-labs/dynamic-auth/commit/40c4973761b3e887577664f72f89d1d6ba285ea3))
|
|
23
|
+
* resolve EOA wallet client on the correct chain for EIP-7702 smart wallets ([#11564](https://github.com/dynamic-labs/dynamic-auth/issues/11564)) ([893b083](https://github.com/dynamic-labs/dynamic-auth/commit/893b0837a450ec683ccd09f2bb54204b77b6bd50))
|
|
24
|
+
|
|
2
25
|
### [4.88.5](https://github.com/dynamic-labs/dynamic-auth/compare/v4.88.4...v4.88.5) (2026-06-11)
|
|
3
26
|
|
|
4
27
|
|
|
@@ -6502,4 +6525,4 @@ Enjoy!
|
|
|
6502
6525
|
### Bug Fixes
|
|
6503
6526
|
|
|
6504
6527
|
* **view-context:** refactor view context to have initial view ([#2268](https://github.com/dynamic-labs/DynamicAuth/issues/2268)) ([0afe6ae](https://github.com/dynamic-labs/DynamicAuth/commit/0afe6ae469f62fd16fd8471322f9295957f607f6))
|
|
6505
|
-
* **wcv2:** upgrade universal p
|
|
6528
|
+
* **wcv2:** upgrade universal p
|
package/package.cjs
CHANGED
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/waas",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.89.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Dynamic Labs, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,17 +17,17 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@dynamic-labs-sdk/client": "1.8.2",
|
|
20
|
-
"@dynamic-labs/assert-package-version": "4.
|
|
20
|
+
"@dynamic-labs/assert-package-version": "4.89.0",
|
|
21
21
|
"@dynamic-labs/sdk-api-core": "0.0.1015",
|
|
22
22
|
"@dynamic-labs-wallet/browser-wallet-client": "1.0.16",
|
|
23
23
|
"@dynamic-labs-wallet/forward-mpc-client": "0.10.1",
|
|
24
|
-
"@dynamic-labs/ethereum-core": "4.
|
|
25
|
-
"@dynamic-labs/logger": "4.
|
|
26
|
-
"@dynamic-labs/solana-core": "4.
|
|
27
|
-
"@dynamic-labs/sui-core": "4.
|
|
28
|
-
"@dynamic-labs/utils": "4.
|
|
29
|
-
"@dynamic-labs/wallet-book": "4.
|
|
30
|
-
"@dynamic-labs/wallet-connector-core": "4.
|
|
24
|
+
"@dynamic-labs/ethereum-core": "4.89.0",
|
|
25
|
+
"@dynamic-labs/logger": "4.89.0",
|
|
26
|
+
"@dynamic-labs/solana-core": "4.89.0",
|
|
27
|
+
"@dynamic-labs/sui-core": "4.89.0",
|
|
28
|
+
"@dynamic-labs/utils": "4.89.0",
|
|
29
|
+
"@dynamic-labs/wallet-book": "4.89.0",
|
|
30
|
+
"@dynamic-labs/wallet-connector-core": "4.89.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {}
|
|
33
33
|
}
|
package/src/DynamicWaasMixin.cjs
CHANGED
|
@@ -12,6 +12,9 @@ var constants = require('../utils/constants.cjs');
|
|
|
12
12
|
var createWaasClientSecureStorage = require('../utils/createWaasClientSecureStorage.cjs');
|
|
13
13
|
var instrumentation = require('../utils/instrumentation.cjs');
|
|
14
14
|
|
|
15
|
+
// Fallback error code used when a thrown value carries no code, or when
|
|
16
|
+
// formatting the error itself fails.
|
|
17
|
+
const UNKNOWN_ERROR_CODE = 'unknown';
|
|
15
18
|
// This class is common across all waas connectors
|
|
16
19
|
class WaasExportHandler {
|
|
17
20
|
constructor() {
|
|
@@ -624,7 +627,28 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
624
627
|
// in. On explicit user-initiated logout, shares are always cleared for
|
|
625
628
|
// security.
|
|
626
629
|
if (reason !== 'token-expired') {
|
|
627
|
-
|
|
630
|
+
// Clear the MPC key share directly on the host's local secure storage.
|
|
631
|
+
// This is fast and guaranteed, independent of the iframe round-trip
|
|
632
|
+
// cleanup below — whose request-channel timeout (plus a recovery retry)
|
|
633
|
+
// can block logout for ~10s on slow devices where secureStorage is slow
|
|
634
|
+
// to ACK. Awaited because it is a local operation (milliseconds).
|
|
635
|
+
const accountAddress = yield this.getActiveAccountAddress();
|
|
636
|
+
if (accountAddress) {
|
|
637
|
+
try {
|
|
638
|
+
yield createWaasClientSecureStorage.createWaasClientSecureStorage().removeClientKeyShare(accountAddress);
|
|
639
|
+
}
|
|
640
|
+
catch (error) {
|
|
641
|
+
this.instrument('[endSession] direct key share removal failed', Object.assign({ key: 'endSession-removeClientKeyShare-failed', time: 0 }, this.buildErrorInstrumentContext(error)));
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
// Tear down the iframe and run its best-effort storage cleanup in the
|
|
645
|
+
// background so logout returns immediately instead of blocking on the
|
|
646
|
+
// iframe cleanup's request-channel timeout. The iframe handler already
|
|
647
|
+
// swallows its own errors, and the DOM teardown obsoletes anything it
|
|
648
|
+
// misses. Promise.resolve guards against a non-promise return in tests.
|
|
649
|
+
void Promise.resolve(waasClient.cleanup()).catch((error) => {
|
|
650
|
+
this.instrument('[endSession] background iframe cleanup failed', Object.assign({ key: 'endSession-cleanup-failed', time: 0 }, this.buildErrorInstrumentContext(error)));
|
|
651
|
+
});
|
|
628
652
|
}
|
|
629
653
|
this.dynamicWaasClient = undefined;
|
|
630
654
|
});
|
|
@@ -661,6 +685,33 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
661
685
|
.map((byte) => byte.toString(16).padStart(2, '0'))
|
|
662
686
|
.join('');
|
|
663
687
|
}
|
|
688
|
+
/**
|
|
689
|
+
* Normalizes an unknown thrown value into the error fields used across
|
|
690
|
+
* instrumentation so callers don't re-derive them at each catch site.
|
|
691
|
+
*
|
|
692
|
+
* Wrapped in try/catch: this is best-effort logging, and a value that
|
|
693
|
+
* resists formatting (e.g. an object whose toString throws) must never
|
|
694
|
+
* turn a log line into an exception that blocks the calling flow such as
|
|
695
|
+
* logout.
|
|
696
|
+
*
|
|
697
|
+
* `public` (not `private`) because the TS `private` keyword can't be used
|
|
698
|
+
* on this mixin's exported class expression (TS4094), and ECMAScript
|
|
699
|
+
* `#private` isn't supported by the package's Jest/Babel transform. It is
|
|
700
|
+
* internal-only despite the modifier — same constraint as `instrument`.
|
|
701
|
+
*/
|
|
702
|
+
buildErrorInstrumentContext(error) {
|
|
703
|
+
var _a, _b;
|
|
704
|
+
try {
|
|
705
|
+
return {
|
|
706
|
+
errorCode: (_a = error === null || error === void 0 ? void 0 : error.code) !== null && _a !== void 0 ? _a : UNKNOWN_ERROR_CODE,
|
|
707
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
708
|
+
errorType: (_b = error === null || error === void 0 ? void 0 : error.constructor) === null || _b === void 0 ? void 0 : _b.name,
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
catch (_c) {
|
|
712
|
+
return { errorCode: UNKNOWN_ERROR_CODE };
|
|
713
|
+
}
|
|
714
|
+
}
|
|
664
715
|
/**
|
|
665
716
|
* Helper method to instrument with automatic properties inclusion
|
|
666
717
|
*/
|
|
@@ -676,7 +727,6 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
676
727
|
}
|
|
677
728
|
instrumentAsync(_a) {
|
|
678
729
|
return _tslib.__awaiter(this, arguments, void 0, function* ({ operation, resource, fn, context, }) {
|
|
679
|
-
var _b, _c;
|
|
680
730
|
const timing = new instrumentation.InstrumentationTimer(context === null || context === void 0 ? void 0 : context.startTime);
|
|
681
731
|
if (context === null || context === void 0 ? void 0 : context.stepStartTime) {
|
|
682
732
|
timing.setStepStartTime(context.stepStartTime);
|
|
@@ -693,11 +743,7 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
693
743
|
catch (error) {
|
|
694
744
|
const isUserRejection = error instanceof utils.UserRejectedRequestError ||
|
|
695
745
|
(error === null || error === void 0 ? void 0 : error.code) === 'user_rejected_request';
|
|
696
|
-
const errorContext =
|
|
697
|
-
errorCode: (_b = error === null || error === void 0 ? void 0 : error.code) !== null && _b !== void 0 ? _b : 'unknown',
|
|
698
|
-
errorMessage: error instanceof Error ? error.message : String(error),
|
|
699
|
-
errorType: (_c = error === null || error === void 0 ? void 0 : error.constructor) === null || _c === void 0 ? void 0 : _c.name,
|
|
700
|
-
};
|
|
746
|
+
const errorContext = this.buildErrorInstrumentContext(error);
|
|
701
747
|
if (isUserRejection) {
|
|
702
748
|
// User-initiated cancellations are expected — debug only, no backend noise
|
|
703
749
|
this.logger.debug(`[${operation}] ${resource} - cancelled`, Object.assign(Object.assign({ key: `${resource}-cancelled`, operation, stepTime: timing.getStepElapsed(), time: timing.getElapsed() }, context), errorContext));
|
|
@@ -166,6 +166,29 @@ export declare const withDynamicWaas: <T extends abstract new (...args: any[]) =
|
|
|
166
166
|
*/
|
|
167
167
|
getConnectedAccounts(): Promise<string[]>;
|
|
168
168
|
generateTraceId(): string;
|
|
169
|
+
/**
|
|
170
|
+
* Normalizes an unknown thrown value into the error fields used across
|
|
171
|
+
* instrumentation so callers don't re-derive them at each catch site.
|
|
172
|
+
*
|
|
173
|
+
* Wrapped in try/catch: this is best-effort logging, and a value that
|
|
174
|
+
* resists formatting (e.g. an object whose toString throws) must never
|
|
175
|
+
* turn a log line into an exception that blocks the calling flow such as
|
|
176
|
+
* logout.
|
|
177
|
+
*
|
|
178
|
+
* `public` (not `private`) because the TS `private` keyword can't be used
|
|
179
|
+
* on this mixin's exported class expression (TS4094), and ECMAScript
|
|
180
|
+
* `#private` isn't supported by the package's Jest/Babel transform. It is
|
|
181
|
+
* internal-only despite the modifier — same constraint as `instrument`.
|
|
182
|
+
*/
|
|
183
|
+
buildErrorInstrumentContext(error: unknown): {
|
|
184
|
+
errorCode: string | import("@dynamic-labs/utils").ErrorCode;
|
|
185
|
+
errorMessage: string;
|
|
186
|
+
errorType: string | undefined;
|
|
187
|
+
} | {
|
|
188
|
+
errorCode: string;
|
|
189
|
+
errorMessage?: undefined;
|
|
190
|
+
errorType?: undefined;
|
|
191
|
+
};
|
|
169
192
|
/**
|
|
170
193
|
* Helper method to instrument with automatic properties inclusion
|
|
171
194
|
*/
|
package/src/DynamicWaasMixin.js
CHANGED
|
@@ -8,6 +8,9 @@ import { DEFAULT_BASE_API_URL, DEFAULT_BASE_MPC_RELAY_API_URL } from '../utils/c
|
|
|
8
8
|
import { createWaasClientSecureStorage } from '../utils/createWaasClientSecureStorage.js';
|
|
9
9
|
import { InstrumentationTimer } from '../utils/instrumentation.js';
|
|
10
10
|
|
|
11
|
+
// Fallback error code used when a thrown value carries no code, or when
|
|
12
|
+
// formatting the error itself fails.
|
|
13
|
+
const UNKNOWN_ERROR_CODE = 'unknown';
|
|
11
14
|
// This class is common across all waas connectors
|
|
12
15
|
class WaasExportHandler {
|
|
13
16
|
constructor() {
|
|
@@ -620,7 +623,28 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
620
623
|
// in. On explicit user-initiated logout, shares are always cleared for
|
|
621
624
|
// security.
|
|
622
625
|
if (reason !== 'token-expired') {
|
|
623
|
-
|
|
626
|
+
// Clear the MPC key share directly on the host's local secure storage.
|
|
627
|
+
// This is fast and guaranteed, independent of the iframe round-trip
|
|
628
|
+
// cleanup below — whose request-channel timeout (plus a recovery retry)
|
|
629
|
+
// can block logout for ~10s on slow devices where secureStorage is slow
|
|
630
|
+
// to ACK. Awaited because it is a local operation (milliseconds).
|
|
631
|
+
const accountAddress = yield this.getActiveAccountAddress();
|
|
632
|
+
if (accountAddress) {
|
|
633
|
+
try {
|
|
634
|
+
yield createWaasClientSecureStorage().removeClientKeyShare(accountAddress);
|
|
635
|
+
}
|
|
636
|
+
catch (error) {
|
|
637
|
+
this.instrument('[endSession] direct key share removal failed', Object.assign({ key: 'endSession-removeClientKeyShare-failed', time: 0 }, this.buildErrorInstrumentContext(error)));
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
// Tear down the iframe and run its best-effort storage cleanup in the
|
|
641
|
+
// background so logout returns immediately instead of blocking on the
|
|
642
|
+
// iframe cleanup's request-channel timeout. The iframe handler already
|
|
643
|
+
// swallows its own errors, and the DOM teardown obsoletes anything it
|
|
644
|
+
// misses. Promise.resolve guards against a non-promise return in tests.
|
|
645
|
+
void Promise.resolve(waasClient.cleanup()).catch((error) => {
|
|
646
|
+
this.instrument('[endSession] background iframe cleanup failed', Object.assign({ key: 'endSession-cleanup-failed', time: 0 }, this.buildErrorInstrumentContext(error)));
|
|
647
|
+
});
|
|
624
648
|
}
|
|
625
649
|
this.dynamicWaasClient = undefined;
|
|
626
650
|
});
|
|
@@ -657,6 +681,33 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
657
681
|
.map((byte) => byte.toString(16).padStart(2, '0'))
|
|
658
682
|
.join('');
|
|
659
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* Normalizes an unknown thrown value into the error fields used across
|
|
686
|
+
* instrumentation so callers don't re-derive them at each catch site.
|
|
687
|
+
*
|
|
688
|
+
* Wrapped in try/catch: this is best-effort logging, and a value that
|
|
689
|
+
* resists formatting (e.g. an object whose toString throws) must never
|
|
690
|
+
* turn a log line into an exception that blocks the calling flow such as
|
|
691
|
+
* logout.
|
|
692
|
+
*
|
|
693
|
+
* `public` (not `private`) because the TS `private` keyword can't be used
|
|
694
|
+
* on this mixin's exported class expression (TS4094), and ECMAScript
|
|
695
|
+
* `#private` isn't supported by the package's Jest/Babel transform. It is
|
|
696
|
+
* internal-only despite the modifier — same constraint as `instrument`.
|
|
697
|
+
*/
|
|
698
|
+
buildErrorInstrumentContext(error) {
|
|
699
|
+
var _a, _b;
|
|
700
|
+
try {
|
|
701
|
+
return {
|
|
702
|
+
errorCode: (_a = error === null || error === void 0 ? void 0 : error.code) !== null && _a !== void 0 ? _a : UNKNOWN_ERROR_CODE,
|
|
703
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
704
|
+
errorType: (_b = error === null || error === void 0 ? void 0 : error.constructor) === null || _b === void 0 ? void 0 : _b.name,
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
catch (_c) {
|
|
708
|
+
return { errorCode: UNKNOWN_ERROR_CODE };
|
|
709
|
+
}
|
|
710
|
+
}
|
|
660
711
|
/**
|
|
661
712
|
* Helper method to instrument with automatic properties inclusion
|
|
662
713
|
*/
|
|
@@ -672,7 +723,6 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
672
723
|
}
|
|
673
724
|
instrumentAsync(_a) {
|
|
674
725
|
return __awaiter(this, arguments, void 0, function* ({ operation, resource, fn, context, }) {
|
|
675
|
-
var _b, _c;
|
|
676
726
|
const timing = new InstrumentationTimer(context === null || context === void 0 ? void 0 : context.startTime);
|
|
677
727
|
if (context === null || context === void 0 ? void 0 : context.stepStartTime) {
|
|
678
728
|
timing.setStepStartTime(context.stepStartTime);
|
|
@@ -689,11 +739,7 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
689
739
|
catch (error) {
|
|
690
740
|
const isUserRejection = error instanceof UserRejectedRequestError ||
|
|
691
741
|
(error === null || error === void 0 ? void 0 : error.code) === 'user_rejected_request';
|
|
692
|
-
const errorContext =
|
|
693
|
-
errorCode: (_b = error === null || error === void 0 ? void 0 : error.code) !== null && _b !== void 0 ? _b : 'unknown',
|
|
694
|
-
errorMessage: error instanceof Error ? error.message : String(error),
|
|
695
|
-
errorType: (_c = error === null || error === void 0 ? void 0 : error.constructor) === null || _c === void 0 ? void 0 : _c.name,
|
|
696
|
-
};
|
|
742
|
+
const errorContext = this.buildErrorInstrumentContext(error);
|
|
697
743
|
if (isUserRejection) {
|
|
698
744
|
// User-initiated cancellations are expected — debug only, no backend noise
|
|
699
745
|
this.logger.debug(`[${operation}] ${resource} - cancelled`, Object.assign(Object.assign({ key: `${resource}-cancelled`, operation, stepTime: timing.getStepElapsed(), time: timing.getElapsed() }, context), errorContext));
|