Skip to content

React ​

@xrpl-wallet-kit/react provides React bindings for XRPL Wallet Kit — a WalletKitProvider, a set of hooks, and a drop-in WalletButton component.

Installation ​

bash
npm install @xrpl-wallet-kit/react @xrpl-wallet-kit/core xrpl \
  @xrpl-wallet-kit/adapter-gemwallet @xrpl-wallet-kit/adapter-crossmark

Choosing a setup ​

TypeScript projects also need @types/node for the XRPL SDK declarations (npm install --save-dev @types/node) if the framework has not already installed it.

You wantUseBundle profile
Default wallets with the least setupclient + reactLargest
Selected wallets with the kit modalclient/selective + react + named adaptersMedium
Your own wallet interfacecore + named adaptersSmallest

The all-in-one client includes first-party adapter factories. If your app supports only a few wallets, import those adapter packages directly as shown below.

Quick Start ​

tsx
import { WalletManager } from "@xrpl-wallet-kit/core";
import { createGemWalletAdapter } from "@xrpl-wallet-kit/adapter-gemwallet";
import { createCrossmarkAdapter } from "@xrpl-wallet-kit/adapter-crossmark";
import { WalletKitProvider, WalletButton } from "@xrpl-wallet-kit/react";

const manager = new WalletManager({
  autoReconnect: true,
  adapters: [createGemWalletAdapter(), createCrossmarkAdapter()],
});

function App() {
  return (
    <WalletKitProvider manager={manager}>
      <WalletButton />
    </WalletKitProvider>
  );
}

WalletButton renders a fully self-contained connect / account panel button. No extra configuration needed.

Xahau and Additional Wallets ​

Use the full client to configure Xahau without importing the protocol manually:

tsx
import { createWalletClient } from "@xrpl-wallet-kit/client";

const manager = createWalletClient({
  network: "xahau-mainnet",
  wallets: ["xaman", "gemwallet", "xyra", "ledger"],
  xamanClientId: "YOUR_XAMAN_CLIENT_ID",
  preflight: { maxFeeDrops: "50000" },
});
// Pass this manager to WalletKitProvider as above.

The provider filters its modal by network support. Set ui.walletList.layout to "auto" on the provider for an adaptive list/card picker. For a smaller explicit core/selective setup, follow Xahau Configuration. Xahau reconnects explicitly after reload.

On XRPL, opt into GhostSig, Xyra and Joey Wallet with wallets: ["ghostsig", "xyra", "joey-wallet"]. They are not in the default XRPL list. Joey's extension ID is distinct from WalletConnect's joey.

WalletKitProvider ​

Wrap your application (or the subtree that needs wallet access) with WalletKitProvider:

tsx
import { WalletKitProvider } from "@xrpl-wallet-kit/react";

function App() {
  return (
    <WalletKitProvider
      manager={manager}
      ui={{
        mode: "dark",
        modal: { title: "Connect to MyApp" },
      }}
    >
      <MyApp />
    </WalletKitProvider>
  );
}

Props:

ts
interface WalletKitProviderProps {
  manager: WalletManager;     // required
  ui?: WalletUiConfig;        // optional — theme, locale, modal config
  children: React.ReactNode;
}

The provider creates and manages the WalletModal internally. You do not need to instantiate it yourself.

Hooks ​

useWalletKit() ​

The main hook. Returns the full context value:

tsx
function MyComponent() {
  const { account, status, openModal, disconnect } = useWalletKit();

  if (status === "disconnected") {
    return <button onClick={openModal}>Connect Wallet</button>;
  }

  if (status === "connecting") {
    return <span>Connecting…</span>;
  }

  return (
    <div>
      <span>{account?.address}</span>
      <button onClick={disconnect}>Disconnect</button>
    </div>
  );
}

Returns:

ts
interface WalletKitContextValue {
  manager: WalletManager;
  session: WalletSession | null;
  account: WalletAccount | null;
  status: "disconnected" | "connecting" | "connected";
  wallets: WalletMetadata[];       // all registered adapters
  availability: Record<string, boolean | "unknown">;
  refreshAvailability: () => Promise<void>;
  connect: (adapterId: string) => Promise<WalletSession>;
  disconnect: () => Promise<void>;
  openModal: () => void;
  closeModal: () => void;
  modal: WalletModal | null;       // null during SSR and before client mount
}

For a custom selector, treat "unknown" as a pending check. Detection is a hint, not a reason to disable web/mobile/hardware wallets. Filter by chain separately:

tsx
import { adapterSupportsNetwork } from "@xrpl-wallet-kit/core";

function WalletList() {
  const { manager, wallets, availability, connect } = useWalletKit();

  return wallets.filter(wallet => adapterSupportsNetwork(
    manager.getAdapter(wallet.id)!, manager.getNetwork(),
  )).map((wallet) => (
    <button
      key={wallet.id}
      aria-busy={availability[wallet.id] === "unknown"}
      onClick={() => connect(wallet.id)}
    >
      {wallet.name}
    </button>
  ));
}

useWalletSession() ​

Returns the current WalletSession or null:

tsx
function SessionDisplay() {
  const session = useWalletSession();
  return session
    ? <span>Connected via {session.adapterId}</span>
    : <span>Not connected</span>;
}

useWalletAccount() ​

Returns the current WalletAccount or null:

tsx
function AddressDisplay() {
  const account = useWalletAccount();
  return account
    ? <span>{account.address}</span>
    : null;
}

useWalletStatus() ​

Returns "disconnected" | "connecting" | "connected" for status indicators. It reads the shared context; it does not establish an independent subscription or guarantee fewer renders:

tsx
function StatusDot() {
  const status = useWalletStatus();
  return <span className={`dot dot--${status}`} />;
}

useWalletCapabilities() ​

Returns the active adapter's capabilities, or undefined if not connected:

tsx
function SignButton() {
  const capabilities = useWalletCapabilities();

  if (!capabilities?.signMessage) {
    return <span>This wallet does not support message signing</span>;
  }

  return <button onClick={sign}>Sign Message</button>;
}

WalletButton Component ​

Drop-in connect button — renders disconnected state, connecting state, connected account panel, and disconnect all automatically:

tsx
import { WalletButton } from "@xrpl-wallet-kit/react";

// Default
<WalletButton />

// With options
<WalletButton label="Connect XRPL Wallet" size="lg" variant="pill" />

// Brand icon while disconnected
<WalletButton
  label="Connect"
  icon={{ type: "image", src: "/brand-wallet.svg", alt: "MyApp wallet" }}
/>

Props (all optional):

ts
type ReactWalletButtonProps = {
  label?: string;
  size?: "sm" | "md" | "lg";
  variant?: "default" | "pill" | "minimal" | "outline";
  icon?: { type: "default" }
    | { type: "image"; src: string; alt?: string }
    | { type: "html"; html: string; ariaLabel?: string };
  showAdapterIcon?: boolean;
  showChevron?: boolean;
  showBalance?: boolean;
  balanceResolver?: WalletBalanceResolver;
};

This is a subset: the component accepts managed WalletButtonOptions plus span attributes. With showBalance, the native balance is hidden in a constrained button before wrapping but remains in the account panel.

WalletButton must be used inside a WalletKitProvider.

Custom Connect Button ​

If you want full control over the button UI, use openModal from useWalletKit():

tsx
function CustomConnectButton() {
  const { openModal, account } = useWalletKit();

  if (account) {
    return <span>{account.address.slice(0, 8)}…</span>;
  }

  return (
    <button
      onClick={openModal}
      className="my-custom-button"
    >
      Connect Wallet
    </button>
  );
}

SSR / Server Components ​

WalletKitProvider keeps its children and a deterministic context value in server-rendered HTML. The modal is created client-side only, so modal is initially null; openModal() and closeModal() are safe no-ops until it mounts.

The React package publishes a "use client" boundary and works directly in Next.js App Router Client Components. The dedicated @xrpl-wallet-kit/next package remains available as a thin discoverability alias. See the Next.js guide for provider placement.

The provider requests manager.autoReconnect() after mount. Set the manager's autoReconnect: true to allow supported restoration; do not add another startup effect for the same call. Use the manager for transactions and native login: manager.signTransaction(), signAndSubmit(), signMessage() and signIn(). Check capabilities and see native sign-in for Joey.

TypeScript ​

All types are exported:

ts
import type {
  WalletKitContextValue,
  WalletKitProviderProps,
  WalletKitStatus,
  ReactWalletButtonProps,
} from "@xrpl-wallet-kit/react";

Released under the MIT License.