@abstraxn/signer-react 3.3.4 → 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 +19 -2
- package/dist/src/components/AbstraxnProvider/AbstraxnProvider.js +4 -0
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js +66 -1
- package/dist/src/hooks.d.ts +24 -24
- package/dist/src/wagmiConfig.js +2 -8
- package/dist/src/walletConnectMobile.d.ts +83 -0
- package/dist/src/walletConnectMobile.js +399 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,11 +5,28 @@ 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
|
|
|
19
|
+
### Fixed
|
|
20
|
+
- **Passkey export/sign 401** — via `@abstraxn/signer-core@2.1.4`, passkey login
|
|
21
|
+
registers the IndexedDB session key on Turnkey after login (fixes
|
|
22
|
+
`PUBLIC_KEY_NOT_FOUND` on export, sign, and proxy).
|
|
23
|
+
|
|
10
24
|
### Changed
|
|
11
|
-
- Bumped `@abstraxn/signer-core` to `2.1.4
|
|
12
|
-
|
|
25
|
+
- Bumped `@abstraxn/signer-core` to `2.1.4`.
|
|
26
|
+
|
|
27
|
+
### Notes
|
|
28
|
+
- Deploy **wallet-service** with `POST /auth/passkey/register-session` before upgrading.
|
|
29
|
+
- Users on passkey must **log out and log in again** after upgrade.
|
|
13
30
|
|
|
14
31
|
## [3.3.3] - 2026-07-09
|
|
15
32
|
|
|
@@ -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,6 +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, rememberCurrentPageForWalletReturn, resumeWalletConnectRelayer, subscribeWalletConnectForegroundResume, syncWalletConnectDappRedirect, } from "../../walletConnectMobile";
|
|
15
16
|
/** Syncs wagmi disconnect to external wallet state; only rendered when wagmi is available (under WagmiProvider). */
|
|
16
17
|
function WagmiConnectionEffectSync({ onDisconnect, }) {
|
|
17
18
|
useConnectionEffect({ onDisconnect });
|
|
@@ -45,6 +46,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
45
46
|
const [emailForOtp, setEmailForOtpState] = useState("");
|
|
46
47
|
const explicitConnectionRef = useRef(false);
|
|
47
48
|
const autoDisconnectHandledRef = useRef(false);
|
|
49
|
+
const wcProviderRef = useRef(null);
|
|
48
50
|
useEffect(() => {
|
|
49
51
|
isExternalWalletConnectedRef.current = isExternalWalletConnected;
|
|
50
52
|
}, [isExternalWalletConnected]);
|
|
@@ -2555,6 +2557,14 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2555
2557
|
if (chainTypePref === "solana" && solana?.wallet?.connected) {
|
|
2556
2558
|
return;
|
|
2557
2559
|
}
|
|
2560
|
+
// Mobile WalletConnect: leaving the browser for MetaMask drops the relay
|
|
2561
|
+
// socket, which can make wagmi look disconnected even though the session
|
|
2562
|
+
// is still valid. Keep UI state and resume the relay instead of resetting.
|
|
2563
|
+
if (!wagmiAccount.isConnected &&
|
|
2564
|
+
hasActiveWalletConnectSession(wcProviderRef.current)) {
|
|
2565
|
+
void resumeWalletConnectRelayer(wcProviderRef.current);
|
|
2566
|
+
return;
|
|
2567
|
+
}
|
|
2558
2568
|
// Prevent auto-connect (but allow restoration from persistence)
|
|
2559
2569
|
// Only auto-disconnect if:
|
|
2560
2570
|
// 1. wagmiAccount is connected
|
|
@@ -2664,6 +2674,8 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2664
2674
|
// Close WalletConnect QR modal when connection detected via wagmi (e.g. Next.js hydration)
|
|
2665
2675
|
if (typeof document !== "undefined") {
|
|
2666
2676
|
const closeWcModalDom = () => {
|
|
2677
|
+
if (hasPendingWalletConnectApproval(wcProviderRef.current))
|
|
2678
|
+
return;
|
|
2667
2679
|
["w3m-modal", "w3m-modal-backdrop", "[data-w3m-modal]", ".w3m-modal", ".w3m-modal-backdrop", "[class*='w3m-modal']", "[class*='walletconnect-qrcode']"].forEach((sel) => {
|
|
2668
2680
|
try {
|
|
2669
2681
|
const el = document.querySelector(sel);
|
|
@@ -2866,6 +2878,21 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2866
2878
|
});
|
|
2867
2879
|
}
|
|
2868
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
|
+
}
|
|
2869
2896
|
// Use connectAsync to properly await the connection
|
|
2870
2897
|
const result = await wagmiConnect.connectAsync({ connector });
|
|
2871
2898
|
// Use the result directly to set state immediately
|
|
@@ -2931,9 +2958,15 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2931
2958
|
connectorName.includes("walletconnect");
|
|
2932
2959
|
if (isWalletConnectConnector) {
|
|
2933
2960
|
const closeWalletConnectModal = async () => {
|
|
2961
|
+
if (hasPendingWalletConnectApproval(wcProviderRef.current))
|
|
2962
|
+
return;
|
|
2934
2963
|
try {
|
|
2935
2964
|
if (typeof connector.getProvider === "function") {
|
|
2936
2965
|
const provider = await connector.getProvider();
|
|
2966
|
+
if (provider) {
|
|
2967
|
+
wcProviderRef.current = provider;
|
|
2968
|
+
patchWalletConnectProviderForMobile(provider);
|
|
2969
|
+
}
|
|
2937
2970
|
if (provider?.modal?.close) {
|
|
2938
2971
|
provider.modal.close();
|
|
2939
2972
|
}
|
|
@@ -3113,6 +3146,11 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3113
3146
|
const handleWagmiDisconnect = useCallback(() => {
|
|
3114
3147
|
if (!externalWalletsEnabledRef.current)
|
|
3115
3148
|
return;
|
|
3149
|
+
// Transport drop (mobile deeplink) is not a session disconnect.
|
|
3150
|
+
if (hasActiveWalletConnectSession(wcProviderRef.current)) {
|
|
3151
|
+
void resumeWalletConnectRelayer(wcProviderRef.current);
|
|
3152
|
+
return;
|
|
3153
|
+
}
|
|
3116
3154
|
setIsExternalWalletConnected(false);
|
|
3117
3155
|
setExternalWalletAddress(null);
|
|
3118
3156
|
setExternalWalletChainId(null);
|
|
@@ -3152,6 +3190,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3152
3190
|
}
|
|
3153
3191
|
const connector = wagmiAccount.connector;
|
|
3154
3192
|
let mounted = true;
|
|
3193
|
+
let unsubscribeForeground;
|
|
3155
3194
|
const setup = async () => {
|
|
3156
3195
|
try {
|
|
3157
3196
|
const getProvider = connector.getProvider ?? connector.getEthereumProvider;
|
|
@@ -3160,15 +3199,39 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3160
3199
|
const p = await getProvider();
|
|
3161
3200
|
if (!mounted || !p)
|
|
3162
3201
|
return;
|
|
3202
|
+
const isWc = isWalletConnectConnector(connector);
|
|
3203
|
+
if (isWc) {
|
|
3204
|
+
wcProviderRef.current = p;
|
|
3205
|
+
syncWalletConnectDappRedirect(p);
|
|
3206
|
+
patchWalletConnectProviderForMobile(p);
|
|
3207
|
+
unsubscribeForeground = subscribeWalletConnectForegroundResume(p);
|
|
3208
|
+
if (!mounted) {
|
|
3209
|
+
unsubscribeForeground();
|
|
3210
|
+
unsubscribeForeground = undefined;
|
|
3211
|
+
wcProviderRef.current = null;
|
|
3212
|
+
return;
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
else {
|
|
3216
|
+
wcProviderRef.current = null;
|
|
3217
|
+
}
|
|
3163
3218
|
const onDisconnectFromProvider = () => {
|
|
3164
3219
|
if (!isExternalWalletConnectedRef.current)
|
|
3165
3220
|
return;
|
|
3221
|
+
if (hasActiveWalletConnectSession(p)) {
|
|
3222
|
+
void resumeWalletConnectRelayer(p);
|
|
3223
|
+
return;
|
|
3224
|
+
}
|
|
3166
3225
|
handleWagmiDisconnect();
|
|
3167
3226
|
};
|
|
3168
3227
|
const onAccountsChanged = (accounts) => {
|
|
3169
3228
|
const list = Array.isArray(accounts) ? accounts : [];
|
|
3170
|
-
if (list.length === 0)
|
|
3229
|
+
if (list.length === 0) {
|
|
3230
|
+
// Empty accounts during mobile resume is often a transport blip.
|
|
3231
|
+
if (hasActiveWalletConnectSession(p))
|
|
3232
|
+
return;
|
|
3171
3233
|
onDisconnectFromProvider();
|
|
3234
|
+
}
|
|
3172
3235
|
};
|
|
3173
3236
|
p.on?.("accountsChanged", onAccountsChanged);
|
|
3174
3237
|
p.on?.("disconnect", onDisconnectFromProvider);
|
|
@@ -3188,6 +3251,8 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3188
3251
|
});
|
|
3189
3252
|
return () => {
|
|
3190
3253
|
mounted = false;
|
|
3254
|
+
unsubscribeForeground?.();
|
|
3255
|
+
wcProviderRef.current = null;
|
|
3191
3256
|
const cleanup = providerListenerCleanupRef.current;
|
|
3192
3257
|
providerListenerCleanupRef.current = null;
|
|
3193
3258
|
if (typeof cleanup === "function")
|
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
|
|
@@ -79,14 +80,7 @@ export function createWagmiConfig(chains, walletConnectProjectId, enabledConnect
|
|
|
79
80
|
else {
|
|
80
81
|
connectors.push(walletConnect({
|
|
81
82
|
projectId: walletConnectProjectId,
|
|
82
|
-
metadata:
|
|
83
|
-
name: "Abstraxn",
|
|
84
|
-
description: "Abstraxn Wallet",
|
|
85
|
-
url: typeof window !== "undefined"
|
|
86
|
-
? window.location.origin
|
|
87
|
-
: "https://abstraxn.com",
|
|
88
|
-
icons: ["https://avatars.githubusercontent.com/u/37784886"],
|
|
89
|
-
},
|
|
83
|
+
metadata: createWalletConnectDappMetadata(),
|
|
90
84
|
showQrModal: true,
|
|
91
85
|
qrModalOptions: {
|
|
92
86
|
themeMode: theme === "dark" ? "dark" : "light",
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mobile WalletConnect helpers.
|
|
3
|
+
*
|
|
4
|
+
* On iOS/Android the browser suspends JS and drops the WalletConnect relay
|
|
5
|
+
* WebSocket when the user is sent to MetaMask (or another wallet) via deeplink.
|
|
6
|
+
* The wallet still approves/rejects, but the in-flight JSON-RPC promise never
|
|
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
|
|
16
|
+
*/
|
|
17
|
+
/** Selectors used to close/restore Reown AppKit + WalletConnect modal DOM. */
|
|
18
|
+
export declare const WALLETCONNECT_MODAL_SELECTORS: string[];
|
|
19
|
+
export declare function isWalletConnectConnector(connector: {
|
|
20
|
+
id?: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
} | null | undefined): boolean;
|
|
23
|
+
export declare function isUserApprovalRpcMethod(method: unknown): boolean;
|
|
24
|
+
export declare function hasPendingWalletConnectApproval(provider?: any): boolean;
|
|
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;
|
|
64
|
+
/**
|
|
65
|
+
* Re-open the WalletConnect relay after the mobile browser comes back
|
|
66
|
+
* from the wallet app so pending approve/reject responses can be delivered.
|
|
67
|
+
*/
|
|
68
|
+
export declare function resumeWalletConnectRelayer(provider: any): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Undo the inline `display: none !important` we apply after connect so the
|
|
71
|
+
* WalletConnect modal can show "Continue in wallet" and process the response.
|
|
72
|
+
*/
|
|
73
|
+
export declare function restoreWalletConnectModal(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Patch the EIP-1193 provider so signing/tx requests resume the relay first.
|
|
76
|
+
* Covers wagmi hooks, viem walletClient, and direct provider.request calls.
|
|
77
|
+
*/
|
|
78
|
+
export declare function patchWalletConnectProviderForMobile(provider: any): void;
|
|
79
|
+
/**
|
|
80
|
+
* When the dapp tab is shown again (user left MetaMask), restart the relay so
|
|
81
|
+
* the pending WalletConnect response can be received.
|
|
82
|
+
*/
|
|
83
|
+
export declare function subscribeWalletConnectForegroundResume(provider: any): () => void;
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mobile WalletConnect helpers.
|
|
3
|
+
*
|
|
4
|
+
* On iOS/Android the browser suspends JS and drops the WalletConnect relay
|
|
5
|
+
* WebSocket when the user is sent to MetaMask (or another wallet) via deeplink.
|
|
6
|
+
* The wallet still approves/rejects, but the in-flight JSON-RPC promise never
|
|
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
|
|
16
|
+
*/
|
|
17
|
+
const PATCHED_FLAG = "__abstraxnWcMobilePatched";
|
|
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;
|
|
22
|
+
const USER_APPROVAL_METHODS = new Set([
|
|
23
|
+
"personal_sign",
|
|
24
|
+
"eth_sign",
|
|
25
|
+
"eth_signTypedData",
|
|
26
|
+
"eth_signTypedData_v3",
|
|
27
|
+
"eth_signTypedData_v4",
|
|
28
|
+
"eth_signTransaction",
|
|
29
|
+
"eth_sendTransaction",
|
|
30
|
+
"eth_sendRawTransaction",
|
|
31
|
+
"wallet_sendCalls",
|
|
32
|
+
"wallet_sendCallsSync",
|
|
33
|
+
"wallet_grantPermissions",
|
|
34
|
+
"wallet_requestPermissions",
|
|
35
|
+
"wallet_watchAsset",
|
|
36
|
+
"wallet_addEthereumChain",
|
|
37
|
+
"wallet_switchEthereumChain",
|
|
38
|
+
]);
|
|
39
|
+
/** Selectors used to close/restore Reown AppKit + WalletConnect modal DOM. */
|
|
40
|
+
export const WALLETCONNECT_MODAL_SELECTORS = [
|
|
41
|
+
"w3m-modal",
|
|
42
|
+
"w3m-modal-backdrop",
|
|
43
|
+
"wcm-modal",
|
|
44
|
+
"[data-w3m-modal]",
|
|
45
|
+
".w3m-modal",
|
|
46
|
+
".w3m-modal-backdrop",
|
|
47
|
+
"#w3m-modal",
|
|
48
|
+
"[class*='w3m-modal']",
|
|
49
|
+
"[id*='w3m-modal']",
|
|
50
|
+
"[class*='walletconnect-qrcode']",
|
|
51
|
+
"[id*='walletconnect']",
|
|
52
|
+
];
|
|
53
|
+
export function isWalletConnectConnector(connector) {
|
|
54
|
+
if (!connector)
|
|
55
|
+
return false;
|
|
56
|
+
const id = String(connector.id || "").toLowerCase();
|
|
57
|
+
const name = String(connector.name || "").toLowerCase();
|
|
58
|
+
return (id.includes("walletconnect") ||
|
|
59
|
+
id.includes("wallet_connect") ||
|
|
60
|
+
name.includes("walletconnect") ||
|
|
61
|
+
name.includes("wallet connect"));
|
|
62
|
+
}
|
|
63
|
+
export function isUserApprovalRpcMethod(method) {
|
|
64
|
+
return typeof method === "string" && USER_APPROVAL_METHODS.has(method);
|
|
65
|
+
}
|
|
66
|
+
export function hasPendingWalletConnectApproval(provider) {
|
|
67
|
+
if (provider && typeof provider[PENDING_FLAG] === "number") {
|
|
68
|
+
return provider[PENDING_FLAG] > 0;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
export function hasActiveWalletConnectSession(provider) {
|
|
73
|
+
const session = provider?.session ?? provider?.signer?.session;
|
|
74
|
+
if (!session?.topic)
|
|
75
|
+
return false;
|
|
76
|
+
if (typeof session.expiry === "number" &&
|
|
77
|
+
session.expiry > 0 &&
|
|
78
|
+
session.expiry * 1000 < Date.now()) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
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
|
+
}
|
|
240
|
+
function getWalletConnectRelayer(provider) {
|
|
241
|
+
return (provider?.signer?.client?.core?.relayer ||
|
|
242
|
+
provider?.client?.core?.relayer ||
|
|
243
|
+
provider?.rpc?.provider?.signer?.client?.core?.relayer ||
|
|
244
|
+
provider?.universalProvider?.client?.core?.relayer ||
|
|
245
|
+
null);
|
|
246
|
+
}
|
|
247
|
+
function isRelayerConnected(relayer) {
|
|
248
|
+
return (relayer?.connected === true ||
|
|
249
|
+
relayer?.provider?.connected === true ||
|
|
250
|
+
relayer?.provider?.connection?.connected === true);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Re-open the WalletConnect relay after the mobile browser comes back
|
|
254
|
+
* from the wallet app so pending approve/reject responses can be delivered.
|
|
255
|
+
*/
|
|
256
|
+
export async function resumeWalletConnectRelayer(provider) {
|
|
257
|
+
if (!provider)
|
|
258
|
+
return;
|
|
259
|
+
const relayer = getWalletConnectRelayer(provider);
|
|
260
|
+
if (!relayer)
|
|
261
|
+
return;
|
|
262
|
+
try {
|
|
263
|
+
if (isRelayerConnected(relayer)) {
|
|
264
|
+
try {
|
|
265
|
+
const ping = relayer.provider?.connection?.ping;
|
|
266
|
+
if (typeof ping === "function") {
|
|
267
|
+
await Promise.race([
|
|
268
|
+
ping.call(relayer.provider.connection),
|
|
269
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("ping timeout")), 1500)),
|
|
270
|
+
]);
|
|
271
|
+
}
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
// Ping failed — transport looks stale, restart below.
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (typeof relayer.restartTransport === "function") {
|
|
279
|
+
await relayer.restartTransport();
|
|
280
|
+
}
|
|
281
|
+
else if (typeof relayer.transportOpen === "function") {
|
|
282
|
+
try {
|
|
283
|
+
await relayer.transportClose?.();
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
// Ignore close errors and still try to open.
|
|
287
|
+
}
|
|
288
|
+
await relayer.transportOpen();
|
|
289
|
+
}
|
|
290
|
+
const session = provider?.session ?? provider?.signer?.session;
|
|
291
|
+
const topic = session?.topic;
|
|
292
|
+
const client = provider?.signer?.client || provider?.client;
|
|
293
|
+
if (topic && typeof client?.ping === "function") {
|
|
294
|
+
try {
|
|
295
|
+
await client.ping({ topic });
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
// Session ping is best-effort; the request may still complete.
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
// Best-effort: a failed resume should not break the original request.
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Undo the inline `display: none !important` we apply after connect so the
|
|
308
|
+
* WalletConnect modal can show "Continue in wallet" and process the response.
|
|
309
|
+
*/
|
|
310
|
+
export function restoreWalletConnectModal() {
|
|
311
|
+
if (typeof document === "undefined")
|
|
312
|
+
return;
|
|
313
|
+
WALLETCONNECT_MODAL_SELECTORS.forEach((sel) => {
|
|
314
|
+
try {
|
|
315
|
+
document.querySelectorAll(sel).forEach((el) => {
|
|
316
|
+
const htmlEl = el;
|
|
317
|
+
if (htmlEl?.style) {
|
|
318
|
+
htmlEl.style.removeProperty("display");
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
// Ignore invalid selectors in older browsers.
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
function getRequestMethod(args) {
|
|
328
|
+
const payload = args[0];
|
|
329
|
+
if (typeof payload === "string")
|
|
330
|
+
return payload;
|
|
331
|
+
if (payload && typeof payload === "object" && "method" in payload) {
|
|
332
|
+
return payload.method;
|
|
333
|
+
}
|
|
334
|
+
return undefined;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Patch the EIP-1193 provider so signing/tx requests resume the relay first.
|
|
338
|
+
* Covers wagmi hooks, viem walletClient, and direct provider.request calls.
|
|
339
|
+
*/
|
|
340
|
+
export function patchWalletConnectProviderForMobile(provider) {
|
|
341
|
+
if (!provider || typeof provider.request !== "function")
|
|
342
|
+
return;
|
|
343
|
+
if (provider[PATCHED_FLAG])
|
|
344
|
+
return;
|
|
345
|
+
const originalRequest = provider.request.bind(provider);
|
|
346
|
+
provider[PATCHED_FLAG] = true;
|
|
347
|
+
provider[PENDING_FLAG] = 0;
|
|
348
|
+
provider.request = async (...args) => {
|
|
349
|
+
const method = getRequestMethod(args);
|
|
350
|
+
if (!isUserApprovalRpcMethod(method)) {
|
|
351
|
+
return originalRequest(...args);
|
|
352
|
+
}
|
|
353
|
+
provider[PENDING_FLAG] = (provider[PENDING_FLAG] || 0) + 1;
|
|
354
|
+
restoreWalletConnectModal();
|
|
355
|
+
syncWalletConnectDappRedirect(provider);
|
|
356
|
+
try {
|
|
357
|
+
await resumeWalletConnectRelayer(provider);
|
|
358
|
+
return await originalRequest(...args);
|
|
359
|
+
}
|
|
360
|
+
finally {
|
|
361
|
+
provider[PENDING_FLAG] = Math.max(0, (provider[PENDING_FLAG] || 1) - 1);
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* When the dapp tab is shown again (user left MetaMask), restart the relay so
|
|
367
|
+
* the pending WalletConnect response can be received.
|
|
368
|
+
*/
|
|
369
|
+
export function subscribeWalletConnectForegroundResume(provider) {
|
|
370
|
+
if (typeof window === "undefined" || !provider)
|
|
371
|
+
return () => { };
|
|
372
|
+
let timer = null;
|
|
373
|
+
const resume = () => {
|
|
374
|
+
if (timer)
|
|
375
|
+
clearTimeout(timer);
|
|
376
|
+
timer = setTimeout(() => {
|
|
377
|
+
clearWalletReturnIfSameDocument();
|
|
378
|
+
void resumeWalletConnectRelayer(provider);
|
|
379
|
+
if (hasPendingWalletConnectApproval(provider)) {
|
|
380
|
+
restoreWalletConnectModal();
|
|
381
|
+
}
|
|
382
|
+
}, 250);
|
|
383
|
+
};
|
|
384
|
+
const onVisibility = () => {
|
|
385
|
+
if (document.visibilityState === "visible")
|
|
386
|
+
resume();
|
|
387
|
+
};
|
|
388
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
389
|
+
window.addEventListener("pageshow", resume);
|
|
390
|
+
window.addEventListener("focus", resume);
|
|
391
|
+
return () => {
|
|
392
|
+
if (timer)
|
|
393
|
+
clearTimeout(timer);
|
|
394
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
395
|
+
window.removeEventListener("pageshow", resume);
|
|
396
|
+
window.removeEventListener("focus", resume);
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
//# sourceMappingURL=walletConnectMobile.js.map
|
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",
|