@abstraxn/signer-react 2.0.1 → 2.0.2
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/README.md +70 -0
- package/dist/src/ExternalWalletButtons.js +139 -59
- package/dist/src/ExternalWalletButtons.js.map +1 -1
- package/dist/src/components/AbstraxnProvider/AbstraxnProvider.js +4 -1
- package/dist/src/components/AbstraxnProvider/AbstraxnProvider.js.map +1 -1
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.d.ts +6 -1
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js +184 -28
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js.map +1 -1
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderWithWagmi.js +4 -5
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderWithWagmi.js.map +1 -1
- package/dist/src/hooks.d.ts +32 -0
- package/dist/src/hooks.js +132 -0
- package/dist/src/hooks.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/types.d.ts +7 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -1
|
@@ -16,7 +16,7 @@ function WagmiConnectionEffectSync({ onDisconnect, }) {
|
|
|
16
16
|
useConnectionEffect({ onDisconnect });
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
|
-
export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
19
|
+
export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }) {
|
|
20
20
|
const { isInitialized, setIsInitialized, isConnected, setIsConnected, address, setAddress, user, setUser, whoami, setWhoami, chainId, setChainId, error, setError, loading, setLoading, resending, setResending, walletBalance, setWalletBalance, onboardingRef, otpIdRef, walletRef, googleCallbackHandledRef, twitterCallbackHandledRef, discordCallbackHandledRef, } = base;
|
|
21
21
|
const externalWalletsEnabled = config.externalWallets?.enabled ?? false;
|
|
22
22
|
// Keep a ref to avoid re-creating callbacks when toggling config (prevents flicker)
|
|
@@ -47,6 +47,99 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
47
47
|
useEffect(() => {
|
|
48
48
|
isExternalWalletConnectedRef.current = isExternalWalletConnected;
|
|
49
49
|
}, [isExternalWalletConnected]);
|
|
50
|
+
// Track Solana state changes
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (solana?.wallet?.connected && solana?.wallet?.publicKey) {
|
|
53
|
+
// For wallets that support both (like MetaMask via snaps), if we explicitly chose "solana", force it
|
|
54
|
+
// The wallet adapter usually handles this, but we want our internal state to reflect the Solana connection
|
|
55
|
+
const pubKey = solana.wallet.publicKey.toBase58();
|
|
56
|
+
setIsExternalWalletConnected(true);
|
|
57
|
+
setExternalWalletAddress(pubKey);
|
|
58
|
+
setIsConnected(true);
|
|
59
|
+
setAddress(pubKey);
|
|
60
|
+
// Use a real Solana chainId so `currentChain` resolves from SOLANA_CHAINS.
|
|
61
|
+
const cluster = String(config?.solanaConfig?.cluster || '').toLowerCase();
|
|
62
|
+
const chainIdForSolana = cluster === 'devnet'
|
|
63
|
+
? SOLANA_CHAINS.solanaDevnet.id
|
|
64
|
+
: SOLANA_CHAINS.solana.id;
|
|
65
|
+
setExternalWalletChainId(chainIdForSolana);
|
|
66
|
+
setChainId(chainIdForSolana);
|
|
67
|
+
const walletName = solana.wallet.wallet?.adapter.name?.toLowerCase() || 'solana';
|
|
68
|
+
setConnectionType(walletName);
|
|
69
|
+
localStorage.setItem("abstraxn_connection_type", walletName);
|
|
70
|
+
localStorage.setItem("abstraxn_chain_type", "solana");
|
|
71
|
+
explicitConnectionRef.current = true;
|
|
72
|
+
autoDisconnectHandledRef.current = false;
|
|
73
|
+
// Close the onboarding modal after successful connection
|
|
74
|
+
if (onboardingRef.current) {
|
|
75
|
+
const onboardingAny = onboardingRef.current;
|
|
76
|
+
if (onboardingAny.modalOverlay) {
|
|
77
|
+
setTimeout(() => {
|
|
78
|
+
if (onboardingAny.modalOverlay) {
|
|
79
|
+
onboardingAny.modalOverlay.classList.remove("onboarding-modal-open");
|
|
80
|
+
onboardingAny.modalOverlay.classList.add("onboarding-modal-closing");
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
if (onboardingAny.modalOverlay) {
|
|
83
|
+
onboardingAny.modalOverlay.style.display = "none";
|
|
84
|
+
}
|
|
85
|
+
}, 200);
|
|
86
|
+
document.body.style.overflow = "";
|
|
87
|
+
}
|
|
88
|
+
}, 100);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else if (solana?.wallet && !solana.wallet.connected) {
|
|
93
|
+
// If the user disconnected from the Solana wallet (e.g. Phantom UI), ensure our state resets.
|
|
94
|
+
// Without this, the UI can stay "connected" and block reconnects until refresh.
|
|
95
|
+
if (disconnectingRef.current)
|
|
96
|
+
return;
|
|
97
|
+
const chainTypePref = typeof window !== "undefined"
|
|
98
|
+
? localStorage.getItem("abstraxn_chain_type")
|
|
99
|
+
: null;
|
|
100
|
+
const ct = (connectionType || "").toLowerCase();
|
|
101
|
+
const looksLikeSolana = chainTypePref === "solana" ||
|
|
102
|
+
ct === "phantom" ||
|
|
103
|
+
ct === "solflare" ||
|
|
104
|
+
ct === "solana";
|
|
105
|
+
if (looksLikeSolana && (isExternalWalletConnectedRef.current || externalWalletAddress)) {
|
|
106
|
+
setIsExternalWalletConnected(false);
|
|
107
|
+
setExternalWalletAddress(null);
|
|
108
|
+
setExternalWalletChainId(null);
|
|
109
|
+
setConnectionType(null);
|
|
110
|
+
// Only clear main state if Abstraxn embedded wallet isn't connected
|
|
111
|
+
if (!walletRef.current?.isConnected) {
|
|
112
|
+
setIsConnected(false);
|
|
113
|
+
setAddress(null);
|
|
114
|
+
setChainId(null);
|
|
115
|
+
}
|
|
116
|
+
explicitConnectionRef.current = false;
|
|
117
|
+
lastConnectionTimeRef.current = 0;
|
|
118
|
+
lastAddressRef.current = null;
|
|
119
|
+
lastChainIdRef.current = null;
|
|
120
|
+
try {
|
|
121
|
+
localStorage.removeItem("abstraxn_connection_type");
|
|
122
|
+
localStorage.removeItem("abstraxn_chain_type");
|
|
123
|
+
localStorage.removeItem("walletName"); // wallet-adapter-react selection key
|
|
124
|
+
}
|
|
125
|
+
catch (e) {
|
|
126
|
+
// Ignore
|
|
127
|
+
}
|
|
128
|
+
// Clear selection so a subsequent connect starts cleanly
|
|
129
|
+
try {
|
|
130
|
+
solana.wallet.select?.(null);
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
// Ignore
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}, [
|
|
138
|
+
solana?.wallet?.connected,
|
|
139
|
+
solana?.wallet?.publicKey?.toBase58(),
|
|
140
|
+
connectionType,
|
|
141
|
+
externalWalletAddress,
|
|
142
|
+
]);
|
|
50
143
|
// Track when we last connected to prevent premature reset
|
|
51
144
|
const lastConnectionTimeRef = useRef(0);
|
|
52
145
|
// Refs to track previous values and prevent unnecessary updates
|
|
@@ -99,6 +192,11 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
99
192
|
// Check if wagmi has already restored a connection from localStorage
|
|
100
193
|
// This happens automatically with wagmi's persistence when storage is configured
|
|
101
194
|
const checkAndRestore = () => {
|
|
195
|
+
// If we explicitly connected to Solana, do not restore Wagmi EVM state
|
|
196
|
+
const chainTypePref = typeof window !== 'undefined' ? localStorage.getItem("abstraxn_chain_type") : null;
|
|
197
|
+
if (chainTypePref === "solana") {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
102
200
|
if (wagmiAccount.isConnected &&
|
|
103
201
|
wagmiAccount.address &&
|
|
104
202
|
!isExternalWalletConnected) {
|
|
@@ -345,6 +443,8 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
345
443
|
// Clear from localStorage
|
|
346
444
|
try {
|
|
347
445
|
localStorage.removeItem("abstraxn_connection_type");
|
|
446
|
+
localStorage.removeItem("abstraxn_chain_type");
|
|
447
|
+
localStorage.removeItem("walletName"); // Clear wallet adapter state
|
|
348
448
|
}
|
|
349
449
|
catch (e) {
|
|
350
450
|
// Ignore localStorage errors
|
|
@@ -1321,8 +1421,34 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
1321
1421
|
// If external wallet is connected, disconnect it first
|
|
1322
1422
|
if (wasExternalWalletConnected &&
|
|
1323
1423
|
externalWalletsEnabled &&
|
|
1324
|
-
wagmiDisconnect) {
|
|
1325
|
-
|
|
1424
|
+
(wagmiDisconnect || solana?.wallet)) {
|
|
1425
|
+
// Disconnect Solana adapter first (Phantom/Solflare), otherwise reconnect can get stuck until refresh.
|
|
1426
|
+
const chainTypePref = typeof window !== "undefined"
|
|
1427
|
+
? localStorage.getItem("abstraxn_chain_type")
|
|
1428
|
+
: null;
|
|
1429
|
+
const ct = (connectionType || "").toLowerCase();
|
|
1430
|
+
const looksLikeSolana = chainTypePref === "solana" ||
|
|
1431
|
+
ct === "phantom" ||
|
|
1432
|
+
ct === "solflare" ||
|
|
1433
|
+
ct === "solana";
|
|
1434
|
+
if (solana?.wallet && (solana.wallet.connected || looksLikeSolana)) {
|
|
1435
|
+
try {
|
|
1436
|
+
if (solana.wallet.connected) {
|
|
1437
|
+
await solana.wallet.disconnect();
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
catch (e) {
|
|
1441
|
+
// Ignore
|
|
1442
|
+
}
|
|
1443
|
+
try {
|
|
1444
|
+
solana.wallet.select?.(null);
|
|
1445
|
+
}
|
|
1446
|
+
catch (e) {
|
|
1447
|
+
// Ignore
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
// Disconnect wagmi connector only if it's actually connected (avoid no-op errors for Solana-only connections)
|
|
1451
|
+
if (wagmiDisconnect && wagmiAccount?.isConnected) {
|
|
1326
1452
|
// For WalletConnect: disconnect provider first so session is fully torn down on first click
|
|
1327
1453
|
const connector = wagmiAccount?.connector;
|
|
1328
1454
|
const isWalletConnect = connector &&
|
|
@@ -1339,36 +1465,40 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
1339
1465
|
// Ignore - wagmi disconnect will still run
|
|
1340
1466
|
}
|
|
1341
1467
|
}
|
|
1342
|
-
await wagmiDisconnect.disconnect();
|
|
1343
|
-
// Wait for wagmi state to update (WalletConnect can be slow)
|
|
1344
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
1345
|
-
// Reset external wallet state immediately
|
|
1346
|
-
setIsExternalWalletConnected(false);
|
|
1347
|
-
setExternalWalletAddress(null);
|
|
1348
|
-
setExternalWalletChainId(null);
|
|
1349
|
-
setConnectionType(null);
|
|
1350
|
-
// Clear refs so useEffect doesn't think we're still connected (fixes "disconnect twice")
|
|
1351
|
-
lastAddressRef.current = null;
|
|
1352
|
-
lastChainIdRef.current = null;
|
|
1353
|
-
// Clear from localStorage
|
|
1354
1468
|
try {
|
|
1355
|
-
|
|
1469
|
+
await wagmiDisconnect.disconnect();
|
|
1470
|
+
// Wait for wagmi state to update (WalletConnect can be slow)
|
|
1471
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
1356
1472
|
}
|
|
1357
1473
|
catch (e) {
|
|
1358
|
-
// Ignore
|
|
1474
|
+
// Ignore wagmi disconnect failures; we still reset our state below.
|
|
1359
1475
|
}
|
|
1360
|
-
explicitConnectionRef.current = false;
|
|
1361
|
-
lastConnectionTimeRef.current = 0;
|
|
1362
|
-
// Always reset main isConnected when disconnecting external wallet
|
|
1363
|
-
// Since the context value is computed as isExternalWalletConnected || isConnected,
|
|
1364
|
-
// we need to set isConnected to false so the overall isConnected becomes false
|
|
1365
|
-
setIsConnected(false);
|
|
1366
|
-
setAddress(null);
|
|
1367
|
-
setChainId(null);
|
|
1368
1476
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1477
|
+
// Reset external wallet state immediately
|
|
1478
|
+
setIsExternalWalletConnected(false);
|
|
1479
|
+
setExternalWalletAddress(null);
|
|
1480
|
+
setExternalWalletChainId(null);
|
|
1481
|
+
setConnectionType(null);
|
|
1482
|
+
// Clear refs so useEffect doesn't think we're still connected (fixes "disconnect twice")
|
|
1483
|
+
lastAddressRef.current = null;
|
|
1484
|
+
lastChainIdRef.current = null;
|
|
1485
|
+
// Clear from localStorage
|
|
1486
|
+
try {
|
|
1487
|
+
localStorage.removeItem("abstraxn_connection_type");
|
|
1488
|
+
localStorage.removeItem("abstraxn_chain_type");
|
|
1489
|
+
localStorage.removeItem("walletName");
|
|
1490
|
+
}
|
|
1491
|
+
catch (e) {
|
|
1492
|
+
// Ignore localStorage errors
|
|
1371
1493
|
}
|
|
1494
|
+
explicitConnectionRef.current = false;
|
|
1495
|
+
lastConnectionTimeRef.current = 0;
|
|
1496
|
+
// Always reset main isConnected when disconnecting external wallet
|
|
1497
|
+
// Since the context value is computed as isExternalWalletConnected || isConnected,
|
|
1498
|
+
// we need to set isConnected to false so the overall isConnected becomes false
|
|
1499
|
+
setIsConnected(false);
|
|
1500
|
+
setAddress(null);
|
|
1501
|
+
setChainId(null);
|
|
1372
1502
|
}
|
|
1373
1503
|
// Disconnect Abstraxn wallet if it's connected
|
|
1374
1504
|
if (wasAbstraxnWalletConnected && walletRef.current) {
|
|
@@ -1384,6 +1514,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
1384
1514
|
// Clear from localStorage
|
|
1385
1515
|
try {
|
|
1386
1516
|
localStorage.removeItem("abstraxn_connection_type");
|
|
1517
|
+
localStorage.removeItem("walletName");
|
|
1387
1518
|
}
|
|
1388
1519
|
catch (e) {
|
|
1389
1520
|
// Ignore localStorage errors
|
|
@@ -1971,6 +2102,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
1971
2102
|
if (!externalWalletsEnabled || !wagmiAccount) {
|
|
1972
2103
|
return;
|
|
1973
2104
|
}
|
|
2105
|
+
// Check if we explicitly connected to a Solana wallet and it is currently connected.
|
|
2106
|
+
// If so, we should ignore Wagmi's connection state to prevent EVM from overriding Solana.
|
|
2107
|
+
const chainTypePref = typeof window !== 'undefined' ? localStorage.getItem("abstraxn_chain_type") : null;
|
|
2108
|
+
if (chainTypePref === "solana" && solana?.wallet?.connected) {
|
|
2109
|
+
return;
|
|
2110
|
+
}
|
|
1974
2111
|
// Prevent auto-connect (but allow restoration from persistence)
|
|
1975
2112
|
// Only auto-disconnect if:
|
|
1976
2113
|
// 1. wagmiAccount is connected
|
|
@@ -2333,6 +2470,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
2333
2470
|
setConnectionType(connectionTypeValue);
|
|
2334
2471
|
try {
|
|
2335
2472
|
localStorage.setItem("abstraxn_connection_type", connectionTypeValue);
|
|
2473
|
+
localStorage.setItem("abstraxn_chain_type", "evm");
|
|
2336
2474
|
}
|
|
2337
2475
|
catch (e) { }
|
|
2338
2476
|
// Update refs
|
|
@@ -2466,6 +2604,19 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
2466
2604
|
}
|
|
2467
2605
|
}
|
|
2468
2606
|
// Await the disconnect to ensure it completes
|
|
2607
|
+
if (solana?.wallet?.connected) {
|
|
2608
|
+
try {
|
|
2609
|
+
await solana?.wallet?.disconnect();
|
|
2610
|
+
}
|
|
2611
|
+
catch (e) { }
|
|
2612
|
+
}
|
|
2613
|
+
// Clear Solana wallet selection so reconnect starts cleanly
|
|
2614
|
+
if (solana?.wallet) {
|
|
2615
|
+
try {
|
|
2616
|
+
solana.wallet.select?.(null);
|
|
2617
|
+
}
|
|
2618
|
+
catch (e) { }
|
|
2619
|
+
}
|
|
2469
2620
|
await wagmiDisconnect.disconnect();
|
|
2470
2621
|
// Wait for wagmi state to update (WalletConnect can be slow)
|
|
2471
2622
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
@@ -2477,6 +2628,8 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
2477
2628
|
// Clear from localStorage
|
|
2478
2629
|
try {
|
|
2479
2630
|
localStorage.removeItem("abstraxn_connection_type");
|
|
2631
|
+
localStorage.removeItem("abstraxn_chain_type");
|
|
2632
|
+
localStorage.removeItem("walletName");
|
|
2480
2633
|
}
|
|
2481
2634
|
catch (e) {
|
|
2482
2635
|
// Ignore localStorage errors
|
|
@@ -2508,7 +2661,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
2508
2661
|
}, 200);
|
|
2509
2662
|
setLoading(false);
|
|
2510
2663
|
}
|
|
2511
|
-
}, [externalWalletsEnabled, wagmiDisconnect, wagmiAccount?.connector]);
|
|
2664
|
+
}, [externalWalletsEnabled, wagmiDisconnect, wagmiAccount?.connector, solana?.wallet]);
|
|
2512
2665
|
// When wagmi reports disconnect (e.g. user disconnected in extension), clear external wallet state immediately
|
|
2513
2666
|
const handleWagmiDisconnect = useCallback(() => {
|
|
2514
2667
|
if (!externalWalletsEnabledRef.current)
|
|
@@ -2519,6 +2672,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
2519
2672
|
setConnectionType(null);
|
|
2520
2673
|
try {
|
|
2521
2674
|
localStorage.removeItem("abstraxn_connection_type");
|
|
2675
|
+
localStorage.removeItem("abstraxn_chain_type");
|
|
2522
2676
|
}
|
|
2523
2677
|
catch (e) {
|
|
2524
2678
|
// Ignore
|
|
@@ -2862,6 +3016,8 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
2862
3016
|
loading,
|
|
2863
3017
|
resending: resending ?? false,
|
|
2864
3018
|
disconnecting: disconnecting ?? false,
|
|
3019
|
+
solanaWallet: solana?.wallet,
|
|
3020
|
+
solanaConnection: solana?.connection,
|
|
2865
3021
|
init,
|
|
2866
3022
|
connect,
|
|
2867
3023
|
disconnect,
|