Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] getDefaultConfig is not a function #1777

Closed
1 task done
nfadeluca opened this issue Feb 17, 2024 · 23 comments
Closed
1 task done

[bug] getDefaultConfig is not a function #1777

nfadeluca opened this issue Feb 17, 2024 · 23 comments

Comments

@nfadeluca
Copy link

nfadeluca commented Feb 17, 2024

Is there an existing issue for this?

  • I have searched the existing issues

RainbowKit Version

2.0.0

wagmi Version

2.5.7

Current Behavior

In a next v14.0.4 project setup with wagmi 2.5.7 and rainbowkit 2.0.0.

Upon page compilation finishing, the error displays:

src\blockchain\config\index.ts (40:39) @ eval
 ⨯ TypeError: (0 , _rainbow_me_rainbowkit__WEBPACK_IMPORTED_MODULE_0__.getDefaultConfig) is not a function

Expected Behavior

getDefaultConfig should work as per the docs.

Steps To Reproduce

I have a config file in /config/index.ts:

import { cookieStorage, createStorage } from 'wagmi'
import {
  getDefaultConfig,
  Chain,
} from '@rainbow-me/rainbowkit';
import {
  mainnet,
  polygon,
  optimism,
  arbitrum,
  base,
  zora,
  goerli,
} from 'wagmi/chains';

export const projectId = process.env.PROJECT_ID;

if (!projectId) throw new Error('Project ID is not defined')


// Local avax custom chain
const avalanche = {
  ...
} as const satisfies Chain

// Create wagmiConfig
export const config = getDefaultConfig({
  appName: "App",
  chains: [avalanche, mainnet, goerli, polygon, optimism, arbitrum, base, zora]
  ssr: true,
  storage: createStorage({
    storage: cookieStorage
  })
})

And I use it in a context provider in /context/index.ts:

import React, { ReactNode } from 'react'
import { config, projectId } from '@/blockchain/config'
import {
  RainbowKitProvider,
} from '@rainbow-me/rainbowkit';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { State, WagmiProvider } from 'wagmi'

// Setup queryClient
const queryClient = new QueryClient()

if (!projectId) throw new Error('Project ID is not defined')

export function ContextProvider({
  children,
  initialState
}: {
  children: ReactNode
  initialState?: State
}) {
  return (
    <WagmiProvider config={config} initialState={initialState}>
      <QueryClientProvider client={queryClient}>
        <RainbowKitProvider>
          {children}
        </RainbowKitProvider>
      </QueryClientProvider>
    </WagmiProvider>
  )
}

And this context provider is finally used in the root layout:

import type { Metadata } from 'next'
import { headers } from 'next/headers'
import { cookieToInitialState } from 'wagmi'
import { config } from '@/blockchain/config'
import { ContextProvider } from '@/context'

import '@/app/globals.css';

export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app'
}

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

const RootLayout: React.FC<LayoutProps> = ({children}) => {
  const initialState = cookieToInitialState(config, headers().get('cookie'))
  return (
    <html lang="en">
      <body>
        <ContextProvider initialState={initialState}>
            {children}
        </ContextProvider>
      </body>
    </html>
  )
}

export default RootLayout;

Ran using npm run dev

Link to Minimal Reproducible Example (CodeSandbox, StackBlitz, etc.)

No response

Anything else?

My directory looks like so:

src
-app
--layout.tsx
-blockchain
--index.ts
-context
--index.ts
...
@magiziz
Copy link
Contributor

magiziz commented Feb 18, 2024

@nfadeluca Thanks for raising this issue!

I've taken a look at your code and a few things that needs to be done to solve this issue:

  • You've not added projectId into your getDefaultConfig function. Make sure to do that first ✅.
  • Import '@rainbow-me/rainbowkit/styles.css' at the top of your layout.tsx file to get RainbowKit styles.
  • You don't need to throw an error if projectId is not specified. We do that for you anyways in getDefaultConfig.
  • Since you're using next.js app router it will include conflicts with with server components and client components. In this case you should import 'use client' at the top of your ContextProvider component to make sure it's only rendered on client side.

Here is the final code for you to try:

layout.tsx

import "@rainbow-me/rainbowkit/styles.css";
import type { Metadata } from 'next'
import { headers } from 'next/headers'
import { cookieToInitialState } from 'wagmi'
import { config } from '@/blockchain/config'
import { ContextProvider } from '@/context'

import '@/app/globals.css';

export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app'
}

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

const RootLayout: React.FC<LayoutProps> = ({children}) => {
  const initialState = cookieToInitialState(config, headers().get('cookie'))
  return (
    <html lang="en">
      <body>
        <ContextProvider initialState={initialState}>
            {children}
        </ContextProvider>
      </body>
    </html>
  )
}

export default RootLayout;

context/index.tsx

"use client";

import React, { ReactNode } from 'react'
import { config } from '@/blockchain/config'
import {
  RainbowKitProvider,
} from '@rainbow-me/rainbowkit';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { State, WagmiProvider } from 'wagmi'

// Setup queryClient
const queryClient = new QueryClient()

export function ContextProvider({
  children,
  initialState
}: {
  children: ReactNode
  initialState?: State
}) {
  return (
    <WagmiProvider config={config} initialState={initialState}>
      <QueryClientProvider client={queryClient}>
        <RainbowKitProvider>
          {children}
        </RainbowKitProvider>
      </QueryClientProvider>
    </WagmiProvider>
  )
}

config/index.ts

import { cookieStorage, createStorage } from 'wagmi'
import {
  getDefaultConfig,
  Chain,
} from '@rainbow-me/rainbowkit';
import {
  mainnet,
  polygon,
  optimism,
  arbitrum,
  base,
  zora,
  goerli,
} from 'wagmi/chains';

export const projectId = process.env.PROJECT_ID;

// Local avax custom chain
const avalanche = {
  ...
} as const satisfies Chain

// Create wagmiConfig
export const config = getDefaultConfig({
  appName: "App",
  chains: [avalanche, mainnet, goerli, polygon, optimism, arbitrum, base, zora],
  ssr: true,
  projectId,
  storage: createStorage({
    storage: cookieStorage
  })
})

Note: You might also get some polyfill errors so make sure to have this fallback in your next.config.mjs file.

Also if it's helpful please refer to our app router example here. Let me know if everything works 🙏

@nfadeluca
Copy link
Author

@kosmoskey Following the example fixed it, I just ended up putting everything in a context file and removing the cookies/state, thank you.

@agonist
Copy link

agonist commented Feb 19, 2024

@kosmoskey in the code you provided, importing the wagmi config inside the layout cause an error since getDefaultConfig seems to be client side. should we use createConfig instead when using cookieToInitialState ?

@magiziz
Copy link
Contributor

magiziz commented Feb 19, 2024

@kosmoskey in the code you provided, importing the wagmi config inside the layout cause an error since getDefaultConfig seems to be client side. should we use createConfig instead when using cookieToInitialState ?

createConfig will also cause the error if rendered as server component. Your choice on whether you want to use getDefaultConfig or createConfig, but getDefaultConfig is much easier since it gives you all the wagmi config + RainbowKit wallets.

@radulff
Copy link

radulff commented Feb 20, 2024

Hi there, i'm getting this exact same error:

"Error: (0 , rainbow_me_rainbowkit__WEBPACK_IMPORTED_MODULE_2_.getDefaultConfig) is not a function".

I have this next.config.ts file:

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  trailingSlash: false,
  swcMinify: true,
  typescript: {
    ignoreBuildErrors: false
  },
  eslint: {
    ignoreDuringBuilds: false
  },
  experimental: {
    urlImports: [],
    scrollRestoration: false
  },
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'raw.githubusercontent.com',
        port: '',
        pathname: '**'
      },
      {
        protocol: 'https',
        hostname: 'avatars.githubusercontent.com',
        port: '',
        pathname: '**'
      }
    ],
    dangerouslyAllowSVG: true
  },
  webpack: config => {
    config.resolve.fallback = { fs: false, net: false, tls: false }
    config.externals.push('pino-pretty', 'lokijs', 'encoding')
    return config
  }
}

module.exports = nextConfig

Currently running these package versions:

   "@rainbow-me/rainbowkit": "^2.0.0",
    "@tanstack/react-query": "^5.20.1",
    "@wagmi/connectors": "^4.1.13",
    "@wagmi/core": "2.6.4",
    "viem": "~2.7.6",
    "wagmi": "^2.5.6"
    "ethers": "6.10.0",
    "next": "14.1.0",

(I plan on removing ethers, but for now still around)

This is my wagmi config file:

import { getDefaultConfig } from '@rainbow-me/rainbowkit'
import { http } from '@wagmi/core'
import { Chain, avalanche, avalancheFuji } from '@wagmi/core/chains'

export const chains: [Chain, ...Chain[]] = [avalanche, avalancheFuji]

export const config = getDefaultConfig({
  appName: 'App',
  appDescription: 'App Description',
  appIcon: '/favicon.ico',
  appUrl: process.env.NEXT_PUBLIC_APP_URL!,
  projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID!,
  chains,
  transports: {
    [avalanche.id]: http()
  },
  ssr: true
})

My providers.tsx:

'use client'

import { RainbowKitProvider } from '@rainbow-me/rainbowkit'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import * as React from 'react'
import { WagmiProvider } from 'wagmi'
import { config } from '../clients/wagmi/config'

const queryClient = new QueryClient()

const wagmiConfig = { ...config }

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <WagmiProvider config={wagmiConfig}>
      <QueryClientProvider client={queryClient}>
        <RainbowKitProvider>{children}</RainbowKitProvider>
      </QueryClientProvider>
    </WagmiProvider>
  )
}

What am I doing wrong here?

Thanks

@magiziz
Copy link
Contributor

magiziz commented Feb 20, 2024

@radulff Can you import 'use-client' at the top of your providers.tsx file ?

@radulff
Copy link

radulff commented Feb 20, 2024

@kosmoskey I'm already doing so, sorry I didn't put it in the question. (Just updated my previous code, to make sure it appears)

@magiziz
Copy link
Contributor

magiziz commented Feb 21, 2024

@radulff The code you provided works totally fine for me i get no errors. Could you please try following this with-next-app example we have and let me know if there is anything else missing in your project ?

@radulff
Copy link

radulff commented Feb 21, 2024

Hi there @kosmoskey, indeed it is working well in the “with-next-app” template. Sorry for the hassle. Do you have any ideas of what could the issue be on my end? How could I debug it? Thanks in advance.

@magiziz
Copy link
Contributor

magiziz commented Feb 21, 2024

@radulff I would suggest looking at the build configuration in your dApp. I am pretty sure you just have to do 'use-client' at the top of your providers.tsx component, but if that doesn't seem to work please feel free to look our next app code here and try to see what's wrong.

@smauret
Copy link

smauret commented Feb 22, 2024

The error persist if you import config in the root layout (needed for cookieToInitialState), is there a working example of rainbowkit + cookieToInitialState somewhere ?

@magiziz
Copy link
Contributor

magiziz commented Feb 22, 2024

@smauret Usually when doing cookieToInitialState it requires some server side action to get the cookies from headers which means it won't be possible if you use 'use-client' which is required in this case.

The one thing you can do is follow the wagmi's cookieToInitialState for config and use that instead.

Just pushed a super simple next app router example with cookieToInitialState here: https://github.com/KosmosKey/rainbowkit-v2-app-router

@smauret
Copy link

smauret commented Feb 22, 2024

@kosmoskey thanks for your answer ! That works ! So it's in the root layout that you can only pass the cookies and it's in the provider that you use cookieToInitialState

@magiziz
Copy link
Contributor

magiziz commented Feb 22, 2024

@smauret Yeah. Maybe there is a better approach, but at least it solves the problem.

@zwergdev
Copy link

@smauret Usually when doing cookieToInitialState it requires some server side action to get the cookies from headers which means it won't be possible if you use 'use-client' which is required in this case.

The one thing you can do is follow the wagmi's cookieToInitialState for config and use that instead.

Just pushed a super simple next app router example with cookieToInitialState here: https://github.com/KosmosKey/rainbowkit-v2-app-router

Thanks, this example helped me

@songkeys
Copy link
Contributor

songkeys commented Mar 1, 2024

What should I do if I want to use the wagmiConfig (derived from the rainbow helper function) on server side?

It looks like the rainbowkit can only import on client side, otherwise error like this will be thrown:

TypeError: (0 , _rainbow_me_rainbowkit__WEBPACK_IMPORTED_MODULE_2__.getDefaultWallets) is not a function

@magiziz
Copy link
Contributor

magiziz commented Mar 1, 2024

@songkeys The same thing will happen if you use createConfig from wagmi on server component, you just need to put 'use-client' at the top of your component wrapper. You can't use rainbow / wagmi config functions in server side.

@songkeys
Copy link
Contributor

songkeys commented Mar 2, 2024

You can't use rainbow / wagmi config functions in server side.

I should be more clear. In my case, I want to use the viem action generated by wagmi cli. Every action needs a wagmiConfig to run in vanilla side.

The same thing will happen if you use createConfig from wagmi on server component

I'm not sure if this is true because I actually made it work - I created another config.server.ts file to write the wagmiConfig again but without rainbowkit related client-end config imported, and use this server config to run with viem actions in server side.

@magiziz
Copy link
Contributor

magiziz commented Mar 2, 2024

@songkeys I see what you mean. I think wagmi has it's own CLI compatibility when it comes to server side rendering which is not supported by RainbowKit yet. Thanks for bringing that up i'll try to investigate more on this and hopefully see what we can do on our end 🙏

@nakedfool
Copy link

Hi @magiziz

I have found an issue related to this implementation https://github.com/magiziz/rainbowkit-v2-app-router

Example is that we have a test route and inside that folder we have page.tsx and test.tsx

If you try to use useAccount inside test.tsx like this

"use client";
import { useAccount } from "wagmi";

const Test = () => {
  const account = useAccount();

  return <div>Account: {account?.address}</div>;
};

export default Test;

It would fail with the following error

WagmiProviderNotFoundError: `useConfig` must be used within `WagmiProvider`.

Docs: https://wagmi.sh/react/api/WagmiProvider.html
Version: [email protected]

@knight174
Copy link

it works, thanks! @magiziz

@arewageek
Copy link

I had same issue in my Next.js application and after long hours of trying to fix it I noticed I left an extra whitespace in the use client flag
I used this: "use client "
Instead of : "use client"

You should probably check that too if you're having a similar issue

@Carlosm99
Copy link

Carlosm99 commented Dec 10, 2024

@smauret Usually when doing cookieToInitialState it requires some server side action to get the cookies from headers which means it won't be possible if you use 'use-client' which is required in this case.

The one thing you can do is follow the wagmi's cookieToInitialState for config and use that instead.

Just pushed a super simple next app router example with cookieToInitialState here: https://github.com/KosmosKey/rainbowkit-v2-app-router

Works like a charm. Many thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests