Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@rainbow-me/rainbowkit

Package Overview
Dependencies
Maintainers
9
Versions
126
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@rainbow-me/rainbowkit

The best way to connect a wallet

  • 0.0.2
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
50K
decreased by-26.94%
Maintainers
9
Weekly downloads
 
Created
Source

RainbowKit

The best way to connect a wallet 🌈

⚠️ Please note

RainbowKit is currently v0.0.x and has a peer dependency on wagmi which is currently v0.x. The APIs are not stable and likely to change in the near future. At this stage we’re looking for early adopters to provide feedback and help us improve the library.

Features

  • 🔥 Out-of-the-box wallet management
  • 👟 Easily customizable
  • 🕊 Lightweight
  • ✅ Accessible
  • 🦄 Built on top of wagmi and ethers

Installation

Install RainbowKit along with wagmi and its ethers peer dependency.

npm install @rainbow-me/rainbowkit wagmi ethers

Getting started

To start, import RainbowKit’s base styles, configure your wallets and desired chains, generate the required connectors, then wrap your application with RainbowKitProvider and WagmiProvider.

import '@rainbow-me/rainbowkit/styles.css';

import {
  RainbowKitProvider,
  Chain,
  getDefaultWallets,
  connectorsForWallets,
} from '@rainbow-me/rainbowkit';
import { WagmiProvider, chain } from 'wagmi';
import { providers } from 'ethers';

const infuraId = process.env.INFURA_ID;

const provider = ({ chainId }: { chainId?: number }) =>
  new providers.InfuraProvider(chainId, infuraId);

const chains: Chain[] = [
  { ...chain.mainnet, name: 'Ethereum' },
  { ...chain.polygonMainnet, name: 'Polygon' },
  { ...chain.optimism, name: 'Optimism' },
  { ...chain.arbitrumOne, name: 'Arbitrum' },
];

const wallets = getDefaultWallets({
  chains,
  infuraId,
  appName: 'My RainbowKit App',
  jsonRpcUrl: ({ chainId }) =>
    chains.find(x => x.id === chainId)?.rpcUrls?.[0] ??
    chain.mainnet.rpcUrls[0],
});

const connectors = connectorsForWallets(wallets);

const App = () => {
  return (
    <RainbowKitProvider chains={chains}>
      <WagmiProvider autoConnect connectors={connectors} provider={provider}>
        <YourApp />
      </WagmiProvider>
    </RainbowKitProvider>
  );
};

Then, in your app, import RainbowKit’s ConnectButton component.

import { ConnectButton } from '@rainbow-me/rainbowkit';

export const YourApp = () => {
  return (
    <>
      <ConnectButton />
    </>
  );
};

You’re done! RainbowKit will now handle your user’s wallet selection, display wallet/transaction information and handle network/wallet switching.

Customizing ConnectButton

The ConnectButton component exposes several props to customize its appearance by toggling the visibility of different elements.

These props can also be defined in a responsive format, e.g. showBalance={{ smallScreen: false, largeScreen: true }}, allowing you to customize its appearance across different screen sizes. Note that the built-in "largeScreen" breakpoint is 768px.

PropTypeDefaultDescription
accountStatus"avatar" | "address" | "full" | { smallScreen: AccountStatus, largeScreen?: AccountStatus }"full"Whether the active account’s avatar and/or address is displayed
chainStatus"icon" | "name" | "full" | "none" | { smallScreen: ChainStatus, largeScreen?: ChainStatus }{ smallScreen: "icon", largeScreen: "full" }Whether the current chain’s icon and/or name is displayed, or hidden entirely
showBalanceboolean | { smallScreen: boolean, largeScreen?: boolean }{ smallScreen: false, largeScreen: true }Whether the balance is visible next to the account name

Choosing a theme

RainbowKit ships with a static CSS file that can be themed via CSS variables, which RainbowKitProvider provides as inline styles by default.

Built-in themes

There are 3 built-in themes:

  • lightTheme (default)
  • darkTheme
  • midnightTheme

These themes are implemented as functions where the resulting theme object can be passed to the theme prop on RainbowKitProvider.

import { RainbowKitProvider, darkTheme } from '@rainbow-me/rainbowkit';

const App = () => {
  return (
    <RainbowKitProvider theme={darkTheme()} {...etc}>
      {/* ... */}
    </RainbowKitProvider>
  );
};
Customizing the built-in themes

The built-in theme functions also accept an options object, allowing you to select from several different visual styles.

OptionTypeDefaultDescription
accentColor"blue" | "green" | "orange" | "pink" | "purple" | "red" | "yellow""blue"The background/text color of various interactive elements
borderRadius"none" | "small" | "medium" | "large""large"The size of the entire border radius scale
fontStack"rounded" | "system""rounded"The font stack used throughout the UI. Note that ‘rounded’ attempts to use SF Pro Rounded, falling back to system fonts when it isn’t available.

For example, to customize the dark theme with a purple accent color and a medium border radius scale:

import { RainbowKitProvider, darkTheme } from '@rainbow-me/rainbowkit';

const App = () => {
  return (
    <RainbowKitProvider
      theme={darkTheme({
        accentColor: 'purple',
        borderRadius: 'medium',
      })}
      {...etc}
    >
      {/* ... */}
    </RainbowKitProvider>
  );
};
Dark mode support

If your app uses the standard prefers-color-mode: dark media query to swap between light and dark modes, you can optionally provide a dynamic theme object containing lightMode and darkMode values.

import {
  RainbowKitProvider,
  lightTheme,
  darkTheme,
} from '@rainbow-me/rainbowkit';

const App = () => {
  return (
    <RainbowKitProvider
      theme={{
        lightMode: lightTheme(),
        darkMode: darkTheme(),
      }}
      {...etc}
    >
      {/* ... */}
    </RainbowKitProvider>
  );
};

Customizing chains

The chains prop on RainbowKitProvider defines which chains are available for the user to select.

Your chain config can be defined in a single array using RainbowKit’s Chain type, which is a combination of wagmi’s Chain type and the chain metadata used by RainbowKit.

import { RainbowKitProvider, Chain } from '@rainbow-me/rainbowkit';
import { chain } from 'wagmi';

const chains: Chain[] = [
  { ...chain.mainnet, name: 'Ethereum' },
  { ...chain.polygonMainnet, name: 'Polygon' },
];

const App = () => {
  return (
    <RainbowKitProvider chains={chains} {...etc}>
      {/* ... */}
    </RainbowKitProvider>
  );
};

Several chain icons are provided by default, but you can customize the icon for each chain using the iconUrl property.

const chains: Chain[] = [
  {
    ...chain.mainnet,
    name: 'Ethereum',
    iconUrl: 'https://example.com/icons/ethereum.png',
  },
  {
    ...chain.polygonMainnet,
    name: 'Polygon',
    iconUrl: 'https://example.com/icons/polygon.png',
  },
];

Advanced usage

Creating a custom ConnectButton

If you want to create your own custom connection buttons, the low-level ConnectButton.Custom component is also provided which accepts a render prop, i.e. a function as a child. This function is passed everything needed to re-implement the built-in buttons.

A minimal re-implementation of the built-in buttons would look something like this:

import { ConnectButton } from '@rainbow-me/rainbowkit';

export const YourApp = () => {
  return (
    <>
      <ConnectButton.Custom>
        {({
          account,
          chain,
          openAccountModal,
          openChainModal,
          openConnectModal,
        }) =>
          !account ? (
            <button onClick={openConnectModal} type="button">
              Connect Wallet
            </button>
          ) : (
            <div style={{ display: 'flex', gap: 12 }}>
              {chain && (
                <button
                  onClick={openChainModal}
                  style={{ display: 'flex', alignItems: 'center' }}
                  type="button"
                >
                  {chain.iconUrl && (
                    <img
                      alt={chain.name ?? 'Chain icon'}
                      src={chain.iconUrl}
                      style={{ width: 12, height: 12, marginRight: 4 }}
                    />
                  )}
                  {chain.name ?? chain.id}
                  {chain.unsupported && ' (unsupported)'}
                </button>
              )}
              <button onClick={openAccountModal} type="button">
                {account.displayName}
                {account.displayBalance ? ` (${account.displayBalance})` : ''}
              </button>
            </div>
          )
        }
      </ConnectButton.Custom>
    </>
  );
};

The following props are passed to your render function.

Account properties
PropertyTypeDescription
accountobject | undefinedObject containing details about the current account, described below
account.addressstringThe full account address, e.g. "0x7a3d05c70581bD345fe117c06e45f9669205384f"
account.balanceDecimalsnumber | undefinedThe account balance in decimals
account.balanceFormattedstring | undefinedThe account balance formatted as a string, e.g. "1.234567890123456789"
account.balanceSymbolstring | undefinedThe currency symbol for the balance, e.g. "ETH"
account.displayBalancestring | undefinedThe balance formatted to 3 significant digits, plus the symbol, e.g. "1.23 ETH"
account.displayNamestringThe ENS name, or a truncated version of the address, e.g. "rainbowwallet.eth" or "0x7a3d...384f"
account.ensAvatarstring | undefinedThe ENS avatar URI
account.ensNamestring | undefinedThe ENS name, e.g. "rainbowwallet.eth"
Chain properties
PropertyTypeDescription
chainobject | undefinedObject containing details about the current chain, described below
chain.iconUrlstring | undefinedThe chain icon URL
chain.idnumberThe chain ID, e.g. 1
chain.namestring | undefinedThe chain name, e.g. "Ethereum"
chain.unsupportedboolean | undefinedBoolean indicating whether the current chain is unsupported
Modal state properties
PropertyTypeDescription
openAccountModal() => voidFunction to open the account modal
openChainModal() => voidFunction to open the chain modal
openConnectModal() => voidFunction to open the connect modal
accountModalOpenbooleanBoolean indicating whether the account modal is open
chainModalOpenbooleanBoolean indicating whether the chain modal is open
connectModalOpenbooleanBoolean indicating whether the connect modal is open

Creating custom themes

⚠️ Note: This API is unstable and likely to change in the near future. We recommend sticking with the built-in themes for now.

While the built-in themes provide some level of customization, the Theme type is provided to help you define your own custom themes with lower-level access to the underlying theme variables.

import { RainbowKitProvider, Theme } from '@rainbow-me/rainbowkit';

const myCustomTheme: Theme = {
  borders: {
    modalBorderWidth: '...',
  },
  colors: {
    accentColor: '...',
    actionButtonBorder: '...',
    actionButtonBorderMobile: '...',
    actionButtonSecondaryBackground: '...',
    actionButtonText: '...',
    closeButton: '...',
    closeButtonBackground: '...',
    connectButtonBackground: '...',
    connectButtonBackgroundError: '...',
    connectButtonInnerBackground: '...',
    connectButtonText: '...',
    connectButtonTextError: '...',
    connectionIndicator: '...',
    error: '...',
    generalBorder: '...',
    menuItemBackground: '...',
    modalBackdrop: '...',
    modalBackground: '...',
    modalBorder: '...',
    modalText: '...',
    modalTextDim: '...',
    modalTextSecondary: '...',
    profileAction: '...',
    profileActionHover: '...',
    profileForeground: '...',
    selectedOptionBorder: '...',
    standby: '',
  },
  fonts: {
    body: '...',
  },
  radii: {
    actionButton: '...',
    connectButton: '...',
    menuButton: '...',
    modal: '...',
    modalMobile: '...',
  },
  shadows: {
    connectButton: '...',
    dialog: '...',
    profileDetailsAction: '...',
    selectedOption: '...',
    selectedWallet: '...',
  },
};

const App = () => {
  return (
    <RainbowKitProvider theme={myCustomTheme} {...etc}>
      {/* ... */}
    </RainbowKitProvider>
  );
};

Creating custom theme selectors

If your app is server/statically rendered and allows users to manually toggle between themes, RainbowKit’s theming system can be hooked up to custom CSS selectors with the following functions that can be used with any CSS-in-JS system:

  • cssStringFromTheme
  • cssObjectFromTheme

These functions return CSS that sets all required theme variables. Since both strings and objects are supported, this can be integrated with any CSS-in-JS system.

As a basic example, you can render your own style element with custom selectors for each theme. Since we’re taking control of rendering the theme’s CSS, we’re passing null to the theme prop so that RainbowKitProvider doesn’t render any styles for us. Also note the use of the extends option on the cssStringFromTheme function which omits any theme variables that are the same as the base theme.

import {
  RainbowKitProvider,
  cssStringFromTheme,
  lightTheme,
  darkTheme,
} from '@rainbow-me/rainbowkit';

const App = () => {
  return (
    <RainbowKitProvider theme={null} {...etc}>
      <style>
        {`
          :root {
            ${cssStringFromTheme(lightTheme)}
          }

          html[data-dark] {
            ${cssStringFromTheme(darkTheme, {
              extends: lightTheme,
            })}
          }
        `}
      </style>

      {/* ... */}
    </RainbowKitProvider>
  );
};

Customizing the wallet list

⚠️ Note: This API is unstable and likely to change in the near future. We recommend avoiding changes to the wallet list for now.

The following wallet options are presented by default via the getDefaultWallets function:

  • Rainbow
  • WalletConnect
  • Coinbase Wallet
  • MetaMask

An "Injected Wallet" fallback is also provided if window.ethereum exists and hasn’t been provided by another wallet.

All built-in wallets are available via the wallet object which allows you to rearrange/omit wallets as needed.

import { wallet, WalletList } from '@rainbow-me/rainbowkit';

const needsInjectedWalletFallback =
  typeof window !== 'undefined' &&
  window.ethereum &&
  !window.ethereum.isMetaMask &&
  !window.ethereum.isCoinbaseWallet;

const wallets: WalletList = [
  {
    groupName: 'Suggested',
    wallets: [
      wallet.rainbow({ chains, infuraId }),
      wallet.walletConnect({ chains, infuraId }),
      wallet.coinbase({
        chains,
        appName: 'My RainbowKit App',
        jsonRpcUrl: ({ chainId }) =>
          chains.find(x => x.id === chainId)?.rpcUrls?.[0] ??
          chain.mainnet.rpcUrls[0],
      }),
      wallet.metaMask({ chains, infuraId }),
      ...(needsInjectedWalletFallback
        ? [wallet.injected({ chains, infuraId })]
        : []),
    ],
  },
];

Creating custom wallets

⚠️ Note: This API is unstable and likely to change in the near future. We will be adding more built-in wallets over time, so let us know if there are any particular wallets you’re interested in.

The Wallet type is provided to help you define your own custom wallets. If you’d like to see some working examples, you can view the source code for the built-in wallets.

Wallet properties
PropertyTypeDescription
idstringUnique ID per wallet
namestringHuman-readable wallet name
shortNamestring | undefinedOptional short name for mobile use
iconUrlstringURL for wallet icon
installedboolean | undefinedWhether the wallet is known to be installed, or undefined if indeterminate
downloadUrls{ android?: string, ios?: string, browserExtension?: string, qrCode?: string } | undefinedObject containing download URLs
createConnector(connectorArgs: { chainId? number }) => RainbowKitConnectorFunction for providing the connector instance and configuration for different connection methods, described below
RainbowKitConnector properties

The following properties are defined on the return value of the createConnector function.

PropertyTypeDescription
connectorConnectorInstance of a wagmi connector
mobile{ getUri?: () => string } | undefinedFunction for resolving a mobile wallet connection URI
qrCode{ getUri: () => string, iconUrl?: string, instructions?: { learnMoreUrl: string, steps: Array<{ step: 'install' | 'create' | 'scan', title: string, description: string }> }}} | undefinedObject containing a function for resolving the QR code URI, plus optional setup instructions an an icon URL if different from the wallet icon

By default, the introductory “Learn more” link within the “What is a wallet?” section points to https://learn.rainbow.me/what-is-a-cryptoweb3-wallet-actually, but you can override this via the learnMoreUrl prop on RainbowKitProvider.

import { RainbowKitProvider } from '@rainbow-me/rainbowkit';

const App = () => {
  return (
    <RainbowKitProvider
      learnMoreUrl="https://learn.rainbow.me/what-is-a-cryptoweb3-wallet-actually"
      {...etc}
    >
      {/* ... */}
    </RainbowKitProvider>
  );
};

License

MIT.

Keywords

FAQs

Package last updated on 31 Mar 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc