npm package: @suzaku-network/lst-widget-react
Description: Drop-in Suzaku staking widget for React apps.
Latest version: 1.0.1

# @suzaku-network/lst-widget-react

Drop-in Suzaku staking widget for React apps.

- **No iframe**
- **No Tailwind required in the host app** (this package ships a compiled, scoped CSS bundle)
- **Host app controls the wallet** (widget uses the host’s `wagmi` context)

---

## Install

```bash
npm i @suzaku-network/lst-widget-react
```

This automatically installs `@suzaku-network/lst-widget-core` as a dependency.

---

## 1) Import the widget CSS (required)

Import once, globally.

### Next.js (App Router)

In `app/layout.tsx`:

```ts
import "@suzaku-network/lst-widget-react/styles.css";
```

### Vite / CRA / Remix

Import in your main entry file (`src/main.tsx`, `src/index.tsx`, `app/root.tsx`, etc.):

```ts
import "@suzaku-network/lst-widget-react/styles.css";
```

---

## 2) Provide required providers (host app owns wallet)

The widget expects these contexts from the host app:

- **`WagmiProvider`**: required
- **`QueryClientProvider`**: required (the widget uses React Query internally)
- **`RainbowKitProvider`**: optional (only if you want RainbowKit UI in your host app)

Minimal provider setup:

```tsx
"use client";

import { WagmiProvider } from "wagmi";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const queryClient = new QueryClient();

export function AppProviders({
  wagmiConfig,
  children,
}: {
  wagmiConfig: any;
  children: React.ReactNode;
}) {
  return (
    <WagmiProvider config={wagmiConfig}>
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    </WagmiProvider>
  );
}
```

---

## 3) Render the widget

```tsx
import { SuzakuWidget } from "@suzaku-network/lst-widget-react";
import type { SuzakuWidgetConfig } from "@suzaku-network/lst-widget-react";

export default function Page() {
  const config: SuzakuWidgetConfig = /* ... */;
  return <SuzakuWidget config={config} className="" />;
}
```

Notes:

- `className` is optional.
- The widget **automatically applies `config.theme`** as CSS variables on its root element (you do **not** need to wrap it in another `<div>` to theme it).

---

## 4) Config (`SuzakuWidgetConfig`)

Type import:

```ts
import type { SuzakuWidgetConfig } from "@suzaku-network/lst-widget-react";
```

The widget takes a single `config` object containing:

- **`contracts`**: all addresses + rewards configuration
- **`info`**: display strings and chain/explorer info (e.g. modal title, explorer URL)
- **`images`** (optional): logos (prefer absolute URLs)
- **`theme`** (optional but recommended): colors/padding/radius/fonts used to style the widget

### Contracts rules

- Use `null` for optional **single** addresses you don’t have:
  - `nativeRewards`, `merklRewards`, `lstWrapper`
- Use `null` for rewards token lists when that rewards system is not configured:
  - `nativeRewardsTokens: null`
  - `merklRewardsTokens: null`
- If the rewards system is configured, pass an array:
  - `nativeRewardsTokens: []`
  - `merklRewardsTokens: []` _format: {address, associatedCampaign, associatedDatabase} check Merkl_

---

## 5) Recommended config structure (4 files)

```
src/
  suzaku-config/
    contracts.ts
    info.ts
    images.ts
    theme.ts
    widgetConfig.ts
```

### `src/suzaku-config/contracts.ts`

```ts
import type { SuzakuWidgetConfig } from "@suzaku-network/lst-widget-react";

export const contracts: SuzakuWidgetConfig["contracts"] = {
  underlying: "0x...",
  collateral: "0x...",
  vault: "0x...",
  vaultHelper: "0x...",
  priceToken: "0x...",
  lstWrapper: null,

  nativeRewards: null, // address of the rewards contract
  merklRewards: null, // address of the merkl distributor contract on this chain

  nativeRewardsTokens: null, // list of rewards tokens || null
  merklRewardsTokens: null, // list of struct {address, associatedCampaign, associatedDatabase} || null
};
```

### `src/suzaku-config/info.ts`

```ts
import type { SuzakuWidgetConfig } from "@suzaku-network/lst-widget-react";

export const info: SuzakuWidgetConfig["info"] = {
  projectId: "your-reown-project-id",
  projectName: "Your Project",
  appTitle: "Your Staking",
  chain: "avalanche", // or "fuji"
  explorer: "https://snowscan.xyz",
  deposits: "enabled", // "enabled" or "disabled"
};
```

### `src/suzaku-config/images.ts`

```ts
import type { SuzakuWidgetConfig } from "@suzaku-network/lst-widget-react";

export const images: SuzakuWidgetConfig["images"] = {
  logoPoweredBy: "https://your-cdn/logo-powered-by.svg",
  logoHeader: "https://your-cdn/logo-header.svg",
  logoRewardsTokens: [],
};
```

### `src/suzaku-config/theme.ts`

```ts
import type { SuzakuWidgetConfig } from "@suzaku-network/lst-widget-react";

export const theme: SuzakuWidgetConfig["theme"] = {
  base: "#313131",
  defaultFontColor: "#ffffff",
  modal: "#1b1b1b",
  primary: "#ff6600",
  secondary: "#ff6600",
  header: "#ffffff",
  footer: "#313131",
  font: "Source Code Pro, monospace",
  fontSizes: {
    basic: "1rem",
    button: "0.85rem",
    label: "0.85rem",
    subtitle: "1.125rem",
    title: "1.5rem",
  },
  uppercase: true,
  paddings: { basic: "1.5rem", modal: "1rem", gap: "0.75rem" },
  radius: { lg: "2rem", md: "1.25rem" },
};
```

### `src/suzaku-config/widgetConfig.ts`

```ts
import type { SuzakuWidgetConfig } from "@suzaku-network/lst-widget-react";
import { contracts } from "./contracts";
import { info } from "./info";
import { images } from "./images";
import { theme } from "./theme";

export const widgetConfig: SuzakuWidgetConfig = {
  contracts,
  info,
  images,
  theme,
};
```

---

## 6) Example Next.js page using RainbowKit connect button

```tsx
"use client";

import "@suzaku-network/lst-widget-react/styles.css";
import { ConnectButton } from "@rainbow-me/rainbowkit";
import { widgetConfig } from "@/suzaku/widgetConfig";

export default function Page() {
  return (
    <div className="flex flex-col min-h-screen w-full items-center justify-center gap-6 bg-white p-6">
      <SuzakuWidget config={widgetConfig} />
      <ConnectButton
        showBalance={false}
        accountStatus="full"
        chainStatus="full"
      />
    </div>
  );
}
```

---

## Troubleshooting

- **Widget looks unstyled**
  - Ensure `@suzaku-network/lst-widget-react/styles.css` is imported once in a global entry.
  - Restart the dev server after installing/updating the package.

- **Wrong network**
  - Ensure the host app’s `wagmi` config uses the same chain as `config.info.chain`.

- **Images don’t load**
  - Use absolute URLs (recommended), or ensure relative paths resolve in the host app.