Next.js
This guide will help you integrate SwapKit into your Next.js application with proper Node.js polyfills and WebAssembly support.
Installation
Section titled “Installation”Install SwapKit and required dependencies:
bun add @swapkit/sdk node-polyfill-webpack-plugin
pnpm add @swapkit/sdk node-polyfill-webpack-plugin
npm install @swapkit/sdk node-polyfill-webpack-plugin
yarn 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
pnpm add buffer crypto-browserify stream-browserify stream-http https-browserify os-browserify path-browserify
npm install buffer crypto-browserify stream-browserify stream-http https-browserify os-browserify path-browserify
yarn add buffer crypto-browserify stream-browserify stream-http https-browserify os-browserify path-browserify
Next.js Configuration
Section titled “Next.js Configuration”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;
Package.json Browser Field
Section titled “Package.json Browser Field”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
}
}
SwapKit Setup
Section titled “SwapKit Setup”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.Process
process.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"' && 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.env.string | undefined
NEXT_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) => void
setApiKey('swapKit', var process: NodeJS.Process
process.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"' && 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.env.string
NEXT_PUBLIC_SWAPKIT_API_KEY);
}
if (var process: NodeJS.Process
process.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"' && 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.env.string | undefined
NEXT_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) => void
setApiKey('walletConnectProjectId', var process: NodeJS.Process
process.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"' && 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.env.string
NEXT_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();
React Component with App Router
Section titled “React Component with App Router”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.useState } from 'react';
import { import swapKitClient
swapKitClient } from Cannot find module '@/lib/swapKit' or its corresponding type declarations.'@/lib/swapKit';
import { enum Chain
Chain, enum WalletOption
WalletOption } from '@swapkit/sdk';
export function function WalletButton(): React.JSX.Element
WalletButton() {
const [const isConnected: boolean
isConnected, 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.useState(false);
const [const address: string
address, 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.useState<string>('');
const [const isLoading: boolean
isLoading, 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.useState(false);
const const connectWallet: () => Promise<void>
connectWallet = async () => {
const setIsLoading: (value: React.SetStateAction<boolean>) => void
setIsLoading(true);
try {
await import swapKitClient
swapKitClient.connectEVMWallet([enum Chain
Chain.function (enum member) Chain.Ethereum = "ETH"
Ethereum], enum WalletOption
WalletOption.function (enum member) WalletOption.METAMASK = "METAMASK"
METAMASK);
const setIsConnected: (value: React.SetStateAction<boolean>) => void
setIsConnected(true);
const const ethAddress: any
ethAddress = await import swapKitClient
swapKitClient.getAddress(enum Chain
Chain.function (enum member) Chain.Ethereum = "ETH"
Ethereum);
const setAddress: (value: React.SetStateAction<string>) => void
setAddress(const ethAddress: any
ethAddress);
} 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.error('Failed to connect wallet:', error);
} finally {
const setIsLoading: (value: React.SetStateAction<boolean>) => void
setIsLoading(false);
}
};
const const disconnectWallet: () => void
disconnectWallet = () => {
import swapKitClient
swapKitClient.disconnectWallet(enum Chain
Chain.function (enum member) Chain.Ethereum = "ETH"
Ethereum);
const setIsConnected: (value: React.SetStateAction<boolean>) => void
setIsConnected(false);
const setAddress: (value: React.SetStateAction<string>) => void
setAddress('');
};
if (const isConnected: boolean
isConnected) {
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: string
address.String.slice(start?: number, end?: number): string
Returns a section of a string.slice(0, 6)}...{const address: string
address.String.slice(start?: number, end?: number): string
Returns a section of a string.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: () => void
disconnectWallet}>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: boolean
isLoading}>
{const isLoading: boolean
isLoading ? 'Connecting...' : 'Connect Wallet'}
</button>
);
}
Context Provider Pattern
Section titled “Context Provider Pattern”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.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.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.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 swapKitClient
swapKitClient } 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.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: ReactNode
children }: { children: ReactNode
children: 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.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: any
value={import swapKitClient
swapKitClient}>
{children: ReactNode
children}
</const SwapKitContext: React.Context<any>
SwapKitContext.React.Context<any>.Provider: React.Provider<any>
Provider>
);
}
export function function useSwapKit(): any
useSwapKit() {
const const context: any
context = 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.useContext(const SwapKitContext: React.Context<any>
SwapKitContext);
if (!const context: any
context) {
throw new var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+2 overloads)
Error('useSwapKit must be used within SwapKitProvider');
}
return const context: any
context;
}
Use in your root layout:
// src/app/layout.tsx
import { import SwapKitProvider
SwapKitProvider } 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.ReactNode
children,
}: {
children: React.ReactNode
children: export namespace React
React.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.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.ReactNode
children}
</import SwapKitProvider
SwapKitProvider>
</body>
</html>
);
}
Environment Variables
Section titled “Environment Variables”Create a .env.local
file:
NEXT_PUBLIC_SWAPKIT_API_KEY=your_api_key_here
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here
Server Components Considerations
Section titled “Server Components Considerations”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 AssetValue
AssetValue, 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: string
symbol }: { symbol: string
symbol: 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: string
symbol,
currency: string
currency: 'USD'
});
return <'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.divProperty '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>;
}
Cosmos Wallets Integration
Section titled “Cosmos Wallets Integration”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.useState } from 'react';
import { import swapKitClient
swapKitClient } from Cannot find module '@/lib/swapKit' or its corresponding type declarations.'@/lib/swapKit';
import { enum Chain
Chain, enum WalletOption
WalletOption } from '@swapkit/sdk';
export function function CosmosWalletButton(): React.JSX.Element
CosmosWalletButton() {
const [const isConnected: boolean
isConnected, 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.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.useState<type Record<K extends keyof any, T> = { [P in K]: T; }
Construct a type with a set of properties K of type TRecord<string, string>>({});
const [const isLoading: boolean
isLoading, 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.useState(false);
const const connectCosmostation: () => Promise<void>
connectCosmostation = async () => {
const setIsLoading: (value: React.SetStateAction<boolean>) => void
setIsLoading(true);
try {
await import swapKitClient
swapKitClient.connectCosmostation([enum Chain
Chain.function (enum member) Chain.Cosmos = "GAIA"
Cosmos, enum Chain
Chain.function (enum member) Chain.THORChain = "THOR"
THORChain, enum Chain
Chain.function (enum member) Chain.Kujira = "KUJI"
Kujira]);
const setIsConnected: (value: React.SetStateAction<boolean>) => void
setIsConnected(true);
const const chains: Chain[]
chains = [enum Chain
Chain.function (enum member) Chain.Cosmos = "GAIA"
Cosmos, enum Chain
Chain.function (enum member) Chain.THORChain = "THOR"
THORChain, enum Chain
Chain.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 TRecord<string, string> = {};
for (const const chain: Chain
chain of const chains: Chain[]
chains) {
try {
const const address: any
address = await import swapKitClient
swapKitClient.getAddress(const chain: Chain
chain);
if (const address: any
address) {
const newAddresses: Record<string, string>
newAddresses[const chain: Chain
chain] = const address: any
address;
}
} catch {
// Chain might not be connected, skip it
}
}
const setAddresses: (value: React.SetStateAction<Record<string, string>>) => void
setAddresses(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.error('Failed to connect Cosmostation:', error);
} finally {
const setIsLoading: (value: React.SetStateAction<boolean>) => void
setIsLoading(false);
}
};
const const disconnectWallet: () => void
disconnectWallet = () => {
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.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.forEach(chain: string
chain => {
import swapKitClient
swapKitClient.disconnectWallet(chain: string
chain as enum Chain
Chain);
});
const setIsConnected: (value: React.SetStateAction<boolean>) => void
setIsConnected(false);
const setAddresses: (value: React.SetStateAction<Record<string, string>>) => void
setAddresses({});
};
if (const isConnected: boolean
isConnected) {
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 objectentries(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.map(([chain: string
chain, address: string
address]) => (
<'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 | undefined
key={chain: string
chain}>
{chain: string
chain}: {address: string
address.String.slice(start?: number, end?: number): string
Returns a section of a string.slice(0, 8)}...{address: string
address.String.slice(start?: number, end?: number): string
Returns a section of a string.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: () => void
disconnectWallet}>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: boolean
isLoading}>
{const isLoading: boolean
isLoading ? 'Connecting...' : 'Connect Cosmostation'}
</button>
);
}
Common Issues
Section titled “Common Issues”WebAssembly errors
Section titled “WebAssembly errors”The webpack configuration should handle WebAssembly modules. If issues persist, check that experiments.asyncWebAssembly
is enabled in your next.config.js
.
Example Repository
Section titled “Example Repository”For a complete working example, check out the Next.js playground in the SwapKit repository.