Skip to content
SwapKit is a powerful suite of tools for building blockchain applications.

Next.js

This guide will help you integrate SwapKit into your Next.js application with proper Node.js polyfills and WebAssembly support.

Install SwapKit and required dependencies:

bun add @swapkit/sdk node-polyfill-webpack-plugin

Additional polyfill dependencies:

bun add buffer crypto-browserify stream-browserify stream-http https-browserify os-browserify path-browserify

Update your next.config.mjs to include necessary polyfills and WebAssembly support:

// @noErrorValidation
import { createRequire } from "module";
import NodePolyfillPlugin from "node-polyfill-webpack-plugin";

const require = createRequire(import.meta.url);

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,

  webpack: (config, { isServer, webpack }) => {
    if (!isServer) {
      // Add polyfills for browser
      config.plugins.push(new NodePolyfillPlugin());

      config.plugins.push(
        new webpack.ProvidePlugin({
          global: require.resolve("global"),
          process: "process/browser",
          Buffer: ["buffer", "Buffer"],
        })
      );

      config.plugins.push(
        new webpack.DefinePlugin({
          "global.crypto": "crypto",
          "global.msCrypto": "crypto",
          "global.process": "process",
          "global.Buffer": "Buffer",
        })
      );

      // Configure fallbacks
      config.resolve.fallback = {
        ...config.resolve.fallback,
        buffer: require.resolve("buffer"),
        crypto: require.resolve("crypto-browserify"),
        fs: false,
        stream: require.resolve("stream-browserify"),
        path: require.resolve("path-browserify"),
        process: require.resolve("process/browser"),
      };

      // Configure aliases
      config.resolve.alias = {
        ...config.resolve.alias,
        crypto: require.resolve("crypto-browserify"),
        path: require.resolve("path-browserify"),
        process: require.resolve("process/browser"),
        stream: require.resolve("stream-browserify"),
        http: require.resolve("stream-http"),
        https: require.resolve("https-browserify"),
        os: require.resolve("os-browserify/browser"),
      };
    }

    // Enable WebAssembly
    config.experiments = {
      ...config.experiments,
      asyncWebAssembly: true,
      syncWebAssembly: true,
      topLevelAwait: true,
    };

    return config;
  },
};

export default nextConfig;

Add browser field to your package.json to handle Node.js modules:

{
  "browser": {
    "dns": false,
    "fs": false,
    "net": false,
    "perf_hooks": false,
    "stream": false,
    "timers": false,
    "tls": false,
    "zlib": false
  }
}

Create a SwapKit instance configuration:

// src/lib/swapKit.ts
import { 
function createSwapKit(config?: Parameters<typeof SwapKit>[0]): {
    chainflip: {
        supportedSwapkitProviders: ProviderName[];
    } & {
        swap: (swapParams: RequestSwapDepositAddressParams) => Promise<...>;
    };
    ... 5 more ...;
    near: {
        ...;
    } & {
        ...;
    };
} & {
    ...;
} & {
    ...;
}
createSwapKit
} from '@swapkit/sdk';
import {
const SKConfig: {
    getState: () => SwapKitConfigStore;
    get: <T extends "wallets" | "apiKeys" | "apis" | "chains" | "explorerUrls" | "nodeUrls" | "rpcUrls" | "envs" | "integrations">(key: T) => SwapKitConfigStore[T];
    ... 6 more ...;
    setIntegrationConfig: <T extends keyof SKConfigIntegrations>(integration: T, config: SKConfigIntegrations[T]) => void;
}
SKConfig
} from '@swapkit/sdk';
// Configure API keys from environment variables if (var process: NodeJS.Processprocess.NodeJS.Process.env: NodeJS.ProcessEnv
The `process.env` property returns an object containing the user environment. See [`environ(7)`](http://man7.org/linux/man-pages/man7/environ.7.html). An example of this object looks like: ```js { TERM: 'xterm-256color', SHELL: '/usr/local/bin/bash', USER: 'maciej', PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', PWD: '/Users/maciej', EDITOR: 'vim', SHLVL: '1', HOME: '/Users/maciej', LOGNAME: 'maciej', _: '/usr/local/bin/node' } ``` It is possible to modify this object, but such modifications will not be reflected outside the Node.js process, or (unless explicitly requested) to other `Worker` threads. In other words, the following example would not work: ```bash node -e 'process.env.foo = "bar"' &#x26;&#x26; echo $foo ``` While the following will: ```js import { env } from 'node:process'; env.foo = 'bar'; console.log(env.foo); ``` Assigning a property on `process.env` will implicitly convert the value to a string. **This behavior is deprecated.** Future versions of Node.js may throw an error when the value is not a string, number, or boolean. ```js import { env } from 'node:process'; env.test = null; console.log(env.test); // => 'null' env.test = undefined; console.log(env.test); // => 'undefined' ``` Use `delete` to delete a property from `process.env`. ```js import { env } from 'node:process'; env.TEST = 1; delete env.TEST; console.log(env.TEST); // => undefined ``` On Windows operating systems, environment variables are case-insensitive. ```js import { env } from 'node:process'; env.TEST = 1; console.log(env.test); // => 1 ``` Unless explicitly specified when creating a `Worker` instance, each `Worker` thread has its own copy of `process.env`, based on its parent thread's `process.env`, or whatever was specified as the `env` option to the `Worker` constructor. Changes to `process.env` will not be visible across `Worker` threads, and only the main thread can make changes that are visible to the operating system or to native add-ons. On Windows, a copy of `process.env` on a `Worker` instance operates in a case-sensitive manner unlike the main thread.
@sincev0.1.27
env
.string | undefinedNEXT_PUBLIC_SWAPKIT_API_KEY) {
const SKConfig: {
    getState: () => SwapKitConfigStore;
    get: <T extends "wallets" | "apiKeys" | "apis" | "chains" | "explorerUrls" | "nodeUrls" | "rpcUrls" | "envs" | "integrations">(key: T) => SwapKitConfigStore[T];
    ... 6 more ...;
    setIntegrationConfig: <T extends keyof SKConfigIntegrations>(integration: T, config: SKConfigIntegrations[T]) => void;
}
SKConfig
.setApiKey: <"swapKit">(key: "swapKit", apiKey: string) => voidsetApiKey('swapKit', var process: NodeJS.Processprocess.NodeJS.Process.env: NodeJS.ProcessEnv
The `process.env` property returns an object containing the user environment. See [`environ(7)`](http://man7.org/linux/man-pages/man7/environ.7.html). An example of this object looks like: ```js { TERM: 'xterm-256color', SHELL: '/usr/local/bin/bash', USER: 'maciej', PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', PWD: '/Users/maciej', EDITOR: 'vim', SHLVL: '1', HOME: '/Users/maciej', LOGNAME: 'maciej', _: '/usr/local/bin/node' } ``` It is possible to modify this object, but such modifications will not be reflected outside the Node.js process, or (unless explicitly requested) to other `Worker` threads. In other words, the following example would not work: ```bash node -e 'process.env.foo = "bar"' &#x26;&#x26; echo $foo ``` While the following will: ```js import { env } from 'node:process'; env.foo = 'bar'; console.log(env.foo); ``` Assigning a property on `process.env` will implicitly convert the value to a string. **This behavior is deprecated.** Future versions of Node.js may throw an error when the value is not a string, number, or boolean. ```js import { env } from 'node:process'; env.test = null; console.log(env.test); // => 'null' env.test = undefined; console.log(env.test); // => 'undefined' ``` Use `delete` to delete a property from `process.env`. ```js import { env } from 'node:process'; env.TEST = 1; delete env.TEST; console.log(env.TEST); // => undefined ``` On Windows operating systems, environment variables are case-insensitive. ```js import { env } from 'node:process'; env.TEST = 1; console.log(env.test); // => 1 ``` Unless explicitly specified when creating a `Worker` instance, each `Worker` thread has its own copy of `process.env`, based on its parent thread's `process.env`, or whatever was specified as the `env` option to the `Worker` constructor. Changes to `process.env` will not be visible across `Worker` threads, and only the main thread can make changes that are visible to the operating system or to native add-ons. On Windows, a copy of `process.env` on a `Worker` instance operates in a case-sensitive manner unlike the main thread.
@sincev0.1.27
env
.stringNEXT_PUBLIC_SWAPKIT_API_KEY);
} if (var process: NodeJS.Processprocess.NodeJS.Process.env: NodeJS.ProcessEnv
The `process.env` property returns an object containing the user environment. See [`environ(7)`](http://man7.org/linux/man-pages/man7/environ.7.html). An example of this object looks like: ```js { TERM: 'xterm-256color', SHELL: '/usr/local/bin/bash', USER: 'maciej', PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', PWD: '/Users/maciej', EDITOR: 'vim', SHLVL: '1', HOME: '/Users/maciej', LOGNAME: 'maciej', _: '/usr/local/bin/node' } ``` It is possible to modify this object, but such modifications will not be reflected outside the Node.js process, or (unless explicitly requested) to other `Worker` threads. In other words, the following example would not work: ```bash node -e 'process.env.foo = "bar"' &#x26;&#x26; echo $foo ``` While the following will: ```js import { env } from 'node:process'; env.foo = 'bar'; console.log(env.foo); ``` Assigning a property on `process.env` will implicitly convert the value to a string. **This behavior is deprecated.** Future versions of Node.js may throw an error when the value is not a string, number, or boolean. ```js import { env } from 'node:process'; env.test = null; console.log(env.test); // => 'null' env.test = undefined; console.log(env.test); // => 'undefined' ``` Use `delete` to delete a property from `process.env`. ```js import { env } from 'node:process'; env.TEST = 1; delete env.TEST; console.log(env.TEST); // => undefined ``` On Windows operating systems, environment variables are case-insensitive. ```js import { env } from 'node:process'; env.TEST = 1; console.log(env.test); // => 1 ``` Unless explicitly specified when creating a `Worker` instance, each `Worker` thread has its own copy of `process.env`, based on its parent thread's `process.env`, or whatever was specified as the `env` option to the `Worker` constructor. Changes to `process.env` will not be visible across `Worker` threads, and only the main thread can make changes that are visible to the operating system or to native add-ons. On Windows, a copy of `process.env` on a `Worker` instance operates in a case-sensitive manner unlike the main thread.
@sincev0.1.27
env
.string | undefinedNEXT_PUBLIC_WALLETCONNECT_PROJECT_ID) {
const SKConfig: {
    getState: () => SwapKitConfigStore;
    get: <T extends "wallets" | "apiKeys" | "apis" | "chains" | "explorerUrls" | "nodeUrls" | "rpcUrls" | "envs" | "integrations">(key: T) => SwapKitConfigStore[T];
    ... 6 more ...;
    setIntegrationConfig: <T extends keyof SKConfigIntegrations>(integration: T, config: SKConfigIntegrations[T]) => void;
}
SKConfig
.setApiKey: <"walletConnectProjectId">(key: "walletConnectProjectId", apiKey: string) => voidsetApiKey('walletConnectProjectId', var process: NodeJS.Processprocess.NodeJS.Process.env: NodeJS.ProcessEnv
The `process.env` property returns an object containing the user environment. See [`environ(7)`](http://man7.org/linux/man-pages/man7/environ.7.html). An example of this object looks like: ```js { TERM: 'xterm-256color', SHELL: '/usr/local/bin/bash', USER: 'maciej', PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', PWD: '/Users/maciej', EDITOR: 'vim', SHLVL: '1', HOME: '/Users/maciej', LOGNAME: 'maciej', _: '/usr/local/bin/node' } ``` It is possible to modify this object, but such modifications will not be reflected outside the Node.js process, or (unless explicitly requested) to other `Worker` threads. In other words, the following example would not work: ```bash node -e 'process.env.foo = "bar"' &#x26;&#x26; echo $foo ``` While the following will: ```js import { env } from 'node:process'; env.foo = 'bar'; console.log(env.foo); ``` Assigning a property on `process.env` will implicitly convert the value to a string. **This behavior is deprecated.** Future versions of Node.js may throw an error when the value is not a string, number, or boolean. ```js import { env } from 'node:process'; env.test = null; console.log(env.test); // => 'null' env.test = undefined; console.log(env.test); // => 'undefined' ``` Use `delete` to delete a property from `process.env`. ```js import { env } from 'node:process'; env.TEST = 1; delete env.TEST; console.log(env.TEST); // => undefined ``` On Windows operating systems, environment variables are case-insensitive. ```js import { env } from 'node:process'; env.TEST = 1; console.log(env.test); // => 1 ``` Unless explicitly specified when creating a `Worker` instance, each `Worker` thread has its own copy of `process.env`, based on its parent thread's `process.env`, or whatever was specified as the `env` option to the `Worker` constructor. Changes to `process.env` will not be visible across `Worker` threads, and only the main thread can make changes that are visible to the operating system or to native add-ons. On Windows, a copy of `process.env` on a `Worker` instance operates in a case-sensitive manner unlike the main thread.
@sincev0.1.27
env
.stringNEXT_PUBLIC_WALLETCONNECT_PROJECT_ID);
} export const
const swapKitClient: {
    chainflip: {
        supportedSwapkitProviders: ProviderName[];
    } & {
        swap: (swapParams: RequestSwapDepositAddressParams) => Promise<...>;
    };
    ... 5 more ...;
    near: {
        ...;
    } & {
        ...;
    };
} & {
    ...;
} & {
    ...;
}
swapKitClient
=
function createSwapKit(config?: Parameters<typeof SwapKit>[0]): {
    chainflip: {
        supportedSwapkitProviders: ProviderName[];
    } & {
        swap: (swapParams: RequestSwapDepositAddressParams) => Promise<...>;
    };
    ... 5 more ...;
    near: {
        ...;
    } & {
        ...;
    };
} & {
    ...;
} & {
    ...;
}
createSwapKit
();

Create a client component for wallet interactions:

// src/components/WalletButton.tsx
'use client';

import { function useState<S>(initialState: S | (() => S)): [S, React.Dispatch<React.SetStateAction<S>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
} from 'react';
import { import swapKitClientswapKitClient } from
Cannot find module '@/lib/swapKit' or its corresponding type declarations.
'@/lib/swapKit'
;
import { enum ChainChain, enum WalletOptionWalletOption } from '@swapkit/sdk'; export function function WalletButton(): React.JSX.ElementWalletButton() { const [const isConnected: booleanisConnected, const setIsConnected: React.Dispatch<React.SetStateAction<boolean>>setIsConnected] = useState<boolean>(initialState: boolean | (() => boolean)): [boolean, React.Dispatch<React.SetStateAction<boolean>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
(false);
const [const address: stringaddress, const setAddress: React.Dispatch<React.SetStateAction<string>>setAddress] = useState<string>(initialState: string | (() => string)): [string, React.Dispatch<React.SetStateAction<string>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
<string>('');
const [const isLoading: booleanisLoading, const setIsLoading: React.Dispatch<React.SetStateAction<boolean>>setIsLoading] = useState<boolean>(initialState: boolean | (() => boolean)): [boolean, React.Dispatch<React.SetStateAction<boolean>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
(false);
const const connectWallet: () => Promise<void>connectWallet = async () => { const setIsLoading: (value: React.SetStateAction<boolean>) => voidsetIsLoading(true); try { await import swapKitClientswapKitClient.connectEVMWallet([enum ChainChain.function (enum member) Chain.Ethereum = "ETH"Ethereum], enum WalletOptionWalletOption.function (enum member) WalletOption.METAMASK = "METAMASK"METAMASK); const setIsConnected: (value: React.SetStateAction<boolean>) => voidsetIsConnected(true); const const ethAddress: anyethAddress = await import swapKitClientswapKitClient.getAddress(enum ChainChain.function (enum member) Chain.Ethereum = "ETH"Ethereum); const setAddress: (value: React.SetStateAction<string>) => voidsetAddress(const ethAddress: anyethAddress); } catch (error) { console.Console.error(message?: any, ...optionalParams: any[]): void (+3 overloads)
Prints to `stderr` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)). ```js const code = 5; console.error('error #%d', code); // Prints: error #5, to stderr console.error('error', code); // Prints: error 5, to stderr ``` If formatting elements (e.g. `%d`) are not found in the first string then [`util.inspect()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilinspectobject-options) is called on each argument and the resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
error
('Failed to connect wallet:', error);
} finally { const setIsLoading: (value: React.SetStateAction<boolean>) => voidsetIsLoading(false); } }; const const disconnectWallet: () => voiddisconnectWallet = () => { import swapKitClientswapKitClient.disconnectWallet(enum ChainChain.function (enum member) Chain.Ethereum = "ETH"Ethereum); const setIsConnected: (value: React.SetStateAction<boolean>) => voidsetIsConnected(false); const setAddress: (value: React.SetStateAction<string>) => voidsetAddress(''); }; if (const isConnected: booleanisConnected) { return ( <
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
div
>
<
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
p
>Connected: {const address: stringaddress.String.slice(start?: number, end?: number): string
Returns a section of a string.
@paramstart The index to the beginning of the specified portion of stringObj.@paramend The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end. If this value is not specified, the substring continues to the end of stringObj.
slice
(0, 6)}...{const address: stringaddress.String.slice(start?: number, end?: number): string
Returns a section of a string.
@paramstart The index to the beginning of the specified portion of stringObj.@paramend The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end. If this value is not specified, the substring continues to the end of stringObj.
slice
(-4)}</p>
<
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
button
onClick={const disconnectWallet: () => voiddisconnectWallet}>Disconnect</button>
</div> ); } return ( <
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
button
onClick={const connectWallet: () => Promise<void>connectWallet} disabled={const isLoading: booleanisLoading}>
{const isLoading: booleanisLoading ? 'Connecting...' : 'Connect Wallet'} </button> ); }

For more complex applications, use a context provider:

// src/providers/SwapKitProvider.tsx
'use client';

import { function createContext<T>(defaultValue: T): React.Context<T>
Lets you create a {@link Context } that components can provide or read.
@paramdefaultValue The value you want the context to have when there is no matching {@link Provider} in the tree above the component reading the context. This is meant as a "last resort" fallback.@see{@link https://react.dev/reference/react/createContext#reference React Docs}@see{@link https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/context/ React TypeScript Cheatsheet}@example```tsx import { createContext } from 'react'; const ThemeContext = createContext('light'); function App() { return ( <ThemeContext value="dark"> <Toolbar /> </ThemeContext> ); } ```
createContext
, function useContext<T>(context: React.Context<T>): T
Accepts a context object (the value returned from `React.createContext`) and returns the current context value, as given by the nearest context provider for the given context.
@version16.8.0@see{@link https://react.dev/reference/react/useContext}
useContext
, type ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<ReactNode> | React.ReactPortal | Promise<...> | null | undefined
Represents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.
@see{@link https://react-typescript-cheatsheet.netlify.app/docs/react-types/reactnode/ React TypeScript Cheatsheet}@example```tsx // Typing children type Props = { children: ReactNode } const Component = ({ children }: Props) => <div>{children}</div> <Component>hello</Component> ```@example```tsx // Typing a custom element type Props = { customElement: ReactNode } const Component = ({ customElement }: Props) => <div>{customElement}</div> <Component customElement={<div>hello</div>} /> ```
ReactNode
} from 'react';
import {
function SwapKit<Plugins extends ReturnType<typeof createPlugin>, Wallets extends ReturnType<typeof createWallet>>({ config, plugins, wallets, }?: {
    config?: SKConfigState;
    plugins?: Plugins;
    wallets?: Wallets;
}): { [key in keyof Plugins]: ReturnType<...>; } & ... 1 more ... & {
    ...;
}
SwapKit
} from '@swapkit/sdk';
import { import swapKitClientswapKitClient } from
Cannot find module '@/lib/swapKit' or its corresponding type declarations.
'@/lib/swapKit'
;
const const SwapKitContext: React.Context<any>SwapKitContext = createContext<any>(defaultValue: any): React.Context<any>
Lets you create a {@link Context } that components can provide or read.
@paramdefaultValue The value you want the context to have when there is no matching {@link Provider} in the tree above the component reading the context. This is meant as a "last resort" fallback.@see{@link https://react.dev/reference/react/createContext#reference React Docs}@see{@link https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/context/ React TypeScript Cheatsheet}@example```tsx import { createContext } from 'react'; const ThemeContext = createContext('light'); function App() { return ( <ThemeContext value="dark"> <Toolbar /> </ThemeContext> ); } ```
createContext
<
'SwapKit' refers to a value, but is being used as a type here. Did you mean 'typeof SwapKit'?
SwapKit
| null>(null);
export function
function SwapKitProvider({ children }: {
    children: ReactNode;
}): React.JSX.Element
SwapKitProvider
({ children: ReactNodechildren }: { children: ReactNodechildren: type ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<ReactNode> | React.ReactPortal | Promise<...> | null | undefined
Represents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.
@see{@link https://react-typescript-cheatsheet.netlify.app/docs/react-types/reactnode/ React TypeScript Cheatsheet}@example```tsx // Typing children type Props = { children: ReactNode } const Component = ({ children }: Props) => <div>{children}</div> <Component>hello</Component> ```@example```tsx // Typing a custom element type Props = { customElement: ReactNode } const Component = ({ customElement }: Props) => <div>{customElement}</div> <Component customElement={<div>hello</div>} /> ```
ReactNode
}) {
return ( <
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
SwapKitContext.Provider
React.ProviderProps<any>.value: anyvalue={import swapKitClientswapKitClient}>
{children: ReactNodechildren} </const SwapKitContext: React.Context<any>SwapKitContext.React.Context<any>.Provider: React.Provider<any>Provider> ); } export function function useSwapKit(): anyuseSwapKit() { const const context: anycontext = useContext<any>(context: React.Context<any>): any
Accepts a context object (the value returned from `React.createContext`) and returns the current context value, as given by the nearest context provider for the given context.
@version16.8.0@see{@link https://react.dev/reference/react/useContext}
useContext
(const SwapKitContext: React.Context<any>SwapKitContext);
if (!const context: anycontext) { throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+2 overloads)
Error
('useSwapKit must be used within SwapKitProvider');
} return const context: anycontext; }

Use in your root layout:

// src/app/layout.tsx
import { import SwapKitProviderSwapKitProvider } from 
Cannot find module '@/providers/SwapKitProvider' or its corresponding type declarations.
'@/providers/SwapKitProvider'
;
export default function
function RootLayout({ children, }: {
    children: React.ReactNode;
}): React.JSX.Element
RootLayout
({
children: React.ReactNodechildren, }: { children: React.ReactNodechildren: export namespace ReactReact.type React.ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<...> | null | undefined
Represents all of the things React can render. Where {@link ReactElement } only represents JSX, `ReactNode` represents everything that can be rendered.
@see{@link https://react-typescript-cheatsheet.netlify.app/docs/react-types/reactnode/ React TypeScript Cheatsheet}@example```tsx // Typing children type Props = { children: ReactNode } const Component = ({ children }: Props) => <div>{children}</div> <Component>hello</Component> ```@example```tsx // Typing a custom element type Props = { customElement: ReactNode } const Component = ({ customElement }: Props) => <div>{customElement}</div> <Component customElement={<div>hello</div>} /> ```
ReactNode
;
}) { return ( <
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
html
lang="en">
<
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
body
>
<
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
SwapKitProvider
>
{children: React.ReactNodechildren} </import SwapKitProviderSwapKitProvider> </body> </html> ); }

Create a .env.local file:

NEXT_PUBLIC_SWAPKIT_API_KEY=your_api_key_here
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here

SwapKit operations that require wallet connections must be performed in client components. For server components, you can only use read-only operations:

// Server component - read-only operations
import { class AssetValueAssetValue, 
const SwapKitApi: {
    mayachainMidgard: {
        getLiquidityPositionRaw: (address: string) => Promise<MemberDetailsMayachain>;
        getNameDetails: (name: string) => Promise<THORNameDetails>;
        getNamesByAddress: (address: string) => Promise<...>;
        getNamesByOwner: (address: string) => Promise<...>;
        getLiquidityPosition: (address: string) => Promise<...>;
    };
    ... 14 more ...;
    getChainflipDepositChannel(body: BrokerDepositChannelParams): Promise<...>;
}
SwapKitApi
} from '@swapkit/sdk';
export async function
function TokenPrice({ symbol }: {
    symbol: string;
}): Promise<React.JSX.Element>
TokenPrice
({ symbol: stringsymbol }: { symbol: stringsymbol: string }) {
const
const price: {
    identifier?: string | undefined;
    provider?: string | undefined;
    timestamp?: number | undefined;
    cg?: {
        id: string;
        market_cap: number;
        name: string;
        price_change_24h_usd: number;
        price_change_percentage_24h_usd: number;
        sparkline_in_7d: number[];
        timestamp: string;
        total_volume: number;
    } | undefined;
    price_usd?: number | undefined;
}[]
price
= await
const SwapKitApi: {
    mayachainMidgard: {
        getLiquidityPositionRaw: (address: string) => Promise<MemberDetailsMayachain>;
        getNameDetails: (name: string) => Promise<THORNameDetails>;
        getNamesByAddress: (address: string) => Promise<...>;
        getNamesByOwner: (address: string) => Promise<...>;
        getLiquidityPosition: (address: string) => Promise<...>;
    };
    ... 14 more ...;
    getChainflipDepositChannel(body: BrokerDepositChannelParams): Promise<...>;
}
SwapKitApi
.
function getPrice(body: PriceRequest): Promise<{
    identifier?: string | undefined;
    provider?: string | undefined;
    timestamp?: number | undefined;
    cg?: {
        id: string;
        market_cap: number;
        ... 5 more ...;
        total_volume: number;
    } | undefined;
    price_usd?: number | undefined;
}[]>
getPrice
({
Object literal may only specify known properties, and 'identifier' does not exist in type '{ tokens: { identifier: string; }[]; metadata: boolean; }'.
identifier
: symbol: stringsymbol,
currency: stringcurrency: 'USD' }); return <
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
div
Property 'price_usd' does not exist on type '{ identifier?: string | undefined; provider?: string | undefined; timestamp?: number | undefined; cg?: { id: string; market_cap: number; name: string; price_change_24h_usd: number; price_change_percentage_24h_usd: number; sparkline_in_7d: number[]; timestamp: string; total_volume: number; } | undefined; price_usd?: ...'.
>Price: ${
const price: {
    identifier?: string | undefined;
    provider?: string | undefined;
    timestamp?: number | undefined;
    cg?: {
        id: string;
        market_cap: number;
        name: string;
        price_change_24h_usd: number;
        price_change_percentage_24h_usd: number;
        sparkline_in_7d: number[];
        timestamp: string;
        total_volume: number;
    } | undefined;
    price_usd?: number | undefined;
}[]
price
.price_usd}</div>;
}

For Cosmos ecosystem wallets like Keplr and Cosmostation, create a specialized component:

// src/components/CosmosWalletButton.tsx
'use client';

import { function useState<S>(initialState: S | (() => S)): [S, React.Dispatch<React.SetStateAction<S>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
} from 'react';
import { import swapKitClientswapKitClient } from
Cannot find module '@/lib/swapKit' or its corresponding type declarations.
'@/lib/swapKit'
;
import { enum ChainChain, enum WalletOptionWalletOption } from '@swapkit/sdk'; export function function CosmosWalletButton(): React.JSX.ElementCosmosWalletButton() { const [const isConnected: booleanisConnected, const setIsConnected: React.Dispatch<React.SetStateAction<boolean>>setIsConnected] = useState<boolean>(initialState: boolean | (() => boolean)): [boolean, React.Dispatch<React.SetStateAction<boolean>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
(false);
const [const addresses: Record<string, string>addresses, const setAddresses: React.Dispatch<React.SetStateAction<Record<string, string>>>setAddresses] = useState<Record<string, string>>(initialState: Record<string, string> | (() => Record<string, string>)): [Record<string, string>, React.Dispatch<React.SetStateAction<Record<string, string>>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
<type Record<K extends keyof any, T> = { [P in K]: T; }
Construct a type with a set of properties K of type T
Record
<string, string>>({});
const [const isLoading: booleanisLoading, const setIsLoading: React.Dispatch<React.SetStateAction<boolean>>setIsLoading] = useState<boolean>(initialState: boolean | (() => boolean)): [boolean, React.Dispatch<React.SetStateAction<boolean>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
(false);
const const connectCosmostation: () => Promise<void>connectCosmostation = async () => { const setIsLoading: (value: React.SetStateAction<boolean>) => voidsetIsLoading(true); try { await import swapKitClientswapKitClient.connectCosmostation([enum ChainChain.function (enum member) Chain.Cosmos = "GAIA"Cosmos, enum ChainChain.function (enum member) Chain.THORChain = "THOR"THORChain, enum ChainChain.function (enum member) Chain.Kujira = "KUJI"Kujira]); const setIsConnected: (value: React.SetStateAction<boolean>) => voidsetIsConnected(true); const const chains: Chain[]chains = [enum ChainChain.function (enum member) Chain.Cosmos = "GAIA"Cosmos, enum ChainChain.function (enum member) Chain.THORChain = "THOR"THORChain, enum ChainChain.function (enum member) Chain.Kujira = "KUJI"Kujira]; const const newAddresses: Record<string, string>newAddresses: type Record<K extends keyof any, T> = { [P in K]: T; }
Construct a type with a set of properties K of type T
Record
<string, string> = {};
for (const const chain: Chainchain of const chains: Chain[]chains) { try { const const address: anyaddress = await import swapKitClientswapKitClient.getAddress(const chain: Chainchain); if (const address: anyaddress) { const newAddresses: Record<string, string>newAddresses[const chain: Chainchain] = const address: anyaddress; } } catch { // Chain might not be connected, skip it } } const setAddresses: (value: React.SetStateAction<Record<string, string>>) => voidsetAddresses(const newAddresses: Record<string, string>newAddresses); } catch (error) { console.Console.error(message?: any, ...optionalParams: any[]): void (+3 overloads)
Prints to `stderr` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)). ```js const code = 5; console.error('error #%d', code); // Prints: error #5, to stderr console.error('error', code); // Prints: error 5, to stderr ``` If formatting elements (e.g. `%d`) are not found in the first string then [`util.inspect()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilinspectobject-options) is called on each argument and the resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
error
('Failed to connect Cosmostation:', error);
} finally { const setIsLoading: (value: React.SetStateAction<boolean>) => voidsetIsLoading(false); } }; const const disconnectWallet: () => voiddisconnectWallet = () => { var Object: ObjectConstructor
Provides functionality common to all JavaScript objects.
Object
.ObjectConstructor.keys(o: {}): string[] (+1 overload)
Returns the names of the enumerable string properties and methods of an object.
@paramo Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
keys
(const addresses: Record<string, string>addresses).Array<string>.forEach(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void
Performs the specified action for each element in an array.
@paramcallbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
forEach
(chain: stringchain => {
import swapKitClientswapKitClient.disconnectWallet(chain: stringchain as enum ChainChain); }); const setIsConnected: (value: React.SetStateAction<boolean>) => voidsetIsConnected(false); const setAddresses: (value: React.SetStateAction<Record<string, string>>) => voidsetAddresses({}); }; if (const isConnected: booleanisConnected) { return ( <
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
div
className="space-y-2">
<
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
h3
>Connected Cosmos Chains:</h3>
{var Object: ObjectConstructor
Provides functionality common to all JavaScript objects.
Object
.
ObjectConstructor.entries<string>(o: {
    [s: string]: string;
} | ArrayLike<string>): [string, string][] (+1 overload)
Returns an array of key/values of the enumerable own properties of an object
@paramo Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
entries
(const addresses: Record<string, string>addresses).Array<[string, string]>.map<React.JSX.Element>(callbackfn: (value: [string, string], index: number, array: [string, string][]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
(([chain: stringchain, address: stringaddress]) => (
<
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
p
React.Attributes.key?: React.Key | null | undefinedkey={chain: stringchain}>
{chain: stringchain}: {address: stringaddress.String.slice(start?: number, end?: number): string
Returns a section of a string.
@paramstart The index to the beginning of the specified portion of stringObj.@paramend The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end. If this value is not specified, the substring continues to the end of stringObj.
slice
(0, 8)}...{address: stringaddress.String.slice(start?: number, end?: number): string
Returns a section of a string.
@paramstart The index to the beginning of the specified portion of stringObj.@paramend The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end. If this value is not specified, the substring continues to the end of stringObj.
slice
(-6)}
</p> ))} <
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
button
onClick={const disconnectWallet: () => voiddisconnectWallet}>Disconnect</button>
</div> ); } return ( <
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.
button
onClick={const connectCosmostation: () => Promise<void>connectCosmostation} disabled={const isLoading: booleanisLoading}>
{const isLoading: booleanisLoading ? 'Connecting...' : 'Connect Cosmostation'} </button> ); }

The webpack configuration should handle WebAssembly modules. If issues persist, check that experiments.asyncWebAssembly is enabled in your next.config.js.

For a complete working example, check out the Next.js playground in the SwapKit repository.