> For the complete documentation index, see [llms.txt](https://dev.ada-anvil.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dev.ada-anvil.io/guides/transaction/create-basic-transaction/nextjs-with-weld/nextjs-with-weld-wallet.md).

# Part 2: Wallet Integration

## Weld Wallet Integration Overview

Weld is a universal Cardano wallet connector library that simplifies wallet integration by providing:

* A unified interface for multiple Cardano wallets
* TypeScript support with full type safety
* React hooks for state management
* Server-side rendering compatibility

See the [Weld documentation](https://github.com/Cardano-Forge/weld) for more information.

## Implementation Steps

### 1. Create the Weld Provider Component

First, we need to create a provider component that will make Weld available throughout your application. This component will handle wallet connectivity state and server/client hydration:

```tsx
// src/components/WeldProvider.tsx
"use client";

import { WeldProvider, type WeldProviderProps } from "@ada-anvil/weld/react";

export function ClientWeldProvider({
  children,
  lastConnectedWallet,
}: {
  children: React.ReactNode;
  lastConnectedWallet?: NonNullable<
    WeldProviderProps["wallet"]
  >["tryToReconnectTo"];
}) {
  return (
    <WeldProvider
      updateInterval={30_000} // 30 seconds
      wallet={{ tryToReconnectTo: lastConnectedWallet }} // Restore wallet connection state
    >
      {children}
    </WeldProvider>
  );
}
```

{% hint style="info" %}
The `updateInterval` option (set to 30 seconds) helps maintain active wallet connections during longer user sessions.
{% endhint %}

### 2. Integrate the Provider in Your Layout

Next, we'll update the app layout to use our `ClientWeldProvider`. Notice that we include the `lastConnectedWallet` prop to restore wallet connection state between server and client. This is important for maintaining wallet connectivity during page navigation, and preventing React hydration errors due to server-side rendering being inconsistent with client-side rendering.

See the [Server-Side Rendering (SSR) section in the Weld documentation](https://github.com/Cardano-Forge/weld?tab=readme-ov-file#server-side-rendering) for more information.

```tsx
// src/app/layout.tsx
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";

// Add the three imports.
import { ClientWeldProvider } from "@/components/WeldProvider";
import { cookies } from "next/headers";
import { STORAGE_KEYS } from "@ada-anvil/weld/server";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Cardano Transaction App",
  description: "Send Cardano transactions using the Anvil API",
};

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {

  // Add the cookie retrieval logic.
  const cookieStore = await cookies();
  const wallet = cookieStore.get(STORAGE_KEYS.connectedWallet)?.value;
  const changeAddress = cookieStore.get(STORAGE_KEYS.connectedChange)?.value;
  const stakeAddress = cookieStore.get(STORAGE_KEYS.connectedStake)?.value;
  const lastConnectedWallet = wallet ? { wallet, changeAddress, stakeAddress } : undefined;

  return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        {/* Wrap the children with the ClientWeldProvider component. */}
        <ClientWeldProvider lastConnectedWallet={lastConnectedWallet}>
          {children}
        </ClientWeldProvider>
      </body>
    </html>
  );
}
```

### 3. Understanding SSR with Weld

Our implementation addresses three critical aspects of wallet integration in Next.js with SSR:

1. **Hydration Consistency**: By retrieving wallet connection data from cookies during server-side rendering, we ensure the initial client-side state matches what was rendered on the server, preventing React hydration errors.
2. **Connection Persistence**: The `updateInterval` configuration keeps an active wallet connection stable through periodic state checks.
3. **Seamless Reconnection**: The `tryToReconnectTo` property provides a smooth user experience by maintaining wallet connections across page refreshes.

### 4. Create a Wallet Connector Component

Now let's create a UI component that users will interact with to connect their wallets:

```tsx
// src/components/WalletConnector.tsx
"use client";
import { useState } from "react";

// Import Weld hooks to get wallet and user extensions. 
import { useWallet, useExtensions } from "@ada-anvil/weld/react";

// Import supported wallets from Weld.
import { SUPPORTED_WALLETS } from "@ada-anvil/weld";

// Helper function to truncate address for display
const truncateAddress = (address: string) => {
  if (!address) return "";
  return `${address.slice(0, 8)}...${address.slice(-8)}`;
};

// Component to display wallet info
const WalletInfo = ({ label, value }: { label: string; value: string }) => (
  <div>
    <span>{label} </span>
    <span>
      <b>{value}</b>
    </span>
  </div>
);

export default function WalletConnector() {
  const wallet = useWallet();
  const { supportedMap: installedWallets, isLoading } = useExtensions(
    "supportedMap",
    "isLoading",
  );
  const availableWallets = SUPPORTED_WALLETS.filter((w) =>
    installedWallets.has(w.key),
  );
  const [selectedWallet, setSelectedWallet] = useState<string>("");

  // Reset connection state if wallet selection changes
  const handleWalletSelection = (value: string) => {
    if (wallet.isConnectingTo && value !== wallet.isConnectingTo) {
      // Cancel any pending connection
      wallet
        .disconnect()
        .catch((err) => console.error("Failed to disconnect wallet:", err));
    }
    setSelectedWallet(value);
  };

  const handleConnect = async (walletKey?: string) => {
    if (!walletKey) return;
    try {
      await wallet.connectAsync(walletKey);
    } catch (error) {
      console.error("Failed to connect wallet:", error);
    }
  };

  return (
    <section className="paper">
      <h2>Wallet</h2>

      {wallet.isConnected ? (
        // Connected state - show wallet info and disconnect button
        <>
          <WalletInfo label="Connected to:" value={wallet.displayName || ""} />
          <WalletInfo
            label="Address:"
            value={truncateAddress(wallet.changeAddressBech32 || "")}
          />
          <WalletInfo
            label="Balance:"
            value={`${wallet.balanceAda?.toFixed(2) || "0.00"} ADA`}
          />

          <button
            onClick={() =>
              wallet
                .disconnect()
                .catch((err) =>
                  console.error("Failed to disconnect wallet:", err),
                )
            }
            className="btn mt-4"
          >
            Disconnect
          </button>
        </>
      ) : // Disconnected state - show wallet selector and connect button
      isLoading ? (
        <div>Detecting wallet extensions...</div>
      ) : (
        <div>
          <select
            className="custom-rounded mb-4"
            name="wallet-key"
            value={selectedWallet}
            onChange={(e) => handleWalletSelection(e.target.value)}
          >
            {availableWallets.length === 0 ? (
              <option value="">No wallets</option>
            ) : (
              <>
                <option value="">Select a wallet</option>
                {availableWallets.map((w) => (
                  <option key={w.key} value={w.key}>
                    {w.displayName}
                  </option>
                ))}
              </>
            )}
          </select>
          <button
            onClick={() => selectedWallet && handleConnect(selectedWallet)}
            className="btn text-center"
            disabled={wallet.isConnecting || availableWallets.length === 0}
          >
            {wallet.isConnecting
              ? `Connecting to ${wallet.isConnectingTo}...`
              : selectedWallet
                ? "Connect Wallet"
                : "Select a Wallet"}
          </button>
        </div>
      )}
    </section>
  );
}
```

### 5. Update the Home Page

Now that we have created the component. Lets update your home page to include the wallet connector component:

```tsx
// src/app/page.tsx
import WalletConnector from "@/components/WalletConnector";

export default function Home() {
  return (
    <main className="container mx-auto p-4">
      <h1 className="text-2xl font-bold mb-6">Cardano Transaction App</h1>
      <div className="max-w-md mx-auto">
        <WalletConnector />
      </div>
    </main>
  );
}
```

## Testing Your Wallet Integration

Now let's test the wallet integration to ensure it's working correctly:

1. **Start your development server**:

```bash
npm run dev
```

2. **Navigate to your application** (usually at <http://localhost:3000>)
3. **Test the wallet connection flow**:
   * Verify that available wallets are correctly detected in the dropdown
   * Select a wallet and click "Connect Wallet"
   * Confirm that the wallet popup appears requesting connection
   * After approving, verify that wallet information is displayed:
     * Connected wallet name
     * Truncated wallet address
     * ADA balance
4. **Test disconnection**:
   * Click the "Disconnect" button
   * Verify that the UI returns to the wallet selection state

{% hint style="warning" %}
If wallet connection fails, check your browser console for errors. Common issues include:

* Wallet extension not properly installed
* Wallet needs to be enabled for dApp interactions.
* Wallet locked (needs to be unlocked first)
* Incompatible wallet versions
  {% endhint %}

## Troubleshooting

### No Wallets Detected

If no wallets are appearing in the dropdown list:

1. Make sure you have wallet extensions installed (Eternl, Lace, etc.)
2. Refresh the page after installing a new wallet extension
3. Check your browser console for any errors

## What's Next?

Now that you have a working wallet integration, you're ready to implement transaction functionality. In [Part 3: Building Transactions](/guides/transaction/create-basic-transaction/nextjs-with-weld/nextjs-with-weld-transactions.md), we'll create the components and API routes needed to build and submit Cardano transactions.

{% hint style="success" %}
Congratulations! You've completed Part 2 of the guide. Your application can now detect wallets, connect to them, and display wallet information.
{% endhint %}
