@abstraxn/signer-react 3.3.7 → 3.3.8
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 +5 -0
- package/dist/src/walletConnectMobile.d.ts +6 -0
- package/dist/src/walletConnectMobile.js +109 -21
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.3.8] - 2026-09-16
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **Create Proposal never opened MetaMask (loader stuck)** – 3.3.7 force-restarted the WalletConnect relay after every return from the wallet, including after *connect*. That restart raced the next `session_request`, so Create Proposal never deeplinked to MetaMask on iOS/Android. Relay restart now happens only for an in-flight approval. New transactions send first, then explicitly open the connected wallet app so the confirmation popup appears.
|
|
12
|
+
|
|
8
13
|
## [3.3.7] - 2026-09-15
|
|
9
14
|
|
|
10
15
|
### Fixed
|
|
@@ -34,6 +34,12 @@ export declare function getDappReturnUrl(): string;
|
|
|
34
34
|
* navigating Safari to a new URL (which reloads and drops in-memory state).
|
|
35
35
|
*/
|
|
36
36
|
export declare function getSourceBrowserNativeRedirect(): string | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Open the already-connected wallet app so the user sees the confirmation UI.
|
|
39
|
+
* WalletConnect often sends the session_request but does not deeplink on a
|
|
40
|
+
* later tx if the QR modal is hidden — Create Proposal then sits on a loader.
|
|
41
|
+
*/
|
|
42
|
+
export declare function openConnectedWalletApp(provider: any): void;
|
|
37
43
|
/**
|
|
38
44
|
* Lazy metadata so url/redirect are read at connect/request time, not at
|
|
39
45
|
* provider mount (which is often the homepage in Next.js layouts).
|
|
@@ -123,6 +123,79 @@ export function getSourceBrowserNativeRedirect() {
|
|
|
123
123
|
return "googlechrome://";
|
|
124
124
|
return undefined;
|
|
125
125
|
}
|
|
126
|
+
function isAndroid() {
|
|
127
|
+
if (typeof navigator === "undefined")
|
|
128
|
+
return false;
|
|
129
|
+
return /Android/i.test(navigator.userAgent || "");
|
|
130
|
+
}
|
|
131
|
+
function isMobileDevice() {
|
|
132
|
+
return isIOS() || isAndroid();
|
|
133
|
+
}
|
|
134
|
+
function isWalletHttpDeepLink(url) {
|
|
135
|
+
try {
|
|
136
|
+
const host = new URL(url).hostname.toLowerCase();
|
|
137
|
+
return (host.includes("metamask.app.link") ||
|
|
138
|
+
host.includes("link.metamask.io") ||
|
|
139
|
+
host.includes("rainbow.me") ||
|
|
140
|
+
host.includes("link.trustwallet.com") ||
|
|
141
|
+
host.includes("walletconnect.com"));
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function canOpenAsWalletApp(url) {
|
|
148
|
+
if (!url)
|
|
149
|
+
return false;
|
|
150
|
+
if (/^https?:\/\//i.test(url))
|
|
151
|
+
return isWalletHttpDeepLink(url);
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Open the already-connected wallet app so the user sees the confirmation UI.
|
|
156
|
+
* WalletConnect often sends the session_request but does not deeplink on a
|
|
157
|
+
* later tx if the QR modal is hidden — Create Proposal then sits on a loader.
|
|
158
|
+
*/
|
|
159
|
+
export function openConnectedWalletApp(provider) {
|
|
160
|
+
if (typeof window === "undefined" || !isMobileDevice())
|
|
161
|
+
return;
|
|
162
|
+
restoreWalletConnectModal();
|
|
163
|
+
try {
|
|
164
|
+
if (typeof provider?.modal?.open === "function") {
|
|
165
|
+
void provider.modal.open();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// Modal may not exist after we force-hid it post-connect.
|
|
170
|
+
}
|
|
171
|
+
const peer = provider?.session?.peer?.metadata ??
|
|
172
|
+
provider?.signer?.session?.peer?.metadata;
|
|
173
|
+
const native = String(peer?.redirect?.native || "");
|
|
174
|
+
const universal = String(peer?.redirect?.universal || "");
|
|
175
|
+
const name = String(peer?.name || "").toLowerCase();
|
|
176
|
+
let target = "";
|
|
177
|
+
if (canOpenAsWalletApp(native))
|
|
178
|
+
target = native;
|
|
179
|
+
else if (canOpenAsWalletApp(universal))
|
|
180
|
+
target = universal;
|
|
181
|
+
else if (name.includes("metamask") || !name) {
|
|
182
|
+
target = isIOS() ? "metamask://" : "https://metamask.app.link/wc";
|
|
183
|
+
}
|
|
184
|
+
else if (name.includes("rainbow")) {
|
|
185
|
+
target = "rainbow://";
|
|
186
|
+
}
|
|
187
|
+
else if (name.includes("trust")) {
|
|
188
|
+
target = "trust://";
|
|
189
|
+
}
|
|
190
|
+
if (!target)
|
|
191
|
+
return;
|
|
192
|
+
try {
|
|
193
|
+
window.location.href = target;
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
// Ignore
|
|
197
|
+
}
|
|
198
|
+
}
|
|
126
199
|
function getWalletConnectRedirect() {
|
|
127
200
|
const native = getSourceBrowserNativeRedirect();
|
|
128
201
|
return native ? { native } : undefined;
|
|
@@ -292,16 +365,13 @@ export async function resumeWalletConnectRelayer(provider, options) {
|
|
|
292
365
|
}
|
|
293
366
|
const run = (async () => {
|
|
294
367
|
try {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
ping.call(relayer.provider.connection),
|
|
300
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error("ping timeout")), 1500)),
|
|
301
|
-
]);
|
|
368
|
+
// New requests must not restart a live session — that races the
|
|
369
|
+
// session_request and MetaMask never shows a confirmation popup.
|
|
370
|
+
if (!options?.force) {
|
|
371
|
+
if (isRelayerConnected(relayer))
|
|
302
372
|
return;
|
|
303
|
-
|
|
304
|
-
|
|
373
|
+
await restartWalletConnectTransport(relayer);
|
|
374
|
+
return;
|
|
305
375
|
}
|
|
306
376
|
await restartWalletConnectTransport(relayer);
|
|
307
377
|
const session = provider?.session ?? provider?.signer?.session;
|
|
@@ -396,16 +466,32 @@ export function patchWalletConnectProviderForMobile(provider) {
|
|
|
396
466
|
if (!isApproval && !wasBackgrounded) {
|
|
397
467
|
return originalRequest(...args);
|
|
398
468
|
}
|
|
469
|
+
if (!isApproval && wasBackgrounded) {
|
|
470
|
+
try {
|
|
471
|
+
await resumeWalletConnectRelayer(provider, { force: true });
|
|
472
|
+
}
|
|
473
|
+
finally {
|
|
474
|
+
provider[NEEDS_RESUME_FLAG] = false;
|
|
475
|
+
}
|
|
476
|
+
return originalRequest(...args);
|
|
477
|
+
}
|
|
399
478
|
if (isApproval) {
|
|
400
479
|
provider[PENDING_FLAG] = (provider[PENDING_FLAG] || 0) + 1;
|
|
401
480
|
restoreWalletConnectModal();
|
|
402
481
|
syncWalletConnectDappRedirect(provider);
|
|
403
482
|
}
|
|
404
483
|
try {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
484
|
+
// Never force-restart right before sending a new tx — that is what
|
|
485
|
+
// blocked the MetaMask popup on Create Proposal after 3.3.7.
|
|
486
|
+
await Promise.race([
|
|
487
|
+
resumeWalletConnectRelayer(provider, { force: false }),
|
|
488
|
+
new Promise((resolve) => setTimeout(resolve, 1000)),
|
|
489
|
+
]);
|
|
490
|
+
const resultPromise = originalRequest(...args);
|
|
491
|
+
if (typeof window !== "undefined") {
|
|
492
|
+
window.setTimeout(() => openConnectedWalletApp(provider), 400);
|
|
493
|
+
}
|
|
494
|
+
return await resultPromise;
|
|
409
495
|
}
|
|
410
496
|
finally {
|
|
411
497
|
if (isApproval) {
|
|
@@ -422,23 +508,25 @@ export function subscribeWalletConnectForegroundResume(provider) {
|
|
|
422
508
|
if (typeof window === "undefined" || !provider)
|
|
423
509
|
return () => { };
|
|
424
510
|
let timer = null;
|
|
425
|
-
let hiddenAt = 0;
|
|
426
511
|
const resume = () => {
|
|
427
512
|
if (timer)
|
|
428
513
|
clearTimeout(timer);
|
|
429
|
-
const hiddenMs = hiddenAt ? Date.now() - hiddenAt : 0;
|
|
430
514
|
const pending = hasPendingWalletConnectApproval(provider);
|
|
431
|
-
const
|
|
515
|
+
const needsResume = pending || !!provider[NEEDS_RESUME_FLAG];
|
|
516
|
+
// Do not restart after connect-only backgrounding — that broke the next
|
|
517
|
+
// session_request so MetaMask never opened for Create Proposal.
|
|
518
|
+
if (!needsResume) {
|
|
519
|
+
clearWalletReturnIfSameDocument();
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
432
522
|
timer = setTimeout(() => {
|
|
433
523
|
clearWalletReturnIfSameDocument();
|
|
434
|
-
void resumeWalletConnectRelayer(provider, { force });
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
}, pending || force ? 50 : 250);
|
|
524
|
+
void resumeWalletConnectRelayer(provider, { force: true });
|
|
525
|
+
restoreWalletConnectModal();
|
|
526
|
+
}, 50);
|
|
438
527
|
};
|
|
439
528
|
const onVisibility = () => {
|
|
440
529
|
if (document.visibilityState === "hidden") {
|
|
441
|
-
hiddenAt = Date.now();
|
|
442
530
|
if (hasPendingWalletConnectApproval(provider)) {
|
|
443
531
|
provider[NEEDS_RESUME_FLAG] = true;
|
|
444
532
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abstraxn/signer-react",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.8",
|
|
4
4
|
"description": "React SDK for Abstraxn Wallet - React components, hooks, and providers for seamless Web3 wallet integration",
|
|
5
5
|
"main": "./dist/src/index.js",
|
|
6
6
|
"module": "./dist/src/index.js",
|