@dynamic-labs/waas 4.98.0 → 4.100.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 +26 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +11 -11
- package/src/DynamicWaasMixin.cjs +60 -6
- package/src/DynamicWaasMixin.d.ts +12 -0
- package/src/DynamicWaasMixin.js +60 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,30 @@
|
|
|
1
1
|
|
|
2
|
+
## [4.100.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.99.0...v4.100.0) (2026-09-10)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **solana-extension:** expose createAssociatedTokenAccount ([#12377](https://github.com/dynamic-labs/dynamic-auth/issues/12377)) ([c127857](https://github.com/dynamic-labs/dynamic-auth/commit/c127857097069ef2fcf337b78971e678f0552277))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* show transaction amount when simulation returns no transfers (v4 backport) ([#12356](https://github.com/dynamic-labs/dynamic-auth/issues/12356)) ([36feb2d](https://github.com/dynamic-labs/dynamic-auth/commit/36feb2d24de3f78560112bdf86a258d0596c4470))
|
|
13
|
+
|
|
14
|
+
## [4.99.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.98.0...v4.99.0) (2026-09-10)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* **solana-core:** standalone sponsored ATA creation [v4 backport] ([#12366](https://github.com/dynamic-labs/dynamic-auth/issues/12366)) ([46d86c9](https://github.com/dynamic-labs/dynamic-auth/commit/46d86c9a1a04c45bf045acc5c6df792dcd4b3590))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Bug Fixes
|
|
23
|
+
|
|
24
|
+
* do not report wallets installed from a provider selection router (v4) ([#12341](https://github.com/dynamic-labs/dynamic-auth/issues/12341)) ([6b02087](https://github.com/dynamic-labs/dynamic-auth/commit/6b02087685545bb6f672eb9040316d01489c82f4))
|
|
25
|
+
* **screening:** soften the blocked-wallet copy to be provider-neutral (v4) ([#12359](https://github.com/dynamic-labs/dynamic-auth/issues/12359)) ([d6772df](https://github.com/dynamic-labs/dynamic-auth/commit/d6772dfc1419811bfbc1d9cb1db58fe12274d397))
|
|
26
|
+
* **waas:** detach the superseded WaaS client from the iframe reverse channel (v4) ([#12349](https://github.com/dynamic-labs/dynamic-auth/issues/12349)) ([393253d](https://github.com/dynamic-labs/dynamic-auth/commit/393253d9e5934e039e21b85ed6ceded760e0f225)), closes [#11766](https://github.com/dynamic-labs/dynamic-auth/issues/11766) [#12348](https://github.com/dynamic-labs/dynamic-auth/issues/12348)
|
|
27
|
+
|
|
2
28
|
## [4.98.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.97.0...v4.98.0) (2026-09-02)
|
|
3
29
|
|
|
4
30
|
|
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.100.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.27.1",
|
|
20
|
-
"@dynamic-labs/assert-package-version": "4.
|
|
20
|
+
"@dynamic-labs/assert-package-version": "4.100.0",
|
|
21
21
|
"@dynamic-labs/sdk-api-core": "0.12.0",
|
|
22
|
-
"@dynamic-labs-wallet/browser-wallet-client": "1.1.
|
|
23
|
-
"@dynamic-labs-wallet/forward-mpc-client": "2.0.
|
|
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.
|
|
22
|
+
"@dynamic-labs-wallet/browser-wallet-client": "1.1.8",
|
|
23
|
+
"@dynamic-labs-wallet/forward-mpc-client": "2.0.2",
|
|
24
|
+
"@dynamic-labs/ethereum-core": "4.100.0",
|
|
25
|
+
"@dynamic-labs/logger": "4.100.0",
|
|
26
|
+
"@dynamic-labs/solana-core": "4.100.0",
|
|
27
|
+
"@dynamic-labs/sui-core": "4.100.0",
|
|
28
|
+
"@dynamic-labs/utils": "4.100.0",
|
|
29
|
+
"@dynamic-labs/wallet-book": "4.100.0",
|
|
30
|
+
"@dynamic-labs/wallet-connector-core": "4.100.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {}
|
|
33
33
|
}
|
package/src/DynamicWaasMixin.cjs
CHANGED
|
@@ -241,6 +241,31 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
241
241
|
return client;
|
|
242
242
|
});
|
|
243
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Stops the client answering the iframe's session-scoped reverse-channel
|
|
246
|
+
* requests — the signed session and the 401 notification. Its key-share
|
|
247
|
+
* handlers stay attached until the client's own cleanup() has its ACK, so
|
|
248
|
+
* the iframe can still clear shares on logout.
|
|
249
|
+
*
|
|
250
|
+
* Returns false only if the attempt threw: the client may still be
|
|
251
|
+
* registered, so the caller must not revoke it. Never rethrows — this runs
|
|
252
|
+
* on the rotation and logout paths, where throwing would leave the caller
|
|
253
|
+
* with no client at all.
|
|
254
|
+
*/
|
|
255
|
+
detachWaasClient(client, reason) {
|
|
256
|
+
var _a;
|
|
257
|
+
// The pinned browser-wallet-client predates detach(); this goes away with
|
|
258
|
+
// the version bump.
|
|
259
|
+
const detachable = client;
|
|
260
|
+
try {
|
|
261
|
+
(_a = detachable === null || detachable === void 0 ? void 0 : detachable.detach) === null || _a === void 0 ? void 0 : _a.call(detachable);
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
this.instrument('[DynamicWaasMixin] WaaS client detach failed', Object.assign({ key: 'waas-client-detach-failed', operation: 'detachWaasClient', reason, time: 0 }, this.buildErrorInstrumentContext(error)));
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
244
269
|
getWaasWalletClient(traceContext_1) {
|
|
245
270
|
return _tslib.__awaiter(this, arguments, void 0, function* (traceContext, { forceRebuild = false } = {}) {
|
|
246
271
|
var _a, _b;
|
|
@@ -250,11 +275,19 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
250
275
|
// available (see getWaasWalletConnector's live-token guard); otherwise
|
|
251
276
|
// createDynamicWaasClient would throw "Auth token is required".
|
|
252
277
|
if (forceRebuild) {
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
//
|
|
257
|
-
|
|
278
|
+
// Detach the superseded client, then revoke it — and never revoke one we
|
|
279
|
+
// did not detach. The reverse channel is page-wide and
|
|
280
|
+
// first-response-wins, so a revoked-but-still-attached client rejects
|
|
281
|
+
// instantly, beats the live client to every getSignedSessionId and
|
|
282
|
+
// poisons wallet creation for the life of the iframe. Two cases land
|
|
283
|
+
// there: a failed detach, and a concurrent rebuild, where
|
|
284
|
+
// createDynamicWaasClient has installed the new revoker but not yet
|
|
285
|
+
// returned the client it belongs to. The revoke stays as a guard for a
|
|
286
|
+
// caller still holding a direct reference.
|
|
287
|
+
const superseded = this.dynamicWaasClient;
|
|
288
|
+
if (superseded && this.detachWaasClient(superseded, 'force-rebuild')) {
|
|
289
|
+
(_a = this.revokeSignedSession) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
290
|
+
}
|
|
258
291
|
this.revokeSignedSession = undefined;
|
|
259
292
|
this.dynamicWaasClient = undefined;
|
|
260
293
|
}
|
|
@@ -774,7 +807,28 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
774
807
|
});
|
|
775
808
|
}
|
|
776
809
|
}
|
|
777
|
-
|
|
810
|
+
// Detach synchronously: the cleanup() above removes the handlers too, but
|
|
811
|
+
// it is un-awaited and can sit on the channel's 5s timeout first, leaving
|
|
812
|
+
// this client in the race with its callback already revoked.
|
|
813
|
+
//
|
|
814
|
+
// Same guard as the rebuild path: never revoke a client we did not detach.
|
|
815
|
+
// waasClient is undefined whenever getWaasWalletClient threw (pending-auth
|
|
816
|
+
// scope, or a failed build), and a client installed concurrently would own
|
|
817
|
+
// the revoke we still hold — revoking that one while it is attached is the
|
|
818
|
+
// original bug.
|
|
819
|
+
const superseded = waasClient !== null && waasClient !== void 0 ? waasClient : this.dynamicWaasClient;
|
|
820
|
+
const detached = superseded
|
|
821
|
+
? this.detachWaasClient(superseded, 'end-session')
|
|
822
|
+
: false;
|
|
823
|
+
// Revoke only while the revoker still belongs to the client we detached.
|
|
824
|
+
// endSession awaits the client, the active address and the key-share
|
|
825
|
+
// removal, and a rotation completing in any of those windows swaps both
|
|
826
|
+
// fields — revoking the live replacement while it is attached is the
|
|
827
|
+
// original bug. Detaching the captured client is unconditional: it is
|
|
828
|
+
// always safe, and it is the half that actually leaves the race.
|
|
829
|
+
if (detached && superseded === this.dynamicWaasClient) {
|
|
830
|
+
(_a = this.revokeSignedSession) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
831
|
+
}
|
|
778
832
|
this.revokeSignedSession = undefined;
|
|
779
833
|
this.dynamicWaasClient = undefined;
|
|
780
834
|
});
|
|
@@ -82,6 +82,18 @@ export declare const withDynamicWaas: <T extends abstract new (...args: any[]) =
|
|
|
82
82
|
getSignedSessionId: () => Promise<string>;
|
|
83
83
|
};
|
|
84
84
|
createDynamicWaasClient(traceContext?: TraceContext): Promise<DynamicWalletClient>;
|
|
85
|
+
/**
|
|
86
|
+
* Stops the client answering the iframe's session-scoped reverse-channel
|
|
87
|
+
* requests — the signed session and the 401 notification. Its key-share
|
|
88
|
+
* handlers stay attached until the client's own cleanup() has its ACK, so
|
|
89
|
+
* the iframe can still clear shares on logout.
|
|
90
|
+
*
|
|
91
|
+
* Returns false only if the attempt threw: the client may still be
|
|
92
|
+
* registered, so the caller must not revoke it. Never rethrows — this runs
|
|
93
|
+
* on the rotation and logout paths, where throwing would leave the caller
|
|
94
|
+
* with no client at all.
|
|
95
|
+
*/
|
|
96
|
+
detachWaasClient(client: DynamicWalletClient | undefined, reason: string): boolean;
|
|
85
97
|
getWaasWalletClient(traceContext?: TraceContext, { forceRebuild }?: {
|
|
86
98
|
forceRebuild?: boolean;
|
|
87
99
|
}): Promise<DynamicWalletClient>;
|
package/src/DynamicWaasMixin.js
CHANGED
|
@@ -237,6 +237,31 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
237
237
|
return client;
|
|
238
238
|
});
|
|
239
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Stops the client answering the iframe's session-scoped reverse-channel
|
|
242
|
+
* requests — the signed session and the 401 notification. Its key-share
|
|
243
|
+
* handlers stay attached until the client's own cleanup() has its ACK, so
|
|
244
|
+
* the iframe can still clear shares on logout.
|
|
245
|
+
*
|
|
246
|
+
* Returns false only if the attempt threw: the client may still be
|
|
247
|
+
* registered, so the caller must not revoke it. Never rethrows — this runs
|
|
248
|
+
* on the rotation and logout paths, where throwing would leave the caller
|
|
249
|
+
* with no client at all.
|
|
250
|
+
*/
|
|
251
|
+
detachWaasClient(client, reason) {
|
|
252
|
+
var _a;
|
|
253
|
+
// The pinned browser-wallet-client predates detach(); this goes away with
|
|
254
|
+
// the version bump.
|
|
255
|
+
const detachable = client;
|
|
256
|
+
try {
|
|
257
|
+
(_a = detachable === null || detachable === void 0 ? void 0 : detachable.detach) === null || _a === void 0 ? void 0 : _a.call(detachable);
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
this.instrument('[DynamicWaasMixin] WaaS client detach failed', Object.assign({ key: 'waas-client-detach-failed', operation: 'detachWaasClient', reason, time: 0 }, this.buildErrorInstrumentContext(error)));
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
240
265
|
getWaasWalletClient(traceContext_1) {
|
|
241
266
|
return __awaiter(this, arguments, void 0, function* (traceContext, { forceRebuild = false } = {}) {
|
|
242
267
|
var _a, _b;
|
|
@@ -246,11 +271,19 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
246
271
|
// available (see getWaasWalletConnector's live-token guard); otherwise
|
|
247
272
|
// createDynamicWaasClient would throw "Auth token is required".
|
|
248
273
|
if (forceRebuild) {
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
|
|
274
|
+
// Detach the superseded client, then revoke it — and never revoke one we
|
|
275
|
+
// did not detach. The reverse channel is page-wide and
|
|
276
|
+
// first-response-wins, so a revoked-but-still-attached client rejects
|
|
277
|
+
// instantly, beats the live client to every getSignedSessionId and
|
|
278
|
+
// poisons wallet creation for the life of the iframe. Two cases land
|
|
279
|
+
// there: a failed detach, and a concurrent rebuild, where
|
|
280
|
+
// createDynamicWaasClient has installed the new revoker but not yet
|
|
281
|
+
// returned the client it belongs to. The revoke stays as a guard for a
|
|
282
|
+
// caller still holding a direct reference.
|
|
283
|
+
const superseded = this.dynamicWaasClient;
|
|
284
|
+
if (superseded && this.detachWaasClient(superseded, 'force-rebuild')) {
|
|
285
|
+
(_a = this.revokeSignedSession) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
286
|
+
}
|
|
254
287
|
this.revokeSignedSession = undefined;
|
|
255
288
|
this.dynamicWaasClient = undefined;
|
|
256
289
|
}
|
|
@@ -770,7 +803,28 @@ const withDynamicWaas = (BaseClass) => {
|
|
|
770
803
|
});
|
|
771
804
|
}
|
|
772
805
|
}
|
|
773
|
-
|
|
806
|
+
// Detach synchronously: the cleanup() above removes the handlers too, but
|
|
807
|
+
// it is un-awaited and can sit on the channel's 5s timeout first, leaving
|
|
808
|
+
// this client in the race with its callback already revoked.
|
|
809
|
+
//
|
|
810
|
+
// Same guard as the rebuild path: never revoke a client we did not detach.
|
|
811
|
+
// waasClient is undefined whenever getWaasWalletClient threw (pending-auth
|
|
812
|
+
// scope, or a failed build), and a client installed concurrently would own
|
|
813
|
+
// the revoke we still hold — revoking that one while it is attached is the
|
|
814
|
+
// original bug.
|
|
815
|
+
const superseded = waasClient !== null && waasClient !== void 0 ? waasClient : this.dynamicWaasClient;
|
|
816
|
+
const detached = superseded
|
|
817
|
+
? this.detachWaasClient(superseded, 'end-session')
|
|
818
|
+
: false;
|
|
819
|
+
// Revoke only while the revoker still belongs to the client we detached.
|
|
820
|
+
// endSession awaits the client, the active address and the key-share
|
|
821
|
+
// removal, and a rotation completing in any of those windows swaps both
|
|
822
|
+
// fields — revoking the live replacement while it is attached is the
|
|
823
|
+
// original bug. Detaching the captured client is unconditional: it is
|
|
824
|
+
// always safe, and it is the half that actually leaves the race.
|
|
825
|
+
if (detached && superseded === this.dynamicWaasClient) {
|
|
826
|
+
(_a = this.revokeSignedSession) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
827
|
+
}
|
|
774
828
|
this.revokeSignedSession = undefined;
|
|
775
829
|
this.dynamicWaasClient = undefined;
|
|
776
830
|
});
|