@gaian-sdk/widgets
v0.2.2
Published
Scan-to-Pay and Order History widgets for React (Rollup build)
Maintainers
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:
- Install the widget SDK
- Reset CSS (or delete your global CSS)
- Install Solana libraries
- Wrap Solana Provider and GaianProvider
- Set up the Scan button (
onScan) - Add an Order Page
- 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/widgetsIf 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-phantomThe 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-domCreate 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} />;
}
OrderPagefetches byorderIdand 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
GaianProviderrequires:partnerCode— issued by Gaianmode—'dev' | 'prod'
Solana RPC: use Devnet for development, switch to Mainnet for production.
Wallets: start with Phantom; add more by pushing adapters into the
walletsarray.
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
walletsarray 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 touseScanQr({ ... })and that you’re not catching/swallowing errors elsewhere. - Order page shows nothing: confirm the
orderIdis present in the route and accessible viauseParams().
