@dynamic-labs/waas 4.91.4 → 4.91.5

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,13 @@
1
1
 
2
+ ### [4.91.5](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.4...v4.91.5) (2026-07-02)
3
+
4
+
5
+ ### Bug Fixes
6
+
7
+ * revoke WaaS signed-session callback on client rebuild to stop iOS nonce race ([#11766](https://github.com/dynamic-labs/dynamic-auth/issues/11766)) ([c895b5d](https://github.com/dynamic-labs/dynamic-auth/commit/c895b5d0987d62a9f5597741dbeae0ec7fedfe5b))
8
+ * **sdk-react-core:** allow sendOneTimeCode to target non-primary chain wallets ([#11777](https://github.com/dynamic-labs/dynamic-auth/issues/11777)) ([63f82af](https://github.com/dynamic-labs/dynamic-auth/commit/63f82af7c52be595bc2948ec88ee9c919ac9275a))
9
+ * **webview-controller:** resolve post-login wallet race in Viem and ZeroDev controllers ([#11774](https://github.com/dynamic-labs/dynamic-auth/issues/11774)) ([95ed26e](https://github.com/dynamic-labs/dynamic-auth/commit/95ed26eee09d9aff5a5af6517ab7e1360ef5f337))
10
+
2
11
  ### [4.91.4](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.3...v4.91.4) (2026-07-01)
3
12
 
4
13
 
package/package.cjs CHANGED
@@ -3,6 +3,6 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "4.91.4";
6
+ var version = "4.91.5";
7
7
 
8
8
  exports.version = version;
package/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  'use client'
2
- var version = "4.91.4";
2
+ var version = "4.91.5";
3
3
 
4
4
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/waas",
3
- "version": "4.91.4",
3
+ "version": "4.91.5",
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.12.1",
20
- "@dynamic-labs/assert-package-version": "4.91.4",
20
+ "@dynamic-labs/assert-package-version": "4.91.5",
21
21
  "@dynamic-labs/sdk-api-core": "0.0.1046",
22
22
  "@dynamic-labs-wallet/browser-wallet-client": "1.0.48",
23
23
  "@dynamic-labs-wallet/forward-mpc-client": "0.12.0",
24
- "@dynamic-labs/ethereum-core": "4.91.4",
25
- "@dynamic-labs/logger": "4.91.4",
26
- "@dynamic-labs/solana-core": "4.91.4",
27
- "@dynamic-labs/sui-core": "4.91.4",
28
- "@dynamic-labs/utils": "4.91.4",
29
- "@dynamic-labs/wallet-book": "4.91.4",
30
- "@dynamic-labs/wallet-connector-core": "4.91.4"
24
+ "@dynamic-labs/ethereum-core": "4.91.5",
25
+ "@dynamic-labs/logger": "4.91.5",
26
+ "@dynamic-labs/solana-core": "4.91.5",
27
+ "@dynamic-labs/sui-core": "4.91.5",
28
+ "@dynamic-labs/utils": "4.91.5",
29
+ "@dynamic-labs/wallet-book": "4.91.5",
30
+ "@dynamic-labs/wallet-connector-core": "4.91.5"
31
31
  },
32
32
  "peerDependencies": {}
33
33
  }
@@ -183,6 +183,24 @@ const withDynamicWaas = (BaseClass) => {
183
183
  }
184
184
  this.chainName = chainName;
185
185
  }
186
+ createRevocableSignedSessionCallback() {
187
+ if (!this.getSignedSessionId) {
188
+ throw new Error('[DynamicWaasMixin] getSignedSessionId must be set before creating a revocable callback');
189
+ }
190
+ const original = this.getSignedSessionId;
191
+ let revoked = false;
192
+ this.revokeSignedSession = () => {
193
+ revoked = true;
194
+ };
195
+ return {
196
+ getSignedSessionId: () => _tslib.__awaiter(this, void 0, void 0, function* () {
197
+ if (revoked) {
198
+ throw new Error('[DynamicWaasMixin] WaaS client replaced — signed session callback revoked');
199
+ }
200
+ return original();
201
+ }),
202
+ };
203
+ }
186
204
  createDynamicWaasClient(traceContext) {
187
205
  return _tslib.__awaiter(this, void 0, void 0, function* () {
188
206
  var _a;
@@ -208,7 +226,7 @@ const withDynamicWaas = (BaseClass) => {
208
226
  }, Object.assign(Object.assign(Object.assign(Object.assign({}, (utils.PlatformService.isWaasSecureStorageSupported
209
227
  ? { secureStorage: createWaasClientSecureStorage.createWaasClientSecureStorage() }
210
228
  : {})), (this.getSignedSessionId
211
- ? { getSignedSessionId: this.getSignedSessionId }
229
+ ? this.createRevocableSignedSessionCallback()
212
230
  : {})), (this.getSessionPublicKey
213
231
  ? { getSessionPublicKey: this.getSessionPublicKey }
214
232
  : {})), (this.onUnauthorized
@@ -225,13 +243,19 @@ const withDynamicWaas = (BaseClass) => {
225
243
  }
226
244
  getWaasWalletClient(traceContext_1) {
227
245
  return _tslib.__awaiter(this, arguments, void 0, function* (traceContext, { forceRebuild = false } = {}) {
228
- var _a;
246
+ var _a, _b;
229
247
  // forceRebuild drops the cached client so the iframe re-auths with the
230
248
  // fresh session (e.g. after a step-up reauth) instead of 401-ing on the
231
249
  // stale cached token. Callers must only force a rebuild when a token is
232
250
  // available (see getWaasWalletConnector's live-token guard); otherwise
233
251
  // createDynamicWaasClient would throw "Auth token is required".
234
252
  if (forceRebuild) {
253
+ // Revoke the previous client's nonce callback before dropping it.
254
+ // The old DynamicWalletClient is not destroyed — it has no cancellation
255
+ // API — but revoking its reverse-channel callback prevents it from
256
+ // fetching fresh nonces and competing with the new client's recovery.
257
+ (_a = this.revokeSignedSession) === null || _a === void 0 ? void 0 : _a.call(this);
258
+ this.revokeSignedSession = undefined;
235
259
  this.dynamicWaasClient = undefined;
236
260
  }
237
261
  if (!this.dynamicWaasClient) {
@@ -243,7 +267,7 @@ const withDynamicWaas = (BaseClass) => {
243
267
  // 401s and trips the iframe's unauthorized → forced-logout path. Every
244
268
  // WaaS caller funnels through here, so this single guard covers auto
245
269
  // wallet creation, ZeroDev smart-wallet init, getWallet, etc.
246
- if (tokenHasPendingAuthScope.tokenHasPendingAuthScope((_a = this.getAuthToken) === null || _a === void 0 ? void 0 : _a.call(this))) {
270
+ if (tokenHasPendingAuthScope.tokenHasPendingAuthScope((_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this))) {
247
271
  throw new utils.WaasAuthScopePendingError();
248
272
  }
249
273
  this.dynamicWaasClient = yield this.createDynamicWaasClient(traceContext);
@@ -670,6 +694,7 @@ const withDynamicWaas = (BaseClass) => {
670
694
  }
671
695
  endSession(reason) {
672
696
  return _tslib.__awaiter(this, void 0, void 0, function* () {
697
+ var _a;
673
698
  // Building the wallet client requires an auth token (createDynamicWaasClient
674
699
  // throws in header auth mode when none is present); the new scope guard in
675
700
  // getWaasWalletClient also throws during pending-auth (MFA/KYC/device). On
@@ -721,6 +746,8 @@ const withDynamicWaas = (BaseClass) => {
721
746
  });
722
747
  }
723
748
  }
749
+ (_a = this.revokeSignedSession) === null || _a === void 0 ? void 0 : _a.call(this);
750
+ this.revokeSignedSession = undefined;
724
751
  this.dynamicWaasClient = undefined;
725
752
  });
726
753
  }
@@ -30,6 +30,7 @@ export declare const withDynamicWaas: <T extends abstract new (...args: any[]) =
30
30
  relayUrl?: string | undefined;
31
31
  baseClientKeysharesRelayApiUrl?: string | undefined;
32
32
  dynamicWaasClient: DynamicWalletClient | undefined;
33
+ revokeSignedSession: (() => void) | undefined;
33
34
  chainName: string;
34
35
  authMode: 'cookie' | 'header';
35
36
  logger: Logger;
@@ -77,6 +78,9 @@ export declare const withDynamicWaas: <T extends abstract new (...args: any[]) =
77
78
  accountAddress: string;
78
79
  password?: string;
79
80
  }): Promise<void>;
81
+ createRevocableSignedSessionCallback(): {
82
+ getSignedSessionId: () => Promise<string>;
83
+ };
80
84
  createDynamicWaasClient(traceContext?: TraceContext): Promise<DynamicWalletClient>;
81
85
  getWaasWalletClient(traceContext?: TraceContext, { forceRebuild }?: {
82
86
  forceRebuild?: boolean;
@@ -179,6 +179,24 @@ const withDynamicWaas = (BaseClass) => {
179
179
  }
180
180
  this.chainName = chainName;
181
181
  }
182
+ createRevocableSignedSessionCallback() {
183
+ if (!this.getSignedSessionId) {
184
+ throw new Error('[DynamicWaasMixin] getSignedSessionId must be set before creating a revocable callback');
185
+ }
186
+ const original = this.getSignedSessionId;
187
+ let revoked = false;
188
+ this.revokeSignedSession = () => {
189
+ revoked = true;
190
+ };
191
+ return {
192
+ getSignedSessionId: () => __awaiter(this, void 0, void 0, function* () {
193
+ if (revoked) {
194
+ throw new Error('[DynamicWaasMixin] WaaS client replaced — signed session callback revoked');
195
+ }
196
+ return original();
197
+ }),
198
+ };
199
+ }
182
200
  createDynamicWaasClient(traceContext) {
183
201
  return __awaiter(this, void 0, void 0, function* () {
184
202
  var _a;
@@ -204,7 +222,7 @@ const withDynamicWaas = (BaseClass) => {
204
222
  }, Object.assign(Object.assign(Object.assign(Object.assign({}, (PlatformService.isWaasSecureStorageSupported
205
223
  ? { secureStorage: createWaasClientSecureStorage() }
206
224
  : {})), (this.getSignedSessionId
207
- ? { getSignedSessionId: this.getSignedSessionId }
225
+ ? this.createRevocableSignedSessionCallback()
208
226
  : {})), (this.getSessionPublicKey
209
227
  ? { getSessionPublicKey: this.getSessionPublicKey }
210
228
  : {})), (this.onUnauthorized
@@ -221,13 +239,19 @@ const withDynamicWaas = (BaseClass) => {
221
239
  }
222
240
  getWaasWalletClient(traceContext_1) {
223
241
  return __awaiter(this, arguments, void 0, function* (traceContext, { forceRebuild = false } = {}) {
224
- var _a;
242
+ var _a, _b;
225
243
  // forceRebuild drops the cached client so the iframe re-auths with the
226
244
  // fresh session (e.g. after a step-up reauth) instead of 401-ing on the
227
245
  // stale cached token. Callers must only force a rebuild when a token is
228
246
  // available (see getWaasWalletConnector's live-token guard); otherwise
229
247
  // createDynamicWaasClient would throw "Auth token is required".
230
248
  if (forceRebuild) {
249
+ // Revoke the previous client's nonce callback before dropping it.
250
+ // The old DynamicWalletClient is not destroyed — it has no cancellation
251
+ // API — but revoking its reverse-channel callback prevents it from
252
+ // fetching fresh nonces and competing with the new client's recovery.
253
+ (_a = this.revokeSignedSession) === null || _a === void 0 ? void 0 : _a.call(this);
254
+ this.revokeSignedSession = undefined;
231
255
  this.dynamicWaasClient = undefined;
232
256
  }
233
257
  if (!this.dynamicWaasClient) {
@@ -239,7 +263,7 @@ const withDynamicWaas = (BaseClass) => {
239
263
  // 401s and trips the iframe's unauthorized → forced-logout path. Every
240
264
  // WaaS caller funnels through here, so this single guard covers auto
241
265
  // wallet creation, ZeroDev smart-wallet init, getWallet, etc.
242
- if (tokenHasPendingAuthScope((_a = this.getAuthToken) === null || _a === void 0 ? void 0 : _a.call(this))) {
266
+ if (tokenHasPendingAuthScope((_b = this.getAuthToken) === null || _b === void 0 ? void 0 : _b.call(this))) {
243
267
  throw new WaasAuthScopePendingError();
244
268
  }
245
269
  this.dynamicWaasClient = yield this.createDynamicWaasClient(traceContext);
@@ -666,6 +690,7 @@ const withDynamicWaas = (BaseClass) => {
666
690
  }
667
691
  endSession(reason) {
668
692
  return __awaiter(this, void 0, void 0, function* () {
693
+ var _a;
669
694
  // Building the wallet client requires an auth token (createDynamicWaasClient
670
695
  // throws in header auth mode when none is present); the new scope guard in
671
696
  // getWaasWalletClient also throws during pending-auth (MFA/KYC/device). On
@@ -717,6 +742,8 @@ const withDynamicWaas = (BaseClass) => {
717
742
  });
718
743
  }
719
744
  }
745
+ (_a = this.revokeSignedSession) === null || _a === void 0 ? void 0 : _a.call(this);
746
+ this.revokeSignedSession = undefined;
720
747
  this.dynamicWaasClient = undefined;
721
748
  });
722
749
  }