# Quickstart (/getting-started/quickstart)



This walks through the smallest useful app: discover wallets, connect one, show
it, disconnect. It mirrors the `demo-vite` reference app, which uses the
batteries-included `@usebutr/wallets` package.

## 1. Wrap your app in the provider [#1-wrap-your-app-in-the-provider]

`WalletManagerProvider` from `@usebutr/react` is the single provider. Pass it a
`WalletSource` via the `discovery` prop to enable auto-discovery. `autoDiscovery()`
from `@usebutr/wallets` composes EVM (EIP-6963) and Solana (Wallet Standard) in one
call. `storageKeyPrefix` namespaces the storage keys.

Hoist the `discovery` source to module scope so the same instance is reused
across renders:

```tsx title="wallet-provider.tsx"
import type { ReactNode } from "react";
import { WalletManagerProvider } from "@usebutr/react";
import { autoDiscovery } from "@usebutr/wallets";

const discovery = autoDiscovery();

const WalletProvider = ({ children }: { children: ReactNode }) => (
  <WalletManagerProvider discovery={discovery} storageKeyPrefix="butr-demo">
    {children}
  </WalletManagerProvider>
);

export { WalletProvider };
```

Mount it above your tree:

```tsx title="main.tsx"
import ReactDOM from "react-dom/client";
import { App } from "./app";
import { WalletProvider } from "./wallet-provider";

ReactDOM.createRoot(document.querySelector("#root")!).render(
  <WalletProvider>
    <App />
  </WalletProvider>,
);
```

## 2. Wait for hydration [#2-wait-for-hydration]

butr restores the previous session asynchronously. Gate your UI on
`useIsHydrated()` so you don't flash a "not connected" state on reload.

```tsx
import { useIsHydrated } from "@usebutr/react";

const Content = () => {
  const isHydrated = useIsHydrated();
  if (!isHydrated) return <p>Loading…</p>;
  // …
};
```

## 3. List discovered wallets and connect [#3-list-discovered-wallets-and-connect]

`useDiscoveredWallets()` is the live list of adapters that have announced
themselves. `useConnectWallet()` returns a function you call with an adapter
`id`.

```tsx
import { useConnectWallet, useConnectedWallets, useDiscoveredWallets } from "@usebutr/react";

const WalletPicker = () => {
  const connect = useConnectWallet();
  const discovered = useDiscoveredWallets();
  const connected = useConnectedWallets();

  const available = discovered.filter((d) => !connected.some((c) => c.connector.id === d.id));

  return (
    <ul>
      {available.map((wallet) => (
        <li key={wallet.id}>
          <button type="button" onClick={() => connect(wallet.id)}>
            Connect {wallet.name} ({wallet.chainPlatform})
          </button>
        </li>
      ))}
    </ul>
  );
};
```

## 4. Show connected wallets and disconnect [#4-show-connected-wallets-and-disconnect]

```tsx
import { useConnectedWallets, useDisconnectWallet } from "@usebutr/react";

const Connected = () => {
  const wallets = useConnectedWallets();
  const disconnect = useDisconnectWallet();

  return (
    <ul>
      {wallets.map((wallet) => (
        <li key={wallet.connector.id}>
          {wallet.connector.name} — {wallet.account.walletAddress}
          <button type="button" onClick={() => disconnect(wallet.connector.id)}>
            Disconnect
          </button>
        </li>
      ))}
    </ul>
  );
};
```

That is a complete multi-chain connect flow. The same `wallet.connector`
exposes `signMessage`, `sendTx`, `switchChain`, and `getSigner` — see the
[guides](/guides/provider-setup).

<Callout type="info">
  **Source:** `apps/demo-vite` in the [butr
  repository](https://github.com/pedroapfilho/usebutr/tree/main/apps/demo-vite). Run it locally with
  `pnpm dev --filter=demo-vite` (serves on `http://localhost:5173`).
</Callout>

## Next steps [#next-steps]

* [Core concepts](/concepts) — what the pool, selection, and active wallet
  mean, and why hydration is asynchronous.
* [Multi-chain & switching](/guides/multi-chain) — connect more than one
  wallet and switch chains.
* [Signing](/guides/signing) and [Transactions](/guides/transactions).
