@abstraxn/signer-react 3.3.5 → 3.3.6
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 +9 -0
- package/dist/src/components/AbstraxnProvider/AbstraxnProvider.js +4 -0
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js +17 -1
- package/dist/src/hooks.d.ts +24 -24
- package/dist/src/wagmiConfig.js +2 -13
- package/dist/src/walletConnectMobile.d.ts +46 -0
- package/dist/src/walletConnectMobile.js +170 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ 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.6] - 2026-09-14
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **WalletConnect mobile approve/reject never returned to the dapp** – After a WalletConnect action deeplinked to MetaMask (or another wallet) on iOS/Android, the browser dropped the relay WebSocket. Approve and reject results never reached the in-flight `signMessage` / `sendTransaction` / `writeContract` promise. The SDK now resumes the WalletConnect relay when the tab becomes visible again and before user-approval requests, and no longer treats a transport drop as a session disconnect.
|
|
12
|
+
- **WalletConnect iOS return opened Safari on the homepage** – Return metadata used `location.origin`, so MetaMask opened Safari at `/` and reloaded the app (lost in-memory UI state). Metadata now uses the current page URL. On iOS Chrome/Firefox/Edge/Brave/Opera, `redirect.native` is the source browser app scheme with no path so the existing tab can be foregrounded. On Safari, `redirect.universal` is omitted so the wallet can return to the same tab instead of navigating to `/`. If a wallet still lands on the homepage, the SDK restores the page the user transacted from.
|
|
13
|
+
|
|
14
|
+
### Notes
|
|
15
|
+
- Disconnect and reconnect WalletConnect once after upgrading so the wallet stores the new return metadata. Existing sessions keep the old homepage/Safari redirect until re-paired.
|
|
16
|
+
|
|
8
17
|
## [3.3.4] - 2026-08-31
|
|
9
18
|
|
|
10
19
|
### Fixed
|
|
@@ -10,6 +10,7 @@ import { EVM_CHAINS, toCoreChain } from "../../chains";
|
|
|
10
10
|
import { AbstraxnProviderWithWagmi } from "./AbstraxnProviderWithWagmi";
|
|
11
11
|
import { AbstraxnProviderWithoutWagmi } from "./AbstraxnProviderWithoutWagmi";
|
|
12
12
|
import { useQueryClientSafe, QueryClientWrapper, canUseReactQuery } from "./utils";
|
|
13
|
+
import { restoreAfterWalletRedirect } from "../../walletConnectMobile";
|
|
13
14
|
import { ConnectionProvider, WalletProvider } from "@solana/wallet-adapter-react";
|
|
14
15
|
import { PhantomWalletAdapter, SolflareWalletAdapter } from "@solana/wallet-adapter-wallets";
|
|
15
16
|
export function AbstraxnProvider({ config, children }) {
|
|
@@ -26,6 +27,9 @@ export function AbstraxnProvider({ config, children }) {
|
|
|
26
27
|
const [isHydrated, setIsHydrated] = useState(() => {
|
|
27
28
|
return typeof window !== 'undefined';
|
|
28
29
|
});
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
restoreAfterWalletRedirect();
|
|
32
|
+
}, []);
|
|
29
33
|
useEffect(() => {
|
|
30
34
|
if (externalSsr && typeof window !== 'undefined' && !isHydrated) {
|
|
31
35
|
// Wait for wallet injection scripts to run (Phantom, etc.)
|
|
@@ -12,7 +12,7 @@ import { ExternalWalletButtons, resetExternalWalletViewState, } from "../../Exte
|
|
|
12
12
|
import { EVM_CHAINS, SOLANA_CHAINS, getChainById, toCoreChain, } from "../../chains";
|
|
13
13
|
import { AbstraxnContext } from "./context";
|
|
14
14
|
import { isLinkAuthCallback } from "./utils";
|
|
15
|
-
import { hasActiveWalletConnectSession, hasPendingWalletConnectApproval, isWalletConnectConnector, patchWalletConnectProviderForMobile, resumeWalletConnectRelayer, subscribeWalletConnectForegroundResume, } from "../../walletConnectMobile";
|
|
15
|
+
import { hasActiveWalletConnectSession, hasPendingWalletConnectApproval, isWalletConnectConnector, patchWalletConnectProviderForMobile, rememberCurrentPageForWalletReturn, resumeWalletConnectRelayer, subscribeWalletConnectForegroundResume, syncWalletConnectDappRedirect, } from "../../walletConnectMobile";
|
|
16
16
|
/** Syncs wagmi disconnect to external wallet state; only rendered when wagmi is available (under WagmiProvider). */
|
|
17
17
|
function WagmiConnectionEffectSync({ onDisconnect, }) {
|
|
18
18
|
useConnectionEffect({ onDisconnect });
|
|
@@ -2878,6 +2878,21 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2878
2878
|
});
|
|
2879
2879
|
}
|
|
2880
2880
|
try {
|
|
2881
|
+
if (isWalletConnectConnector) {
|
|
2882
|
+
rememberCurrentPageForWalletReturn();
|
|
2883
|
+
try {
|
|
2884
|
+
if (typeof connector.getProvider === "function") {
|
|
2885
|
+
const provider = await connector.getProvider();
|
|
2886
|
+
if (provider) {
|
|
2887
|
+
syncWalletConnectDappRedirect(provider);
|
|
2888
|
+
patchWalletConnectProviderForMobile(provider);
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
catch {
|
|
2893
|
+
// Provider may not exist until after connect.
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2881
2896
|
// Use connectAsync to properly await the connection
|
|
2882
2897
|
const result = await wagmiConnect.connectAsync({ connector });
|
|
2883
2898
|
// Use the result directly to set state immediately
|
|
@@ -3187,6 +3202,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3187
3202
|
const isWc = isWalletConnectConnector(connector);
|
|
3188
3203
|
if (isWc) {
|
|
3189
3204
|
wcProviderRef.current = p;
|
|
3205
|
+
syncWalletConnectDappRedirect(p);
|
|
3190
3206
|
patchWalletConnectProviderForMobile(p);
|
|
3191
3207
|
unsubscribeForeground = subscribeWalletConnectForegroundResume(p);
|
|
3192
3208
|
if (!mounted) {
|
package/dist/src/hooks.d.ts
CHANGED
|
@@ -358,16 +358,16 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
358
358
|
withdrawals?: import("viem").Withdrawal[] | undefined | undefined;
|
|
359
359
|
withdrawalsRoot?: `0x${string}` | undefined;
|
|
360
360
|
transactions: includeTransactions extends true ? ({
|
|
361
|
+
input: import("viem").Hex;
|
|
362
|
+
s: import("viem").Hex;
|
|
361
363
|
type: "legacy";
|
|
362
364
|
value: bigint;
|
|
363
365
|
yParity?: undefined | undefined;
|
|
364
366
|
from: Address;
|
|
365
367
|
gas: bigint;
|
|
366
368
|
hash: import("viem").Hash;
|
|
367
|
-
input: import("viem").Hex;
|
|
368
369
|
nonce: number;
|
|
369
370
|
r: import("viem").Hex;
|
|
370
|
-
s: import("viem").Hex;
|
|
371
371
|
to: Address | null;
|
|
372
372
|
typeHex: import("viem").Hex | null;
|
|
373
373
|
v: bigint;
|
|
@@ -383,16 +383,16 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
383
383
|
blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
|
|
384
384
|
transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
|
|
385
385
|
} | {
|
|
386
|
+
input: import("viem").Hex;
|
|
387
|
+
s: import("viem").Hex;
|
|
386
388
|
type: "eip2930";
|
|
387
389
|
value: bigint;
|
|
388
390
|
yParity: number;
|
|
389
391
|
from: Address;
|
|
390
392
|
gas: bigint;
|
|
391
393
|
hash: import("viem").Hash;
|
|
392
|
-
input: import("viem").Hex;
|
|
393
394
|
nonce: number;
|
|
394
395
|
r: import("viem").Hex;
|
|
395
|
-
s: import("viem").Hex;
|
|
396
396
|
to: Address | null;
|
|
397
397
|
typeHex: import("viem").Hex | null;
|
|
398
398
|
v: bigint;
|
|
@@ -408,16 +408,16 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
408
408
|
blockNumber: (blockTag extends "pending" ? true : false) extends infer T_4 ? T_4 extends (blockTag extends "pending" ? true : false) ? T_4 extends true ? null : bigint : never : never;
|
|
409
409
|
transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_5 ? T_5 extends (blockTag extends "pending" ? true : false) ? T_5 extends true ? null : number : never : never;
|
|
410
410
|
} | {
|
|
411
|
+
input: import("viem").Hex;
|
|
412
|
+
s: import("viem").Hex;
|
|
411
413
|
type: "eip1559";
|
|
412
414
|
value: bigint;
|
|
413
415
|
yParity: number;
|
|
414
416
|
from: Address;
|
|
415
417
|
gas: bigint;
|
|
416
418
|
hash: import("viem").Hash;
|
|
417
|
-
input: import("viem").Hex;
|
|
418
419
|
nonce: number;
|
|
419
420
|
r: import("viem").Hex;
|
|
420
|
-
s: import("viem").Hex;
|
|
421
421
|
to: Address | null;
|
|
422
422
|
typeHex: import("viem").Hex | null;
|
|
423
423
|
v: bigint;
|
|
@@ -433,16 +433,16 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
433
433
|
blockNumber: (blockTag extends "pending" ? true : false) extends infer T_7 ? T_7 extends (blockTag extends "pending" ? true : false) ? T_7 extends true ? null : bigint : never : never;
|
|
434
434
|
transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_8 ? T_8 extends (blockTag extends "pending" ? true : false) ? T_8 extends true ? null : number : never : never;
|
|
435
435
|
} | {
|
|
436
|
+
input: import("viem").Hex;
|
|
437
|
+
s: import("viem").Hex;
|
|
436
438
|
type: "eip4844";
|
|
437
439
|
value: bigint;
|
|
438
440
|
yParity: number;
|
|
439
441
|
from: Address;
|
|
440
442
|
gas: bigint;
|
|
441
443
|
hash: import("viem").Hash;
|
|
442
|
-
input: import("viem").Hex;
|
|
443
444
|
nonce: number;
|
|
444
445
|
r: import("viem").Hex;
|
|
445
|
-
s: import("viem").Hex;
|
|
446
446
|
to: Address | null;
|
|
447
447
|
typeHex: import("viem").Hex | null;
|
|
448
448
|
v: bigint;
|
|
@@ -458,16 +458,16 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
458
458
|
blockNumber: (blockTag extends "pending" ? true : false) extends infer T_10 ? T_10 extends (blockTag extends "pending" ? true : false) ? T_10 extends true ? null : bigint : never : never;
|
|
459
459
|
transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_11 ? T_11 extends (blockTag extends "pending" ? true : false) ? T_11 extends true ? null : number : never : never;
|
|
460
460
|
} | {
|
|
461
|
+
input: import("viem").Hex;
|
|
462
|
+
s: import("viem").Hex;
|
|
461
463
|
type: "eip7702";
|
|
462
464
|
value: bigint;
|
|
463
465
|
yParity: number;
|
|
464
466
|
from: Address;
|
|
465
467
|
gas: bigint;
|
|
466
468
|
hash: import("viem").Hash;
|
|
467
|
-
input: import("viem").Hex;
|
|
468
469
|
nonce: number;
|
|
469
470
|
r: import("viem").Hex;
|
|
470
|
-
s: import("viem").Hex;
|
|
471
471
|
to: Address | null;
|
|
472
472
|
typeHex: import("viem").Hex | null;
|
|
473
473
|
v: bigint;
|
|
@@ -508,16 +508,16 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
508
508
|
} | undefined) => Promise<import("viem").EstimateMaxPriorityFeePerGasReturnType>;
|
|
509
509
|
getStorageAt: (args: import("viem").GetStorageAtParameters) => Promise<import("viem").GetStorageAtReturnType>;
|
|
510
510
|
getTransaction: <blockTag extends import("viem").BlockTag = "latest">(args: import("viem").GetTransactionParameters<blockTag>) => Promise<{
|
|
511
|
+
input: import("viem").Hex;
|
|
512
|
+
s: import("viem").Hex;
|
|
511
513
|
type: "legacy";
|
|
512
514
|
value: bigint;
|
|
513
515
|
yParity?: undefined | undefined;
|
|
514
516
|
from: Address;
|
|
515
517
|
gas: bigint;
|
|
516
518
|
hash: import("viem").Hash;
|
|
517
|
-
input: import("viem").Hex;
|
|
518
519
|
nonce: number;
|
|
519
520
|
r: import("viem").Hex;
|
|
520
|
-
s: import("viem").Hex;
|
|
521
521
|
to: Address | null;
|
|
522
522
|
typeHex: import("viem").Hex | null;
|
|
523
523
|
v: bigint;
|
|
@@ -533,16 +533,16 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
533
533
|
blockNumber: (blockTag extends "pending" ? true : false) extends infer T_1 ? T_1 extends (blockTag extends "pending" ? true : false) ? T_1 extends true ? null : bigint : never : never;
|
|
534
534
|
transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_2 ? T_2 extends (blockTag extends "pending" ? true : false) ? T_2 extends true ? null : number : never : never;
|
|
535
535
|
} | {
|
|
536
|
+
input: import("viem").Hex;
|
|
537
|
+
s: import("viem").Hex;
|
|
536
538
|
type: "eip2930";
|
|
537
539
|
value: bigint;
|
|
538
540
|
yParity: number;
|
|
539
541
|
from: Address;
|
|
540
542
|
gas: bigint;
|
|
541
543
|
hash: import("viem").Hash;
|
|
542
|
-
input: import("viem").Hex;
|
|
543
544
|
nonce: number;
|
|
544
545
|
r: import("viem").Hex;
|
|
545
|
-
s: import("viem").Hex;
|
|
546
546
|
to: Address | null;
|
|
547
547
|
typeHex: import("viem").Hex | null;
|
|
548
548
|
v: bigint;
|
|
@@ -558,16 +558,16 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
558
558
|
blockNumber: (blockTag extends "pending" ? true : false) extends infer T_4 ? T_4 extends (blockTag extends "pending" ? true : false) ? T_4 extends true ? null : bigint : never : never;
|
|
559
559
|
transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_5 ? T_5 extends (blockTag extends "pending" ? true : false) ? T_5 extends true ? null : number : never : never;
|
|
560
560
|
} | {
|
|
561
|
+
input: import("viem").Hex;
|
|
562
|
+
s: import("viem").Hex;
|
|
561
563
|
type: "eip1559";
|
|
562
564
|
value: bigint;
|
|
563
565
|
yParity: number;
|
|
564
566
|
from: Address;
|
|
565
567
|
gas: bigint;
|
|
566
568
|
hash: import("viem").Hash;
|
|
567
|
-
input: import("viem").Hex;
|
|
568
569
|
nonce: number;
|
|
569
570
|
r: import("viem").Hex;
|
|
570
|
-
s: import("viem").Hex;
|
|
571
571
|
to: Address | null;
|
|
572
572
|
typeHex: import("viem").Hex | null;
|
|
573
573
|
v: bigint;
|
|
@@ -583,16 +583,16 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
583
583
|
blockNumber: (blockTag extends "pending" ? true : false) extends infer T_7 ? T_7 extends (blockTag extends "pending" ? true : false) ? T_7 extends true ? null : bigint : never : never;
|
|
584
584
|
transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_8 ? T_8 extends (blockTag extends "pending" ? true : false) ? T_8 extends true ? null : number : never : never;
|
|
585
585
|
} | {
|
|
586
|
+
input: import("viem").Hex;
|
|
587
|
+
s: import("viem").Hex;
|
|
586
588
|
type: "eip4844";
|
|
587
589
|
value: bigint;
|
|
588
590
|
yParity: number;
|
|
589
591
|
from: Address;
|
|
590
592
|
gas: bigint;
|
|
591
593
|
hash: import("viem").Hash;
|
|
592
|
-
input: import("viem").Hex;
|
|
593
594
|
nonce: number;
|
|
594
595
|
r: import("viem").Hex;
|
|
595
|
-
s: import("viem").Hex;
|
|
596
596
|
to: Address | null;
|
|
597
597
|
typeHex: import("viem").Hex | null;
|
|
598
598
|
v: bigint;
|
|
@@ -608,16 +608,16 @@ export declare function usePublicClient(chain: Chain, rpcUrl: string): {
|
|
|
608
608
|
blockNumber: (blockTag extends "pending" ? true : false) extends infer T_10 ? T_10 extends (blockTag extends "pending" ? true : false) ? T_10 extends true ? null : bigint : never : never;
|
|
609
609
|
transactionIndex: (blockTag extends "pending" ? true : false) extends infer T_11 ? T_11 extends (blockTag extends "pending" ? true : false) ? T_11 extends true ? null : number : never : never;
|
|
610
610
|
} | {
|
|
611
|
+
input: import("viem").Hex;
|
|
612
|
+
s: import("viem").Hex;
|
|
611
613
|
type: "eip7702";
|
|
612
614
|
value: bigint;
|
|
613
615
|
yParity: number;
|
|
614
616
|
from: Address;
|
|
615
617
|
gas: bigint;
|
|
616
618
|
hash: import("viem").Hash;
|
|
617
|
-
input: import("viem").Hex;
|
|
618
619
|
nonce: number;
|
|
619
620
|
r: import("viem").Hex;
|
|
620
|
-
s: import("viem").Hex;
|
|
621
621
|
to: Address | null;
|
|
622
622
|
typeHex: import("viem").Hex | null;
|
|
623
623
|
v: bigint;
|
|
@@ -8162,9 +8162,9 @@ export declare function useWalletClient(chain: any, rpcUrl?: string): {
|
|
|
8162
8162
|
[x: `address[${string}]`]: undefined;
|
|
8163
8163
|
[x: `bool[${string}]`]: undefined;
|
|
8164
8164
|
[x: `bytes[${string}]`]: undefined;
|
|
8165
|
+
[x: `bytes3[${string}]`]: undefined;
|
|
8165
8166
|
[x: `bytes1[${string}]`]: undefined;
|
|
8166
8167
|
[x: `bytes2[${string}]`]: undefined;
|
|
8167
|
-
[x: `bytes3[${string}]`]: undefined;
|
|
8168
8168
|
[x: `bytes4[${string}]`]: undefined;
|
|
8169
8169
|
[x: `bytes5[${string}]`]: undefined;
|
|
8170
8170
|
[x: `bytes6[${string}]`]: undefined;
|
|
@@ -8264,9 +8264,9 @@ export declare function useWalletClient(chain: any, rpcUrl?: string): {
|
|
|
8264
8264
|
address?: undefined;
|
|
8265
8265
|
bool?: undefined;
|
|
8266
8266
|
bytes?: undefined;
|
|
8267
|
+
bytes3?: undefined;
|
|
8267
8268
|
bytes1?: undefined;
|
|
8268
8269
|
bytes2?: undefined;
|
|
8269
|
-
bytes3?: undefined;
|
|
8270
8270
|
bytes4?: undefined;
|
|
8271
8271
|
bytes5?: undefined;
|
|
8272
8272
|
bytes6?: undefined;
|
|
@@ -13137,9 +13137,9 @@ export declare function useExternalWalletClient(): {
|
|
|
13137
13137
|
[x: `address[${string}]`]: undefined;
|
|
13138
13138
|
[x: `bool[${string}]`]: undefined;
|
|
13139
13139
|
[x: `bytes[${string}]`]: undefined;
|
|
13140
|
+
[x: `bytes3[${string}]`]: undefined;
|
|
13140
13141
|
[x: `bytes1[${string}]`]: undefined;
|
|
13141
13142
|
[x: `bytes2[${string}]`]: undefined;
|
|
13142
|
-
[x: `bytes3[${string}]`]: undefined;
|
|
13143
13143
|
[x: `bytes4[${string}]`]: undefined;
|
|
13144
13144
|
[x: `bytes5[${string}]`]: undefined;
|
|
13145
13145
|
[x: `bytes6[${string}]`]: undefined;
|
|
@@ -13239,9 +13239,9 @@ export declare function useExternalWalletClient(): {
|
|
|
13239
13239
|
address?: undefined;
|
|
13240
13240
|
bool?: undefined;
|
|
13241
13241
|
bytes?: undefined;
|
|
13242
|
+
bytes3?: undefined;
|
|
13242
13243
|
bytes1?: undefined;
|
|
13243
13244
|
bytes2?: undefined;
|
|
13244
|
-
bytes3?: undefined;
|
|
13245
13245
|
bytes4?: undefined;
|
|
13246
13246
|
bytes5?: undefined;
|
|
13247
13247
|
bytes6?: undefined;
|
package/dist/src/wagmiConfig.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { createConfig, createStorage, http, cookieStorage, } from "@wagmi/core";
|
|
5
5
|
import { injected, walletConnect } from "wagmi/connectors";
|
|
6
6
|
import { SUPPORTED_CHAINS, } from "@abstraxn/signer-core";
|
|
7
|
+
import { createWalletConnectDappMetadata } from "./walletConnectMobile";
|
|
7
8
|
/**
|
|
8
9
|
* Convert internal Chain type to viem Chain type
|
|
9
10
|
* Uses viem's built-in chain definitions when available for better compatibility
|
|
@@ -77,21 +78,9 @@ export function createWagmiConfig(chains, walletConnectProjectId, enabledConnect
|
|
|
77
78
|
console.warn("WalletConnect project ID is required for WalletConnect connector. Skipping...");
|
|
78
79
|
}
|
|
79
80
|
else {
|
|
80
|
-
const dappUrl = typeof window !== "undefined"
|
|
81
|
-
? window.location.origin
|
|
82
|
-
: "https://abstraxn.com";
|
|
83
81
|
connectors.push(walletConnect({
|
|
84
82
|
projectId: walletConnectProjectId,
|
|
85
|
-
metadata:
|
|
86
|
-
name: "Abstraxn",
|
|
87
|
-
description: "Abstraxn Wallet",
|
|
88
|
-
url: dappUrl,
|
|
89
|
-
icons: ["https://avatars.githubusercontent.com/u/37784886"],
|
|
90
|
-
// Helps mobile wallets (MetaMask) return to this dapp after approve/reject.
|
|
91
|
-
redirect: {
|
|
92
|
-
universal: dappUrl,
|
|
93
|
-
},
|
|
94
|
-
},
|
|
83
|
+
metadata: createWalletConnectDappMetadata(),
|
|
95
84
|
showQrModal: true,
|
|
96
85
|
qrModalOptions: {
|
|
97
86
|
themeMode: theme === "dark" ? "dark" : "light",
|
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
* WebSocket when the user is sent to MetaMask (or another wallet) via deeplink.
|
|
6
6
|
* The wallet still approves/rejects, but the in-flight JSON-RPC promise never
|
|
7
7
|
* settles unless the relay is resumed when the dapp becomes visible again.
|
|
8
|
+
*
|
|
9
|
+
* After approve/reject, MetaMask opens metadata.redirect / metadata.url. Using
|
|
10
|
+
* only `location.origin` sends iOS users to Safari on the homepage (full reload,
|
|
11
|
+
* lost React state). We:
|
|
12
|
+
* - keep metadata.url as the current page (not origin)
|
|
13
|
+
* - on iOS Chrome/Firefox/etc. set redirect.native to the browser app scheme
|
|
14
|
+
* with no path, so the existing tab is foregrounded
|
|
15
|
+
* - on Safari omit redirect so MetaMask can `goBack()` to the same tab
|
|
8
16
|
*/
|
|
9
17
|
/** Selectors used to close/restore Reown AppKit + WalletConnect modal DOM. */
|
|
10
18
|
export declare const WALLETCONNECT_MODAL_SELECTORS: string[];
|
|
@@ -15,6 +23,44 @@ export declare function isWalletConnectConnector(connector: {
|
|
|
15
23
|
export declare function isUserApprovalRpcMethod(method: unknown): boolean;
|
|
16
24
|
export declare function hasPendingWalletConnectApproval(provider?: any): boolean;
|
|
17
25
|
export declare function hasActiveWalletConnectSession(provider: any): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Current dapp page, including path/query/hash. Never origin-only — that is
|
|
28
|
+
* what made MetaMask open the homepage after approve/reject.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getDappReturnUrl(): string;
|
|
31
|
+
/**
|
|
32
|
+
* iOS-only app scheme for the browser the user is actually in. No path:
|
|
33
|
+
* opening `googlechrome://` foregrounds Chrome's existing tab instead of
|
|
34
|
+
* navigating Safari to a new URL (which reloads and drops in-memory state).
|
|
35
|
+
*/
|
|
36
|
+
export declare function getSourceBrowserNativeRedirect(): string | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Lazy metadata so url/redirect are read at connect/request time, not at
|
|
39
|
+
* provider mount (which is often the homepage in Next.js layouts).
|
|
40
|
+
*/
|
|
41
|
+
export declare function createWalletConnectDappMetadata(): {
|
|
42
|
+
name: string;
|
|
43
|
+
description: string;
|
|
44
|
+
icons: string[];
|
|
45
|
+
url: string;
|
|
46
|
+
redirect?: {
|
|
47
|
+
native?: string;
|
|
48
|
+
universal?: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
export declare function rememberCurrentPageForWalletReturn(): void;
|
|
52
|
+
export declare function clearWalletReturnIfSameDocument(): void;
|
|
53
|
+
/**
|
|
54
|
+
* If the wallet opened a fresh Safari tab on the homepage, send the user back
|
|
55
|
+
* to the page they transacted from. This still reloads that page (React state
|
|
56
|
+
* cannot be recovered), but it is better than leaving them on `/`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function restoreAfterWalletRedirect(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Push the current page + source-browser scheme onto the live WC provider so
|
|
61
|
+
* MetaMask does not keep a stale homepage redirect from first init.
|
|
62
|
+
*/
|
|
63
|
+
export declare function syncWalletConnectDappRedirect(provider: any): void;
|
|
18
64
|
/**
|
|
19
65
|
* Re-open the WalletConnect relay after the mobile browser comes back
|
|
20
66
|
* from the wallet app so pending approve/reject responses can be delivered.
|
|
@@ -5,9 +5,20 @@
|
|
|
5
5
|
* WebSocket when the user is sent to MetaMask (or another wallet) via deeplink.
|
|
6
6
|
* The wallet still approves/rejects, but the in-flight JSON-RPC promise never
|
|
7
7
|
* settles unless the relay is resumed when the dapp becomes visible again.
|
|
8
|
+
*
|
|
9
|
+
* After approve/reject, MetaMask opens metadata.redirect / metadata.url. Using
|
|
10
|
+
* only `location.origin` sends iOS users to Safari on the homepage (full reload,
|
|
11
|
+
* lost React state). We:
|
|
12
|
+
* - keep metadata.url as the current page (not origin)
|
|
13
|
+
* - on iOS Chrome/Firefox/etc. set redirect.native to the browser app scheme
|
|
14
|
+
* with no path, so the existing tab is foregrounded
|
|
15
|
+
* - on Safari omit redirect so MetaMask can `goBack()` to the same tab
|
|
8
16
|
*/
|
|
9
17
|
const PATCHED_FLAG = "__abstraxnWcMobilePatched";
|
|
10
18
|
const PENDING_FLAG = "__abstraxnWcPendingApprovals";
|
|
19
|
+
const RETURN_HREF_KEY = "abstraxn_wc_return_href";
|
|
20
|
+
const RETURN_AT_KEY = "abstraxn_wc_return_at";
|
|
21
|
+
const RETURN_TTL_MS = 3 * 60 * 1000;
|
|
11
22
|
const USER_APPROVAL_METHODS = new Set([
|
|
12
23
|
"personal_sign",
|
|
13
24
|
"eth_sign",
|
|
@@ -69,6 +80,163 @@ export function hasActiveWalletConnectSession(provider) {
|
|
|
69
80
|
}
|
|
70
81
|
return true;
|
|
71
82
|
}
|
|
83
|
+
function isIOS() {
|
|
84
|
+
if (typeof navigator === "undefined")
|
|
85
|
+
return false;
|
|
86
|
+
const ua = navigator.userAgent || "";
|
|
87
|
+
const platform = navigator.platform || "";
|
|
88
|
+
return (/iPad|iPhone|iPod/i.test(ua) ||
|
|
89
|
+
(platform === "MacIntel" && (navigator.maxTouchPoints || 0) > 1));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Current dapp page, including path/query/hash. Never origin-only — that is
|
|
93
|
+
* what made MetaMask open the homepage after approve/reject.
|
|
94
|
+
*/
|
|
95
|
+
export function getDappReturnUrl() {
|
|
96
|
+
if (typeof window === "undefined")
|
|
97
|
+
return "https://abstraxn.com";
|
|
98
|
+
const url = new URL(window.location.href);
|
|
99
|
+
url.searchParams.delete("wc_ev");
|
|
100
|
+
url.searchParams.delete("wc_res");
|
|
101
|
+
return `${url.origin}${url.pathname}${url.search}${url.hash}`;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* iOS-only app scheme for the browser the user is actually in. No path:
|
|
105
|
+
* opening `googlechrome://` foregrounds Chrome's existing tab instead of
|
|
106
|
+
* navigating Safari to a new URL (which reloads and drops in-memory state).
|
|
107
|
+
*/
|
|
108
|
+
export function getSourceBrowserNativeRedirect() {
|
|
109
|
+
if (typeof navigator === "undefined" || !isIOS())
|
|
110
|
+
return undefined;
|
|
111
|
+
const ua = navigator.userAgent || "";
|
|
112
|
+
if (/FxiOS/i.test(ua))
|
|
113
|
+
return "firefox://";
|
|
114
|
+
if (/EdgiOS/i.test(ua))
|
|
115
|
+
return "microsoft-edge://";
|
|
116
|
+
if (/OPiOS/i.test(ua) || /OPT\//i.test(ua))
|
|
117
|
+
return "touch://";
|
|
118
|
+
if (/Brave/i.test(ua))
|
|
119
|
+
return "brave://";
|
|
120
|
+
if (/CriOS/i.test(ua))
|
|
121
|
+
return "googlechrome://";
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
function getWalletConnectRedirect() {
|
|
125
|
+
const native = getSourceBrowserNativeRedirect();
|
|
126
|
+
return native ? { native } : undefined;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Lazy metadata so url/redirect are read at connect/request time, not at
|
|
130
|
+
* provider mount (which is often the homepage in Next.js layouts).
|
|
131
|
+
*/
|
|
132
|
+
export function createWalletConnectDappMetadata() {
|
|
133
|
+
return {
|
|
134
|
+
name: "Abstraxn",
|
|
135
|
+
description: "Abstraxn Wallet",
|
|
136
|
+
icons: ["https://avatars.githubusercontent.com/u/37784886"],
|
|
137
|
+
get url() {
|
|
138
|
+
return getDappReturnUrl();
|
|
139
|
+
},
|
|
140
|
+
get redirect() {
|
|
141
|
+
return getWalletConnectRedirect();
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export function rememberCurrentPageForWalletReturn() {
|
|
146
|
+
if (typeof window === "undefined")
|
|
147
|
+
return;
|
|
148
|
+
try {
|
|
149
|
+
window.localStorage.setItem(RETURN_HREF_KEY, getDappReturnUrl());
|
|
150
|
+
window.localStorage.setItem(RETURN_AT_KEY, String(Date.now()));
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// Ignore quota / private-mode errors.
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export function clearWalletReturnIfSameDocument() {
|
|
157
|
+
if (typeof window === "undefined")
|
|
158
|
+
return;
|
|
159
|
+
try {
|
|
160
|
+
const saved = window.localStorage.getItem(RETURN_HREF_KEY);
|
|
161
|
+
if (!saved)
|
|
162
|
+
return;
|
|
163
|
+
const savedUrl = new URL(saved, window.location.origin);
|
|
164
|
+
if (savedUrl.origin !== window.location.origin)
|
|
165
|
+
return;
|
|
166
|
+
if (savedUrl.pathname === window.location.pathname &&
|
|
167
|
+
savedUrl.search === window.location.search &&
|
|
168
|
+
savedUrl.hash === window.location.hash) {
|
|
169
|
+
window.localStorage.removeItem(RETURN_HREF_KEY);
|
|
170
|
+
window.localStorage.removeItem(RETURN_AT_KEY);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// Ignore
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* If the wallet opened a fresh Safari tab on the homepage, send the user back
|
|
179
|
+
* to the page they transacted from. This still reloads that page (React state
|
|
180
|
+
* cannot be recovered), but it is better than leaving them on `/`.
|
|
181
|
+
*/
|
|
182
|
+
export function restoreAfterWalletRedirect() {
|
|
183
|
+
if (typeof window === "undefined")
|
|
184
|
+
return;
|
|
185
|
+
try {
|
|
186
|
+
const at = Number(window.localStorage.getItem(RETURN_AT_KEY) || 0);
|
|
187
|
+
const saved = window.localStorage.getItem(RETURN_HREF_KEY);
|
|
188
|
+
if (!saved || !at || Date.now() - at > RETURN_TTL_MS) {
|
|
189
|
+
window.localStorage.removeItem(RETURN_HREF_KEY);
|
|
190
|
+
window.localStorage.removeItem(RETURN_AT_KEY);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const savedUrl = new URL(saved, window.location.origin);
|
|
194
|
+
if (savedUrl.origin !== window.location.origin) {
|
|
195
|
+
window.localStorage.removeItem(RETURN_HREF_KEY);
|
|
196
|
+
window.localStorage.removeItem(RETURN_AT_KEY);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const savedPath = `${savedUrl.pathname}${savedUrl.search}${savedUrl.hash}`;
|
|
200
|
+
const currentPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;
|
|
201
|
+
if (savedPath === currentPath) {
|
|
202
|
+
window.localStorage.removeItem(RETURN_HREF_KEY);
|
|
203
|
+
window.localStorage.removeItem(RETURN_AT_KEY);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
window.localStorage.removeItem(RETURN_HREF_KEY);
|
|
207
|
+
window.localStorage.removeItem(RETURN_AT_KEY);
|
|
208
|
+
window.location.replace(savedUrl.href);
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Ignore
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function applyDappMetadata(meta, url, redirect) {
|
|
215
|
+
if (!meta || typeof meta !== "object")
|
|
216
|
+
return;
|
|
217
|
+
meta.url = url;
|
|
218
|
+
if (redirect) {
|
|
219
|
+
meta.redirect = { native: redirect.native };
|
|
220
|
+
}
|
|
221
|
+
else if (meta.redirect) {
|
|
222
|
+
delete meta.redirect;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Push the current page + source-browser scheme onto the live WC provider so
|
|
227
|
+
* MetaMask does not keep a stale homepage redirect from first init.
|
|
228
|
+
*/
|
|
229
|
+
export function syncWalletConnectDappRedirect(provider) {
|
|
230
|
+
if (!provider || typeof window === "undefined")
|
|
231
|
+
return;
|
|
232
|
+
const url = getDappReturnUrl();
|
|
233
|
+
const redirect = getWalletConnectRedirect();
|
|
234
|
+
rememberCurrentPageForWalletReturn();
|
|
235
|
+
applyDappMetadata(provider.metadata, url, redirect);
|
|
236
|
+
applyDappMetadata(provider.signer?.metadata, url, redirect);
|
|
237
|
+
applyDappMetadata(provider.session?.self?.metadata, url, redirect);
|
|
238
|
+
applyDappMetadata(provider.signer?.session?.self?.metadata, url, redirect);
|
|
239
|
+
}
|
|
72
240
|
function getWalletConnectRelayer(provider) {
|
|
73
241
|
return (provider?.signer?.client?.core?.relayer ||
|
|
74
242
|
provider?.client?.core?.relayer ||
|
|
@@ -184,6 +352,7 @@ export function patchWalletConnectProviderForMobile(provider) {
|
|
|
184
352
|
}
|
|
185
353
|
provider[PENDING_FLAG] = (provider[PENDING_FLAG] || 0) + 1;
|
|
186
354
|
restoreWalletConnectModal();
|
|
355
|
+
syncWalletConnectDappRedirect(provider);
|
|
187
356
|
try {
|
|
188
357
|
await resumeWalletConnectRelayer(provider);
|
|
189
358
|
return await originalRequest(...args);
|
|
@@ -205,6 +374,7 @@ export function subscribeWalletConnectForegroundResume(provider) {
|
|
|
205
374
|
if (timer)
|
|
206
375
|
clearTimeout(timer);
|
|
207
376
|
timer = setTimeout(() => {
|
|
377
|
+
clearWalletReturnIfSameDocument();
|
|
208
378
|
void resumeWalletConnectRelayer(provider);
|
|
209
379
|
if (hasPendingWalletConnectApproval(provider)) {
|
|
210
380
|
restoreWalletConnectModal();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abstraxn/signer-react",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.6",
|
|
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",
|