@cookill/wallet-adapter 2.4.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,9 +11,8 @@ npm install @cookill/wallet-adapter
11
11
  ## Quick Start
12
12
 
13
13
  ```tsx
14
- import {
15
- WalletProvider,
16
- WalletModal,
14
+ import {
15
+ WalletProvider,
17
16
  ConnectButton,
18
17
  WalletErrorBoundary,
19
18
  } from '@cookill/wallet-adapter/react';
@@ -21,9 +20,9 @@ import {
21
20
  function App() {
22
21
  return (
23
22
  <WalletErrorBoundary>
23
+ {/* WalletProvider will render a default WalletModal automatically */}
24
24
  <WalletProvider network="devnet" autoConnect>
25
25
  <ConnectButton />
26
- <WalletModal />
27
26
  <YourDApp />
28
27
  </WalletProvider>
29
28
  </WalletErrorBoundary>
@@ -31,6 +30,14 @@ function App() {
31
30
  }
32
31
  ```
33
32
 
33
+ ## Troubleshooting (Connect stuck)
34
+
35
+ If clicking **Connect** does nothing or feels "stuck":
36
+
37
+ - Make sure your dApp is wrapped in `<WalletProvider>` (and ideally `<WalletErrorBoundary>`).
38
+ - Prefer `useConnectWallet().connect` (opens the modal) instead of `connectDirect`.
39
+ - The modal is rendered automatically by `WalletProvider`.
40
+
34
41
  ## React Hooks
35
42
 
36
43
  ### useWallet
package/dist/react.cjs CHANGED
@@ -1,8 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
3
+ var React2 = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
 
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var React2__default = /*#__PURE__*/_interopDefault(React2);
9
+
6
10
  // src/react.tsx
7
11
 
8
12
  // src/index.ts
@@ -99,7 +103,7 @@ function isValidAddress(address) {
99
103
  if (address.length < 32 || address.length > 50) return false;
100
104
  return /^[1-9A-HJ-NP-Za-km-z]+$/.test(address);
101
105
  }
102
- var WalletErrorBoundary = class extends react.Component {
106
+ var WalletErrorBoundary = class extends React2.Component {
103
107
  constructor() {
104
108
  super(...arguments);
105
109
  this.state = {
@@ -454,7 +458,17 @@ var DEFAULT_WALLETS = [
454
458
  downloadUrl: "https://rialo.io/wallet"
455
459
  }
456
460
  ];
457
- var WalletContext = react.createContext(null);
461
+ var CONNECT_TIMEOUT_MS = 2e4;
462
+ function withTimeout(promise, ms, message) {
463
+ let timeoutId;
464
+ const timeout = new Promise((_, reject) => {
465
+ timeoutId = setTimeout(() => reject(new Error(message)), ms);
466
+ });
467
+ return Promise.race([promise, timeout]).finally(() => {
468
+ if (timeoutId) clearTimeout(timeoutId);
469
+ });
470
+ }
471
+ var WalletContext = React2.createContext(null);
458
472
  function WalletProvider({
459
473
  children,
460
474
  network: initialNetwork = "devnet",
@@ -465,26 +479,27 @@ function WalletProvider({
465
479
  onError,
466
480
  onNetworkChange
467
481
  }) {
468
- const [connected, setConnected] = react.useState(false);
469
- const [connecting, setConnecting] = react.useState(false);
470
- const [accounts, setAccounts] = react.useState([]);
471
- const [network, setNetwork] = react.useState(initialNetwork);
472
- const [balance, setBalance] = react.useState(null);
473
- const [selectedWallet, setSelectedWallet] = react.useState(null);
474
- const [isModalOpen, setIsModalOpen] = react.useState(false);
475
- const [provider, setProvider] = react.useState();
476
- const [error, setError] = react.useState(null);
477
- const chainId = react.useMemo(() => `rialo:${network}`, [network]);
482
+ const [connected, setConnected] = React2.useState(false);
483
+ const [connecting, setConnecting] = React2.useState(false);
484
+ const [accounts, setAccounts] = React2.useState([]);
485
+ const [network, setNetwork] = React2.useState(initialNetwork);
486
+ const [balance, setBalance] = React2.useState(null);
487
+ const [selectedWallet, setSelectedWallet] = React2.useState(null);
488
+ const [isModalOpen, setIsModalOpen] = React2.useState(false);
489
+ const [provider, setProvider] = React2.useState();
490
+ const [error, setError] = React2.useState(null);
491
+ const connectPromiseRef = React2.useRef(null);
492
+ const chainId = React2.useMemo(() => `rialo:${network}`, [network]);
478
493
  const activeAccount = accounts[0] || null;
479
494
  const isInstalled = isRialoInstalled();
480
- const wallets = react.useMemo(() => {
495
+ const wallets = React2.useMemo(() => {
481
496
  const installed = isRialoInstalled();
482
497
  return [...DEFAULT_WALLETS, ...customWallets].map((w) => ({
483
498
  ...w,
484
499
  installed: w.id === "sheep-wallet" ? installed : false
485
500
  }));
486
501
  }, [customWallets]);
487
- react.useEffect(() => {
502
+ React2.useEffect(() => {
488
503
  const init = async () => {
489
504
  const p = await waitForRialoProvider(3e3);
490
505
  setProvider(p);
@@ -494,7 +509,7 @@ function WalletProvider({
494
509
  };
495
510
  init();
496
511
  }, [wallets]);
497
- const refreshBalance = react.useCallback(async () => {
512
+ const refreshBalance = React2.useCallback(async () => {
498
513
  if (!provider || !activeAccount) return;
499
514
  try {
500
515
  const result = await provider.getBalance(activeAccount.address);
@@ -504,24 +519,42 @@ function WalletProvider({
504
519
  console.error("Balance fetch error:", e);
505
520
  }
506
521
  }, [provider, activeAccount]);
507
- react.useEffect(() => {
522
+ React2.useEffect(() => {
508
523
  if (connected && activeAccount && provider) {
509
524
  refreshBalance();
510
525
  const interval = setInterval(refreshBalance, 3e4);
511
526
  return () => clearInterval(interval);
512
527
  }
513
528
  }, [connected, activeAccount, provider, refreshBalance]);
514
- react.useEffect(() => {
515
- if (autoConnect && provider && !connected && !connecting) {
516
- provider.isConnected().then((isConn) => {
517
- if (isConn) {
518
- handleConnect();
529
+ React2.useEffect(() => {
530
+ if (!autoConnect || !provider || connected || connecting) return;
531
+ let cancelled = false;
532
+ provider.isConnected().then(async (isConn) => {
533
+ if (!isConn || cancelled) return;
534
+ try {
535
+ const rawAccounts = await withTimeout(provider.getAccounts(), 5e3, "Auto-connect timed out");
536
+ const normalized = (rawAccounts || []).map((acc) => {
537
+ if (typeof acc === "string") return { address: acc, publicKey: acc };
538
+ return { address: acc.address, publicKey: acc.publicKey || acc.address };
539
+ });
540
+ if (cancelled) return;
541
+ setAccounts(normalized);
542
+ setConnected(true);
543
+ try {
544
+ const net = await provider.getNetwork();
545
+ if (!cancelled) setNetwork(net);
546
+ } catch {
519
547
  }
520
- }).catch(() => {
521
- });
522
- }
523
- }, [provider, autoConnect, connected, connecting]);
524
- react.useEffect(() => {
548
+ onConnect?.(normalized);
549
+ } catch {
550
+ }
551
+ }).catch(() => {
552
+ });
553
+ return () => {
554
+ cancelled = true;
555
+ };
556
+ }, [provider, autoConnect, connected, connecting, onConnect]);
557
+ React2.useEffect(() => {
525
558
  if (!provider) return;
526
559
  const cleanupFns = [];
527
560
  cleanupFns.push(
@@ -570,48 +603,65 @@ function WalletProvider({
570
603
  cleanupFns.forEach((fn) => fn?.());
571
604
  };
572
605
  }, [provider, onDisconnect, onNetworkChange]);
573
- const handleConnect = react.useCallback(async () => {
574
- if (!provider) {
575
- const err = new Error("Rialo Wallet not installed");
576
- setError(err);
577
- onError?.(err);
578
- throw err;
606
+ const handleConnect = React2.useCallback(async () => {
607
+ if (connectPromiseRef.current) {
608
+ return connectPromiseRef.current;
579
609
  }
580
- setConnecting(true);
581
- setError(null);
582
- try {
583
- console.log("[Adapter] Calling provider.connect()...");
584
- const result = await provider.connect();
585
- console.log("[Adapter] Connect result:", result);
586
- const walletAccounts = result.map((acc) => {
587
- if (typeof acc === "string") {
588
- return { address: acc, publicKey: acc };
589
- }
590
- return {
591
- address: acc.address,
592
- publicKey: acc.publicKey || acc.address
593
- };
594
- });
595
- setAccounts(walletAccounts);
596
- setConnected(true);
597
- setIsModalOpen(false);
610
+ const run = (async () => {
611
+ if (!provider) {
612
+ const err = new Error("Rialo Wallet not installed");
613
+ setError(err);
614
+ onError?.(err);
615
+ throw err;
616
+ }
617
+ setIsModalOpen(true);
618
+ setConnecting(true);
619
+ setError(null);
598
620
  try {
599
- const net = await provider.getNetwork();
600
- setNetwork(net);
601
- } catch {
621
+ console.log("[Adapter] Calling provider.connect()...");
622
+ const result = await withTimeout(
623
+ provider.connect(),
624
+ CONNECT_TIMEOUT_MS,
625
+ "Connect timed out. Please open Sheep Wallet extension and approve the request."
626
+ );
627
+ console.log("[Adapter] Connect result:", result);
628
+ const walletAccounts = result.map((acc) => {
629
+ if (typeof acc === "string") {
630
+ return { address: acc, publicKey: acc };
631
+ }
632
+ return {
633
+ address: acc.address,
634
+ publicKey: acc.publicKey || acc.address
635
+ };
636
+ });
637
+ setAccounts(walletAccounts);
638
+ setConnected(true);
639
+ setIsModalOpen(false);
640
+ try {
641
+ const net = await withTimeout(provider.getNetwork(), 5e3, "Network request timed out");
642
+ setNetwork(net);
643
+ } catch {
644
+ }
645
+ onConnect?.(walletAccounts);
646
+ return walletAccounts;
647
+ } catch (e) {
648
+ const err = e;
649
+ setError(err);
650
+ onError?.(err);
651
+ setIsModalOpen(true);
652
+ throw err;
653
+ } finally {
654
+ setConnecting(false);
602
655
  }
603
- onConnect?.(walletAccounts);
604
- return walletAccounts;
605
- } catch (e) {
606
- const err = e;
607
- setError(err);
608
- onError?.(err);
609
- throw err;
656
+ })();
657
+ connectPromiseRef.current = run;
658
+ try {
659
+ return await run;
610
660
  } finally {
611
- setConnecting(false);
661
+ connectPromiseRef.current = null;
612
662
  }
613
663
  }, [provider, onConnect, onError]);
614
- const handleDisconnect = react.useCallback(async () => {
664
+ const handleDisconnect = React2.useCallback(async () => {
615
665
  try {
616
666
  if (provider) {
617
667
  await provider.disconnect();
@@ -623,7 +673,7 @@ function WalletProvider({
623
673
  setBalance(null);
624
674
  onDisconnect?.();
625
675
  }, [provider, onDisconnect]);
626
- const selectWallet = react.useCallback((walletId) => {
676
+ const selectWallet = React2.useCallback((walletId) => {
627
677
  const wallet = wallets.find((w) => w.id === walletId);
628
678
  if (wallet) {
629
679
  setSelectedWallet(wallet);
@@ -634,40 +684,40 @@ function WalletProvider({
634
684
  }
635
685
  }
636
686
  }, [wallets, handleConnect]);
637
- const handleSwitchNetwork = react.useCallback(async (newNetwork) => {
687
+ const handleSwitchNetwork = React2.useCallback(async (newNetwork) => {
638
688
  if (provider) {
639
689
  await provider.switchNetwork(newNetwork);
640
690
  }
641
691
  setNetwork(newNetwork);
642
692
  onNetworkChange?.(newNetwork);
643
693
  }, [provider, onNetworkChange]);
644
- const handleSignMessage = react.useCallback(async (message) => {
694
+ const handleSignMessage = React2.useCallback(async (message) => {
645
695
  if (!provider || !connected) {
646
696
  throw new Error("Wallet not connected");
647
697
  }
648
698
  return provider.signMessage(message);
649
699
  }, [provider, connected]);
650
- const handleSignTransaction = react.useCallback(async (tx) => {
700
+ const handleSignTransaction = React2.useCallback(async (tx) => {
651
701
  if (!provider || !connected) {
652
702
  throw new Error("Wallet not connected");
653
703
  }
654
704
  const result = await provider.signTransaction(tx);
655
705
  return result.signature;
656
706
  }, [provider, connected]);
657
- const handleSendTransaction = react.useCallback(async (tx) => {
707
+ const handleSendTransaction = React2.useCallback(async (tx) => {
658
708
  if (!provider || !connected) {
659
709
  throw new Error("Wallet not connected");
660
710
  }
661
711
  return provider.sendTransaction(tx);
662
712
  }, [provider, connected]);
663
- const handleSignAndSendTransaction = react.useCallback(async (tx) => {
713
+ const handleSignAndSendTransaction = React2.useCallback(async (tx) => {
664
714
  if (!provider || !connected) {
665
715
  throw new Error("Wallet not connected");
666
716
  }
667
717
  return provider.signAndSendTransaction(tx);
668
718
  }, [provider, connected]);
669
- const openModal = react.useCallback(() => setIsModalOpen(true), []);
670
- const closeModal = react.useCallback(() => setIsModalOpen(false), []);
719
+ const openModal = React2.useCallback(() => setIsModalOpen(true), []);
720
+ const closeModal = React2.useCallback(() => setIsModalOpen(false), []);
671
721
  const value = {
672
722
  connected,
673
723
  connecting,
@@ -693,10 +743,13 @@ function WalletProvider({
693
743
  openModal,
694
744
  closeModal
695
745
  };
696
- return /* @__PURE__ */ jsxRuntime.jsx(WalletContext.Provider, { value, children });
746
+ return /* @__PURE__ */ jsxRuntime.jsxs(WalletContext.Provider, { value, children: [
747
+ children,
748
+ /* @__PURE__ */ jsxRuntime.jsx(WalletModal, {})
749
+ ] });
697
750
  }
698
751
  function useWallet() {
699
- const context = react.useContext(WalletContext);
752
+ const context = React2.useContext(WalletContext);
700
753
  if (!context) {
701
754
  throw new Error("useWallet must be used within WalletProvider");
702
755
  }
@@ -736,9 +789,9 @@ function useChainId() {
736
789
  }
737
790
  function useSwitchNetwork() {
738
791
  const { switchNetwork, network } = useWallet();
739
- const [switching, setSwitching] = react.useState(false);
740
- const [error, setError] = react.useState(null);
741
- const doSwitch = react.useCallback(async (newNetwork) => {
792
+ const [switching, setSwitching] = React2.useState(false);
793
+ const [error, setError] = React2.useState(null);
794
+ const doSwitch = React2.useCallback(async (newNetwork) => {
742
795
  setSwitching(true);
743
796
  setError(null);
744
797
  try {
@@ -754,7 +807,7 @@ function useSwitchNetwork() {
754
807
  }
755
808
  function useConnectWallet() {
756
809
  const { connect, connecting, openModal, isInstalled, error } = useWallet();
757
- const handleConnect = react.useCallback(() => {
810
+ const handleConnect = React2.useCallback(() => {
758
811
  openModal();
759
812
  }, [openModal]);
760
813
  return {
@@ -772,10 +825,10 @@ function useDisconnectWallet() {
772
825
  }
773
826
  function useSignMessage() {
774
827
  const { signMessage, connected, activeAccount } = useWallet();
775
- const [signing, setSigning] = react.useState(false);
776
- const [signature, setSignature] = react.useState(null);
777
- const [error, setError] = react.useState(null);
778
- const sign = react.useCallback(async (message) => {
828
+ const [signing, setSigning] = React2.useState(false);
829
+ const [signature, setSignature] = React2.useState(null);
830
+ const [error, setError] = React2.useState(null);
831
+ const sign = React2.useCallback(async (message) => {
779
832
  if (!connected) {
780
833
  setError(new Error("Wallet not connected"));
781
834
  return null;
@@ -797,10 +850,10 @@ function useSignMessage() {
797
850
  }
798
851
  function useSendTransaction() {
799
852
  const { signAndSendTransaction, connected } = useWallet();
800
- const [sending, setSending] = react.useState(false);
801
- const [txHash, setTxHash] = react.useState(null);
802
- const [error, setError] = react.useState(null);
803
- const send = react.useCallback(async (tx) => {
853
+ const [sending, setSending] = React2.useState(false);
854
+ const [txHash, setTxHash] = React2.useState(null);
855
+ const [error, setError] = React2.useState(null);
856
+ const send = React2.useCallback(async (tx) => {
804
857
  if (!connected) {
805
858
  setError(new Error("Wallet not connected"));
806
859
  return null;
@@ -825,10 +878,10 @@ function useSendTransaction() {
825
878
  }
826
879
  function useSignTransaction() {
827
880
  const { signTransaction, connected } = useWallet();
828
- const [signing, setSigning] = react.useState(false);
829
- const [signature, setSignature] = react.useState(null);
830
- const [error, setError] = react.useState(null);
831
- const sign = react.useCallback(async (tx) => {
881
+ const [signing, setSigning] = React2.useState(false);
882
+ const [signature, setSignature] = React2.useState(null);
883
+ const [error, setError] = React2.useState(null);
884
+ const sign = React2.useCallback(async (tx) => {
832
885
  if (!connected) {
833
886
  setError(new Error("Wallet not connected"));
834
887
  return null;
@@ -913,7 +966,24 @@ function ConnectButton({
913
966
  }
914
967
  );
915
968
  }
969
+ var walletModalOwnerToken = null;
916
970
  function WalletModal({ title = "Connect Wallet", className = "" }) {
971
+ const ownerRef = React2__default.default.useRef({});
972
+ const [isOwner] = React2.useState(() => {
973
+ if (!walletModalOwnerToken) {
974
+ walletModalOwnerToken = ownerRef.current;
975
+ return true;
976
+ }
977
+ return walletModalOwnerToken === ownerRef.current;
978
+ });
979
+ React2.useEffect(() => {
980
+ return () => {
981
+ if (isOwner && walletModalOwnerToken === ownerRef.current) {
982
+ walletModalOwnerToken = null;
983
+ }
984
+ };
985
+ }, [isOwner]);
986
+ if (!isOwner) return null;
917
987
  const { isModalOpen, closeModal, wallets, selectWallet, connecting } = useWallet();
918
988
  if (!isModalOpen) return null;
919
989
  return /* @__PURE__ */ jsxRuntime.jsx(