Issue with Fuel wallet connector packages when using with NextJs 15

I was trying to integrate Fuel’s official wallet connectors packages in my NextJs 15 Dapp. But the packages are not working as expected. The problems I am facing are -

  • The switch network is not working automatically from the package
  • No popup for the bridge when a wallet doesn’t have ETH token
  • The wallet object is null when connecting with any other than the fuel wallet.

I am also getting an error in my console -

⨯ Error: dynamic usage of require is not supported
    at requireStub (C:\Users\HP\Desktop\Development\Work\Frontend\Fuel\fuelup-v2\.next\server\chunks\ssr\[turbopack]_runtime.js:337:11)
    at instantiateModule (C:\Users\HP\Desktop\Development\Work\Frontend\Fuel\fuelup-v2\.next\server\chunks\ssr\[turbopack]_runtime.js:590:23)
    at getOrInstantiateModuleFromParent (C:\Users\HP\Desktop\Development\Work\Frontend\Fuel\fuelup-v2\.next\server\chunks\ssr\[turbopack]_runtime.js:645:12)
    at esmImport (C:\Users\HP\Desktop\Development\Work\Frontend\Fuel\fuelup-v2\.next\server\chunks\ssr\[turbopack]_runtime.js:132:20)
    at [project]/contexts/wallet-providers/FuelProviders.tsx [app-ssr] (ecmascript) (file://C%3A/Users/HP/Desktop/Development/Work/Frontend/Fuel/fuelup-v2/contexts/wallet-providers/FuelProviders.tsx:4:0)
    at instantiateModule (C:\Users\HP\Desktop\Development\Work\Frontend\Fuel\fuelup-v2\.next\server\chunks\ssr\[turbopack]_runtime.js:590:23)
    at getOrInstantiateModuleFromParent (C:\Users\HP\Desktop\Development\Work\Frontend\Fuel\fuelup-v2\.next\server\chunks\ssr\[turbopack]_runtime.js:645:12)
    at esmImport (C:\Users\HP\Desktop\Development\Work\Frontend\Fuel\fuelup-v2\.next\server\chunks\ssr\[turbopack]_runtime.js:132:20)
    at [project]/contexts/wallet-providers/WalletProviders.tsx [app-ssr] (ecmascript) (file://C%3A/Users/HP/Desktop/Development/Work/Frontend/Fuel/fuelup-v2/contexts/wallet-providers/WalletProviders.tsx:7:0)
    at instantiateModule (C:\Users\HP\Desktop\Development\Work\Frontend\Fuel\fuelup-v2\.next\server\chunks\ssr\[turbopack]_runtime.js:590:23)
    at getOrInstantiateModuleFromParent (C:\Users\HP\Desktop\Development\Work\Frontend\Fuel\fuelup-v2\.next\server\chunks\ssr\[turbopack]_runtime.js:645:12)
    at commonJsRequire (C:\Users\HP\Desktop\Development\Work\Frontend\Fuel\fuelup-v2\.next\server\chunks\ssr\[turbopack]_runtime.js:147:20)
  2 |
  3 | import { DEFAULT_WAGMI_CONFIG } from "@/configs";  
> 4 | import { createConfig, defaultConnectors } from "@fuels/connectors";
  5 | import { FuelProvider } from "@fuels/react";       
  6 | import { CHAIN_IDS, Provider } from "fuels";       
  7 | {
  digest: '1668858999'
}

However, all the above functionalities work when using the same Vite + React Dapp packages.

I have used the fuels official example Dapp as a reference to integrate fuel connectors.

Here are the package versions that I am using in my Dapp -

"@fuels/connectors": "^0.36.1",
"@fuels/react": "^0.36.1",
"connectkit": "^1.8.2",
"fuels": "^0.99.0",
"wagmi": "^2.14.9"

Here are code snippets that I’m using from the example project on github -

// ConnectProvider.tsx

"use client";

import { ConnectKitProvider } from "connectkit";
import type { ReactNode } from "react";
import type { State } from "wagmi";
import { WagmiProvider } from "wagmi";
import { DEFAULT_WAGMI_CONFIG } from "@/configs";

type ProvidersProps = {
  children: ReactNode;
  wagmiInitialState: State | undefined;
};

export const ConnectProvider = ({
  children,
  wagmiInitialState,
}: Readonly<ProvidersProps>) => {
  return (
    <WagmiProvider
      config={DEFAULT_WAGMI_CONFIG}
      initialState={wagmiInitialState}>
      <ConnectKitProvider>{children}</ConnectKitProvider>
    </WagmiProvider>
  );
};
// FuelProviders.tsx
"use client";

import { DEFAULT_WAGMI_CONFIG } from "@/configs";
import { createConfig, defaultConnectors } from "@fuels/connectors";
import { FuelProvider } from "@fuels/react";
import { CHAIN_IDS, Provider } from "fuels";

const NETWORKS = [
  {
    chainId: CHAIN_IDS.fuel.mainnet,
    url: "https://mainnet.fuel.network/v1/graphql",
  },
];

const FUEL_CONFIG = createConfig(() => {
  return {
    connectors: defaultConnectors({
      devMode: process.env.NODE_ENV === "development",
      wcProjectId: process.env.NEXT_PUBLIC_WC_PROJECT_ID,
      ethWagmiConfig: DEFAULT_WAGMI_CONFIG as any,
      chainId: NETWORKS[0].chainId,
      fuelProvider: new Provider(NETWORKS[0].url),
    }),
  };
});

export const FuelProviders = ({ children }: { children: React.ReactNode }) => {
  return (
    <FuelProvider theme="dark" fuelConfig={FUEL_CONFIG} networks={NETWORKS}>
      {children}
    </FuelProvider>
  );
};
// WalletProviders.tsx

"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import type React from "react";
import type { State } from "wagmi";
import { ConnectProvider } from "./ConnectProvider";
import { FuelProviders } from "./FuelProviders";

type WalletProvidersProps = {
  children: React.ReactNode;
  initialState?: State;
};

const queryClient = new QueryClient();

export const WalletProviders = ({
  children,
  initialState: wagmiInitialState,
}: Readonly<WalletProvidersProps>) => {
  return (
    <QueryClientProvider client={queryClient}>
      <ConnectProvider wagmiInitialState={wagmiInitialState}>
        <FuelProviders>{children}</FuelProviders>
      </ConnectProvider>
    </QueryClientProvider>
  );
};
// connectors.ts

import type { CreateConnectorFn } from "wagmi";
import { coinbaseWallet, injected, walletConnect } from "wagmi/connectors";

export const generateETHConnectors = (
  appName: string
): Array<CreateConnectorFn> => {
  const connectors: Array<CreateConnectorFn> = [
    injected({
      shimDisconnect: true,
      target: () => ({
        id: "io.metamask",
        name: "MetaMask",
        provider: "isMetaMask",
        icon: "https://raw.githubusercontent.com/MetaMask/brand-resources/master/SVG/SVG_MetaMask_Icon_Color.svg",
      }),
    }),
    coinbaseWallet({ appName, headlessMode: true }),
  ];

  if (process.env.NEXT_PUBLIC_WC_PROJECT_ID) {
    connectors.push(
      walletConnect({
        projectId: process.env.NEXT_PUBLIC_WC_PROJECT_ID,
        showQrModal: false,
      })
    );
  }

  return connectors;
};
// wallet-configs.ts

import { generateETHConnectors } from "@/utils/connectors";
import {
  http,
  cookieStorage,
  createConfig,
  createStorage,
  fallback,
} from "wagmi";
import { type Chain, sepolia } from "wagmi/chains";

export const APP = {
  name: "...",
  description: "...",
};

export const CHAINS_TO_CONNECT = [sepolia] as [Chain, ...Chain[]];

export const TRANSPORTS = {
  [CHAINS_TO_CONNECT[0].id]: fallback(
    [
      http(
        `https://eth-${CHAINS_TO_CONNECT[0].name}.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_WC_PROJECT_ID}`
      ),
      http(),
    ],
    { rank: false }
  ),
};

export const DEFAULT_WAGMI_CONFIG = createConfig({
  chains: CHAINS_TO_CONNECT,
  connectors: generateETHConnectors(APP.name),
  transports: TRANSPORTS,
  storage: createStorage({
    storage: cookieStorage,
  }),
  ssr: true,
});
// layout.tsx

import type { Metadata } from "next";
...
import { headers } from "next/headers";
import { cookieToInitialState } from "wagmi";
import { DEFAULT_WAGMI_CONFIG } from "@/configs";
import { WalletProviders } from "@/contexts/wallet-providers";
...

...

type RootLayoutProps = {
  children: React.ReactNode;
};

const RootLayout = async ({ children }: Readonly<RootLayoutProps>) => {
  const { get } = await headers();
  const wagmiInitialState = cookieToInitialState(DEFAULT_WAGMI_CONFIG, get("cookie"));

  return (
    <html lang="en" className="no-scrollbar">
      <head>
          ...
          ...
      </head>
      <body className="antialiased">
        <WalletProviders initialState={wagmiInitialState}>
          ...
          ...
        </WalletProviders>
      </body>
    </html>
  );
};

export default RootLayout;
1 Like

Hey @bobby-lync :wave:

Can’t see a "use client" in your layout.tsx file, could you please add this and try again.

Currently, the latest fuels version is not compatible with the connectors + react packages. So you may also need to downgrade to 0.97.2 to ensure all functionality works correctly.

4 Likes

Hey @p.s, This solution worked for me. Thanks.

Instead of marking the whole layout.tsx as a client component (by putting a "use client" on the top of the file), I have created another component marked as "use client" and called it a component in the layout.tsx.

Also, I have downgraded the fuels version from "^0.99.0" to "0.97.2".

The modified layout.tsx looks like following -

// layout.tsx

import type { Metadata } from "next";
import "./globals.css";
import { headers } from "next/headers";
import { cookieToInitialState } from "wagmi";
import { DEFAULT_WAGMI_CONFIG } from "@/configs";
import { checkServerStatus } from "@/services/server";
import { RenderLayoutAsClient } from "@/components/common/RenderLayoutAsClient";

export const metadata: Metadata = {
  title: "...",
  description: "...",
};

type RootLayoutProps = {
  children: React.ReactNode;
};

const RootLayout = async ({ children }: Readonly<RootLayoutProps>) => {
  const { get } = await headers();
  const wagmiInitialState = cookieToInitialState(DEFAULT_WAGMI_CONFIG, get("cookie"));

  const isServerOk = await checkServerStatus();

  return (
    <html lang="en" className="no-scrollbar">
      <head>
        ...
        ...
      </head>
      <body className="antialiased">
        <RenderLayoutAsClient isServerOk={isServerOk} wagmiInitialState={wagmiInitialState}>
          {children}
        </RenderLayoutAsClient>
      </body>
    </html>
  );
};

export default RootLayout;
// RenderLayoutAsClient .tsx

"use client";

...
import { WalletProviders } from "@/contexts/wallet-providers";
import React from "react";
...
...
import type { State } from "wagmi";

type RenderLayoutAsClientProps = {
  children: React.ReactNode;
  ...
  wagmiInitialState?: State;
};

export const RenderLayoutAsClient: React.FC<Readonly<RenderLayoutAsClientProps>> = ({
  children,
  ...
  wagmiInitialState,
}) => {
  return (
    <WalletProviders initialState={wagmiInitialState}>
      ...
      ...
    </WalletProviders>
  );
};

3 Likes

Glad you found a solution :slight_smile:

2 Likes

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.