Widget Implementation in Next.js + wagmi

Here is a step-by-step guide to integrate the widget into your dApp seamlessly. You can find the complete implementation in this repo.

  1. If you are creating a new repository, start by initializing a new Next.js app. If a Next.js project is already set up, you can skip this step.

npx create-next-app@latest <your-app-name>
  1. Navigate to your app directory.

cd <your-app-name>
  1. After setting up your preferences, install the required packages. You can use any package manager of your choice, such as yarn or pnpm.

npm i @aarc-xyz/fundkit-web-sdk @aarc-xyz/eth-connector
  1. Next, define your environment variables in the .env file.

NEXT_PUBLIC_API_KEY=your-aarc-api-key
  1. Setup config for the widget.

AarcConfig.ts

"use client";

import {
  FKConfig,
  ThemeName,
  TransactionErrorData,
  TransactionSuccessData,
} from "@aarc-xyz/fundkit-web-sdk";

export const aarcConfig: FKConfig = {
  appName: "Dapp Name",
  module: {
    exchange: {
      enabled: true,
    },
    onRamp: {
      enabled: true,
      onRampConfig: {
        customerId: "323232323",
      },
    },
    bridgeAndSwap: {
      enabled: true,
      fetchOnlyDestinationBalance: false,
      routeType: "Value",
      connectors: [SourceConnectorName.ETHEREUM],
    },
  },
  destination: {
    walletAddress: "0xeDa8Dec60B6C2055B61939dDA41E9173Bab372b2",
  },
  appearance: {
    themeColor: "#A5E547",
    textColor: "#2D2D2D",
    backgroundColor: "#FAFAFA",
    dark: {
      themeColor: "#A5E547",
      textColor: "#FFF",
      backgroundColor: "#2D2D2D",
      highlightColor: "#08091B",
      borderColor: "#424242",
    },
    theme: ThemeName.DARK,
    roundness: 8,
  },
  apiKeys: {
    aarcSDK: process.env.NEXT_PUBLIC_API_KEY ?? "",
  },
  events: {
    onTransactionSuccess: (data: TransactionSuccessData) => {
      console.log("client onTransactionSuccess", data);
    },
    onTransactionError: (data: TransactionErrorData) => {
      console.log("client onTransactionError", data);
    },
    onWidgetClose: () => {
      console.log("client onWidgetClose");
    },
    onWidgetOpen: () => {
      console.log("client onWidgetOpen");
    },
  },
  origin: typeof window !== "undefined" ? window.location.origin : "",
};
  1. Setup your wagmi & RainbowKit.

import { arbitrum, base, mainnet, optimism, polygon, linea, avalanche, bsc } from "wagmi/chains";

export const wagmiConfig = getDefaultConfig({
  appName: "Your App Rainbowkit",
  projectId: "YOUR_RAINBOW_KIT_PROJECT_ID",
  chains: [mainnet, polygon, optimism, arbitrum, base, linea, avalanche, bsc],
  transports: {
    [mainnet.id]: http(),
    [polygon.id]: http(),
    [optimism.id]: http(),
    [arbitrum.id]: http(),
    [base.id]: http(),
    [linea.id]: http(),
    [avalanche.id]: http(),
    [bsc.id]: http(),
  },
});
  1. Create a custom provider to manage the widget's state consistently throughout the application.

contexts/AarcProvider.tsx

"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import "@aarc-xyz/eth-connector/styles.css";
import {
  AarcFundKitModal,
  SourceConnectorName
} from "@aarc-xyz/fundkit-web-sdk";
import { createContext, useContext, useRef } from "react";
import { useEffect } from "react";
import dynamic from "next/dynamic";
import { http, WagmiProvider } from "wagmi";
import { getDefaultConfig, RainbowKitProvider } from "@rainbow-me/rainbowkit";
import { AarcEthWalletConnector } from "@aarc-xyz/eth-connector";
import { wagmiConfig } from "your-wagmi-config";
import { aarcConfig } from "your-aarc-config"

interface AarcProviderProps {
  children: React.ReactNode;
}

interface AarcContextType {
  aarcModal: AarcFundKitModal | null;
}

const AarcContext = createContext<AarcContextType | undefined>(undefined);

const queryClient = new QueryClient();

const AarcProvider = ({ children }: AarcProviderProps) => {
  const aarcModalRef = useRef<AarcFundKitModal | null>(
    new AarcFundKitModal(aarcConfig)
  );

  const aarcModal = aarcModalRef.current;

  if (!aarcModal) {
    return null; // Or a fallback UI while initializing
  }

  return (
    <WagmiProvider config={wagmiConfig}>
      <QueryClientProvider client={queryClient}>
        <RainbowKitProvider>
          <AarcEthWalletConnector aarcWebClient={aarcModal}>
            <AarcContext.Provider value={{ aarcModal }}>
              {children}
            </AarcContext.Provider>
          </AarcEthWalletConnector>
        </RainbowKitProvider>
      </QueryClientProvider>
    </WagmiProvider>
  );
};

export const useAarcContext = () => {
  const context = useContext(AarcContext);
  if (!context) {
    throw new Error("useAarcContext must be used within AarcProvider");
  }
  return context;
};

export default AarcProvider;
  1. Wrap the application with the necessary provider(s).

In root component:

import AarcProvider from "@/contexts/AarcProvider"

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
     <AarcProvider>
        {children}
     </AarcProvider>
  );
}
  1. Opening widget.

"use client";

import { useAarcContext } from "@/contexts/AarcProvider";

export default function YourComponent() {
  const { aarcModal } = useAarcContext();

  return (
        <button
          onClick={() => {
            aarcModal?.openModal();
          }}
        >
          Open Aarc Widget
        </button>
  );
}

Last updated