npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gaian-sdk/widgets

v0.2.2

Published

Scan-to-Pay and Order History widgets for React (Rollup build)

Readme

Gaian Widget SDK — Quick Integration Guide

This README walks you through integrating @gaian-sdk/widgets into a React app from zero to working screens:

  1. Install the widget SDK
  2. Reset CSS (or delete your global CSS)
  3. Install Solana libraries
  4. Wrap Solana Provider and GaianProvider
  5. Set up the Scan button (onScan)
  6. Add an Order Page
  7. Add Transaction History

Prereqs

  • Node 18+ / pnpm, npm or yarn
  • React 18+
  • Vite or Next.js (examples below use Vite-style entry)

1) Install @gaian-sdk/widgets

# with pnpm (recommended)
pnpm add @gaian-sdk/widgets

# or npm\ nnpm i @gaian-sdk/widgets

# or yarn
yarn add @gaian-sdk/widgets

If you’re using TypeScript, make sure you’re on TS 5.x+.


2) Reset CSS or delete your app CSS

The widget ships with its own styles. To avoid style clashes, either:

Delete your global CSS

  • Remove import './index.css' (or ./App.css) from your entry files (e.g., main.tsx, index.tsx).
  • Delete the css file(s) if you don’t need them.

3) Install Solana libraries

pnpm add @solana/web3.js \
          @solana/wallet-adapter-base \
          @solana/wallet-adapter-wallets \
          @solana/wallet-adapter-react \
          @solana/wallet-adapter-react-ui \
          @solana/wallet-adapter-phantom

The widget expects a Wallet Adapter context to be present. We’ll wire it next.


4) Wrap Solana Provider and GaianProvider

Create a small provider shell that sets up Solana (RPC + wallets) and the Gaian config.

// src/providers/AppProviders.tsx
import React, { PropsWithChildren, useMemo } from "react";
import {
  ConnectionProvider,
  WalletProvider,
} from "@solana/wallet-adapter-react";
import { WalletModalProvider } from "@solana/wallet-adapter-react-ui";
import { PhantomWalletAdapter } from "@solana/wallet-adapter-phantom";
import "@solana/wallet-adapter-react-ui/styles.css";

import { GaianProvider } from "@gaian-sdk/widgets";

const RPC_DEVNET = "https://api.devnet.solana.com";
const RPC_MAINNET = "https://api.mainnet-beta.solana.com";

export function AppProviders({ children }: PropsWithChildren) {
  // switch envs however your app prefers
  const endpoint = RPC_DEVNET; // or RPC_MAINNET
  const wallets = useMemo(() => [new PhantomWalletAdapter()], []);

  return (
    <ConnectionProvider endpoint={endpoint}>
      <WalletProvider wallets={wallets} autoConnect>
        <WalletModalProvider>
          <GaianProvider
            config={{
              partnerCode: "YOUR_PARTNER_CODE",
              mode: "dev", // 'dev' | 'prod'
            }}
          >
            {children}
          </GaianProvider>
        </WalletModalProvider>
      </WalletProvider>
    </ConnectionProvider>
  );
}

5) Set up routes

Add React Router so your Scan button can navigate to the Order and History pages.

pnpm install react-router-dom
# or: npm i react-router-dom / yarn add react-router-dom

Create the router and wrap your app:

// src/App.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { RouterProvider } from "react-router-dom";
import { router } from "./routes/";
import { AppProviders } from "./providers/AppProviders";

export default function App() {
  return (
    <AppProviders>
      <RouterProvider router={router} />
    </AppProviders>
  );
}

Define routes for Home, Order, and History:

// src/routes/index.tsx
import { createBrowserRouter } from "react-router-dom";
import App from "./App";
import OrderPageRoute from "./pages/OrderPage";
import HistoryPage from "./pages/HistoryPage";

export const router = createBrowserRouter([
  { path: "/", element: <HomePage /> },
  { path: "/orders/:orderId", element: <OrderPageRoute /> },
  { path: "/history", element: <HistoryPage /> },
]);

6) Set up the Scan button (onScan)

Use the widget’s scan hook to get onScan, then wire it to any button.

// src/components/ScanToPayButton.tsx
import React from "react";
import { useScanQr } from "@gaian-sdk/widgets";

export function ScanToPayButton() {
  const { onScan } = useScanQr({
    userEmail: "[email protected]",
    onSuccess(data) {
      console.log("Data response:", data);
      window.location.href = `/order/${data.orderId}`;
    },
    onError(error) {
      console.log(error);
    },
  });

  return (
    <div>
      <button onClick={onScan}>Scan</button>
    </div>
  );
}

Use it anywhere:

// src/pages/HomePage.tsx
import React from "react";
import { ScanToPayButton } from "./components/ScanToPayButton";

export default function App() {
  return (
    <main style={{ padding: 24 }}>
      <h1>Gaian Widget Demo</h1>
      <ScanToPayButton />
    </main>
  );
}

7) Set up OrderPage

Drop-in page to display order status and payment progress.

// src/pages/OrderPage.tsx
import React from "react";
import { OrderPage } from "@gaian-sdk/widgets";
import { useParams } from "react-router-dom";

export default function OrderPageRoute() {
  const { orderId } = useParams();
  if (!orderId) return <p>Missing orderId</p>;
  return <OrderPage orderId={orderId} />;
}

OrderPage fetches by orderId and renders real-time status updates.


8) Set up TransactionHistory

Embed a history list for the current user. You can filter by wallet or user profile depending on your integration.

// src/pages/HistoryPage.tsx
import React from "react";
import { TransactionHistory } from "@gaian-sdk/widgets";

export default function HistoryPage() {
  return (
    <section style={{ padding: 24 }}>
      <h2>Transaction History</h2>
      <TransactionHistory />
    </section>
  );
}

Environment & Config Notes

  • GaianProvider requires:

    • partnerCode — issued by Gaian
    • mode'dev' | 'prod'
  • Solana RPC: use Devnet for development, switch to Mainnet for production.

  • Wallets: start with Phantom; add more by pushing adapters into the wallets array.


Minimal working example (all-in-one)

// main.tsx (Vite)
import React from "react";
import ReactDOM from "react-dom/client";
import "modern-normalize/modern-normalize.css";
import {
  ConnectionProvider,
  WalletProvider,
} from "@solana/wallet-adapter-react";
import { WalletModalProvider } from "@solana/wallet-adapter-react-ui";
import { PhantomWalletAdapter } from "@solana/wallet-adapter-phantom";
import "@solana/wallet-adapter-react-ui/styles.css";
import { GaianProviderBYO, useScanQr } from "@gaian-sdk/widgets";

function ScanBtn() {
  const { onScan } = useScanQr({
    userEmail: "[email protected]",
    onSuccess(data) {
      console.log("Data response:", data);
      window.location.href = `/order/${data.orderId}`;
    },
    onError(error) {
      console.log(error);
    },
  });
  return <button onClick={onScan}>Scan & Pay</button>;
}

function App() {
  return (
    <main style={{ padding: 24 }}>
      <h1>Gaian + Solana</h1>
      <ScanBtn />
    </main>
  );
}

const endpoint = "https://api.devnet.solana.com";
const wallets = [new PhantomWalletAdapter()];

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <ConnectionProvider endpoint={endpoint}>
      <WalletProvider wallets={wallets} autoConnect>
        <WalletModalProvider>
          <GaianProvider
            config={{ partnerCode: "YOUR_PARTNER_CODE", mode: "dev" }}
          >
            <App />
          </GaianProvider>
        </WalletModalProvider>
      </WalletProvider>
    </ConnectionProvider>
  </React.StrictMode>
);

Troubleshooting

  • No wallet found: ensure Phantom (or another wallet) is installed and your wallets array includes its adapter.
  • Styles look off: remove your global CSS or import a reset before anything else. Avoid overwriting the widget’s class names.
  • Callbacks not firing: if you supplied onSuccess/onError, check they’re passed to useScanQr({ ... }) and that you’re not catching/swallowing errors elsewhere.
  • Order page shows nothing: confirm the orderId is present in the route and accessible via useParams().