Back to Widget V2

Integration Examples

This guide provides step-by-step instructions for integrating OpenOcean Widget into different frameworks and setups.

OpenOcean Widget Integration Guide

Table of Contents


Vite + React

Installation

Terminal
SH
1
npm install @openocean.finance/widget @openocean.finance/wallet-management
2
npm install @tanstack/react-query wagmi viem
3
npm install --save-dev vite-plugin-node-polyfills

Configuration

vite.config.ts

Terminal
TS
1
import { defineConfig } from 'vite'
2
import react from '@vitejs/plugin-react'
3
import { nodePolyfills } from 'vite-plugin-node-polyfills'
4
5
export default defineConfig({
6
plugins: [
7
react(),
8
nodePolyfills({
9
include: ['buffer', 'process'],
10
}),
11
],
12
})

Usage

src/App.tsx

Terminal
TSX
1
import { OpenOceanWidget } from '@openocean.finance/widget'
2
3
export function App() {
4
return (
5
<OpenOceanWidget
6
integrator="vite-example"
7
config={{
8
buildUrl: false,
9
subvariant: 'split',
10
theme: {
11
container: {
12
border: '1px solid rgb(234, 234, 234)',
13
borderRadius: '16px',
14
},
15
},
16
}}
17
/>
18
)
19
}

Key Points

  • Requires vite-plugin-node-polyfills for Node.js polyfills
  • Basic React integration without wallet management
  • Can be extended with wallet providers

Next.js (App Router)

Installation

Terminal
SH
1
npm install @openocean.finance/widget @openocean.finance/widget-sdk
2
npm install @mui/material-nextjs

Configuration

next.config.js

Terminal
JS
1
/** @type {import('next').NextConfig} */
2
const nextConfig = {
3
transpilePackages: ['@openocean.finance/widget'],
4
}
5
6
module.exports = nextConfig

Usage

app/page.tsx

Terminal
TSX
1
import { Widget } from '@/components/Widget'
2
3
export default function Home() {
4
return (
5
<main>
6
<Widget />
7
</main>
8
)
9
}

components/Widget.tsx

Terminal
TSX
1
'use client'
2
3
import type { WidgetConfig } from '@openocean.finance/widget'
4
import { OpenOceanWidget, WidgetSkeleton } from '@openocean.finance/widget'
5
import { ClientOnly } from './ClientOnly'
6
7
export function Widget() {
8
const config = {
9
appearance: 'light',
10
theme: {
11
container: {
12
border: '1px solid rgb(234, 234, 234)',
13
borderRadius: '16px',
14
},
15
},
16
} as Partial<WidgetConfig>
17
18
return (
19
<ClientOnly fallback={<WidgetSkeleton config={config} />}>
20
<OpenOceanWidget config={config} integrator="nextjs-example" />
21
</ClientOnly>
22
)
23
}

components/ClientOnly.tsx

Terminal
TSX
1
'use client'
2
3
import { useEffect, useState } from 'react'
4
5
export function ClientOnly({ children, fallback = null }) {
6
const [hasMounted, setHasMounted] = useState(false)
7
8
useEffect(() => {
9
setHasMounted(true)
10
}, [])
11
12
if (!hasMounted) {
13
return fallback
14
}
15
16
return children
17
}

Key Points

  • Use 'use client' directive for client components
  • Implement ClientOnly wrapper to prevent SSR issues
  • Use WidgetSkeleton as fallback during SSR
  • Configure transpilePackages in next.config.js

Next.js (Pages Router)

Installation

Same as Next.js App Router.

Usage

pages/index.tsx

Terminal
TSX
1
import { Widget } from '@/components/Widget'
2
3
export default function Home() {
4
return (
5
<main>
6
<Widget />
7
</main>
8
)
9
}

components/Widget.tsx

Same implementation as App Router, but without 'use client' directive (not needed in Pages Router).

Key Points

  • Similar to App Router but uses pages/ directory
  • No need for 'use client' directive
  • Still requires ClientOnly wrapper for SSR safety

Vue 3

Installation

Terminal
SH
1
npm install @openocean.finance/widget veaury\nnpm install --save-dev @vitejs/plugin-react @vitejs/plugin-vue

Configuration

vite.config.ts

Terminal
TS
1
import { defineConfig } from 'vite'
2
import vue from '@vitejs/plugin-vue'
3
import react from '@vitejs/plugin-react'
4
import { nodePolyfills } from 'vite-plugin-node-polyfills'
5
6
export default defineConfig({
7
plugins: [
8
vue(),
9
react(),
10
nodePolyfills(),
11
],
12
})

Usage

src/components/Widget.vue

Terminal
VUE
1
<template>
2
<Widget :config="config" />
3
</template>
4
5
<script lang="ts">
6
import { OpenOceanWidget } from '@openocean.finance/widget'
7
import { applyPureReactInVue } from 'veaury'
8
9
export default {
10
components: {
11
Widget: applyPureReactInVue(OpenOceanWidget),
12
},
13
setup() {
14
return {
15
config: {
16
theme: {
17
container: {
18
border: '1px solid rgb(234, 234, 234)',
19
borderRadius: '16px',
20
},
21
},
22
integrator: 'vue-example',
23
},
24
}
25
},
26
}
27
</script>

Key Points

  • Uses veaury to bridge React and Vue components
  • Requires both Vue and React plugins in Vite
  • Use applyPureReactInVue or applyReactInVue HOC

Nuxt 3

Installation

Terminal
SH
1
npm install @openocean.finance/widget veaury

Configuration

nuxt.config.ts

Terminal
TS
1
export default defineNuxtConfig({
2
compatibilityDate: '2024-04-03',
3
ssr: false, // Widget requires client-side rendering
4
})

Usage

components/WidgetContainer.vue

Terminal
VUE
1
<template>
2
<Widget :config="config" />
3
</template>
4
5
<script lang="ts">
6
import { OpenOceanWidget } from '@openocean.finance/widget'
7
import { applyPureReactInVue } from 'veaury'
8
9
export default {
10
components: {
11
Widget: applyPureReactInVue(OpenOceanWidget),
12
},
13
setup() {
14
return {
15
config: {
16
theme: {
17
container: {
18
border: '1px solid rgb(234, 234, 234)',
19
borderRadius: '16px',
20
},
21
},
22
integrator: 'nuxt-example',
23
},
24
}
25
},
26
}
27
</script>

app.vue

Terminal
VUE
1
<template>
2
<ClientOnly>
3
<WidgetContainer />
4
</ClientOnly>
5
</template>

Key Points

  • Use ClientOnly component for SSR safety
  • Disable SSR or use client-only rendering
  • Same Vue-React bridge approach as Vue 3

Svelte

Installation

Terminal
SH
1
npm install @openocean.finance/widget\nnpm install --save-dev @vitejs/plugin-react @vitejs/plugin-svelte

Configuration

vite.config.ts

Terminal
TS
1
import { defineConfig } from 'vite'
2
import { svelte } from '@sveltejs/vite-plugin-svelte'
3
import react from '@vitejs/plugin-react'
4
5
export default defineConfig({
6
plugins: [svelte(), react()],
7
})

Usage

src/lib/OpenOceanWidget.svelte

Terminal
SVE
1
<script>
2
import { OpenOceanWidget } from '@openocean.finance/widget'
3
import ReactAdapter from './ReactAdapter.svelte'
4
</script>
5
6
<ReactAdapter
7
element={OpenOceanWidget}
8
config={{
9
theme: {
10
container: {
11
boxShadow: '0px 8px 32px rgba(0, 0, 0, 0.08)',
12
borderRadius: '16px',
13
},
14
},
15
}}
16
integrator="svelte-example"
17
/>

src/lib/ReactAdapter.svelte

You'll need a React adapter component. Check the example for the full implementation.

Key Points

  • Requires a React adapter to use React components in Svelte
  • Both Svelte and React plugins needed
  • Custom adapter implementation required

Remix

Installation

Terminal
SH
1
npm install @openocean.finance/widget @tanstack/react-query

Configuration

remix.config.js

Terminal
JS
1
/** @type {import('@remix-run/dev').AppConfig} */
2
module.exports = {
3
serverModuleFormat: 'esm',
4
future: {
5
v2_errorBoundary: true,
6
v2_meta: true,
7
v2_normalizeFormMethod: true,
8
v2_routeConvention: true,
9
},
10
}

Usage

app/routes/_index.tsx

Terminal
TSX
1
import { ClientOnly } from 'remix-utils/client-only'
2
import { Fallback } from '../components/Fallback'
3
import { OpenOceanWidget } from '../components/OpenOceanWidget'
4
5
export default function Index() {
6
return (
7
<ClientOnly fallback={<Fallback />}>
8
{() => <OpenOceanWidget />}
9
</ClientOnly>
10
)
11
}

app/components/OpenOceanWidget.tsx

Terminal
TSX
1
import { OpenOceanWidget } from '@openocean.finance/widget'
2
import { QueryClientProvider } from '@tanstack/react-query'
3
import { queryClient } from '../lib/queryClient'
4
5
export function OpenOceanWidget() {
6
return (
7
<QueryClientProvider client={queryClient}>
8
<OpenOceanWidget
9
integrator="remix-example"
10
config={{
11
theme: {
12
container: {
13
border: '1px solid rgb(234, 234, 234)',
14
borderRadius: '16px',
15
},
16
},
17
}}
18
/>
19
</QueryClientProvider>
20
)
21
}

Key Points

  • Requires React Query provider
  • Server-side rendering support
  • Configure Remix for ES modules

RainbowKit

Installation

Terminal
SH
1
npm install @openocean.finance/widget @rainbow-me/rainbowkit wagmi viem\nnpm install @tanstack/react-query

Configuration

src/config/wagmi.ts

Terminal
TS
1
import { getDefaultConfig } from '@rainbow-me/rainbowkit'
2
import { mainnet, polygon, optimism, arbitrum, base } from 'wagmi/chains'
3
4
export const config = getDefaultConfig({
5
appName: 'OpenOcean Widget Example',
6
projectId: 'YOUR_PROJECT_ID',
7
chains: [mainnet, polygon, optimism, arbitrum, base],
8
ssr: true,
9
})

Usage

src/App.tsx

Terminal
TSX
1
import { OpenOceanWidget } from '@openocean.finance/widget'
2
import { ConnectButton, useConnectModal } from '@rainbow-me/rainbowkit'
3
import { WagmiProvider } from 'wagmi'
4
import { QueryClientProvider } from '@tanstack/react-query'
5
import { config } from './config/wagmi'
6
import { queryClient } from './config/queryClient'
7
8
export default function App() {
9
const { openConnectModal } = useConnectModal()
10
11
return (
12
<WagmiProvider config={config}>
13
<QueryClientProvider client={queryClient}>
14
<RainbowKitProvider>
15
<ConnectButton chainStatus="none" />
16
<OpenOceanWidget
17
config={{
18
walletConfig: {
19
onConnect() {
20
openConnectModal?.()
21
},
22
},
23
theme: {
24
container: {
25
boxShadow: '0px 8px 32px rgba(0, 0, 0, 0.08)',
26
borderRadius: '16px',
27
},
28
},
29
}}
30
integrator="rainbowkit-example"
31
/>
32
</RainbowKitProvider>
33
</QueryClientProvider>
34
</WagmiProvider>
35
)
36
}

Key Points

  • Integrates with RainbowKit wallet connection
  • Uses walletConfig.onConnect to trigger RainbowKit modal
  • Requires Wagmi and React Query setup

ConnectKit

Installation

Terminal
SH
1
npm install @openocean.finance/widget @openocean.finance/wallet-management\nnpm install connectkit wagmi viem @tanstack/react-query

Configuration

src/config/queryClient.ts

Terminal
TS
1
import { QueryClient } from '@tanstack/react-query'
2
3
export const queryClient = new QueryClient()

src/providers/WalletProvider.tsx

Set up ConnectKit wallet provider. See example for full implementation.

Usage

src/App.tsx

Terminal
TSX
1
import { OpenOceanWidget } from '@openocean.finance/widget'
2
import { QueryClientProvider } from '@tanstack/react-query'
3
import { WalletProvider } from './providers/WalletProvider'
4
import { queryClient } from './config/queryClient'
5
6
function App() {
7
return (
8
<QueryClientProvider client={queryClient}>
9
<WalletProvider>
10
<OpenOceanWidget
11
integrator="widget-connectkit-example"
12
config={{
13
theme: {
14
container: {
15
border: '1px solid rgb(234, 234, 234)',
16
borderRadius: '16px',
17
},
18
},
19
}}
20
/>
21
</WalletProvider>
22
</QueryClientProvider>
23
)
24
}

Key Points

  • Uses OpenOcean's wallet-management package
  • Integrates with ConnectKit
  • Requires QueryClient setup

Privy

Installation

Terminal
SH
1
npm install @openocean.finance/widget @privy-io/react-auth\nnpm install @tanstack/react-query

Configuration

src/config/queryClient.ts

Terminal
TS
1
import { QueryClient } from '@tanstack/react-query'
2
3
export const queryClient = new QueryClient()

Usage

src/App.tsx

Terminal
TSX
1
import { OpenOceanWidget } from '@openocean.finance/widget'
2
import { PrivyProvider } from '@privy-io/react-auth'
3
import { QueryClientProvider } from '@tanstack/react-query'
4
import { queryClient } from './config/queryClient'
5
6
function App() {
7
return (
8
<PrivyProvider
9
appId="YOUR_PRIVY_APP_ID"
10
config={{
11
loginMethods: ['wallet', 'email', 'sms'],
12
}}
13
>
14
<QueryClientProvider client={queryClient}>
15
<OpenOceanWidget
16
integrator="privy-example"
17
config={{
18
theme: {
19
container: {
20
border: '1px solid rgb(234, 234, 234)',
21
borderRadius: '16px',
22
},
23
},
24
}}
25
/>
26
</QueryClientProvider>
27
</PrivyProvider>
28
)
29
}

Key Points

  • Integrates with Privy authentication
  • Supports multiple login methods
  • Requires Privy app ID

Privy + Ethers

Installation

Terminal
SH
1
npm install @openocean.finance/widget @privy-io/react-auth ethers\nnpm install @tanstack/react-query

Usage

Similar to Privy example but with Ethers.js integration for wallet operations.

Key Points

  • Extends Privy with Ethers.js
  • Provides more wallet control
  • See example for wallet provider implementation

Reown (WalletConnect)

Installation

Terminal
SH
1
npm install @openocean.finance/widget @reown/appkit @reown/appkit-adapter-wagmi\nnpm install wagmi viem @tanstack/react-query

Configuration

src/config/wagmi.ts

Terminal
TS
1
import { createConfig, http } from 'wagmi'
2
import { mainnet, sepolia } from 'wagmi/chains'
3
import { createAppKit } from '@reown/appkit/react'
4
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
5
6
const metadata = {
7
name: 'OpenOcean Widget',
8
description: 'OpenOcean Widget Example',
9
url: 'https://openocean.finance',
10
icons: ['/logo.avif'],
11
}
12
13
const wagmiAdapter = new WagmiAdapter({
14
ssr: true,
15
chains: [mainnet, sepolia],
16
transports: {
17
[mainnet.id]: http(),
18
[sepolia.id]: http(),
19
},
20
})
21
22
export const config = createConfig({
23
chains: [mainnet, sepolia],
24
transports: {
25
[mainnet.id]: http(),
26
[sepolia.id]: http(),
27
},
28
})
29
30
createAppKit({
31
adapters: [wagmiAdapter],
32
chains: [mainnet, sepolia],
33
projectId: 'YOUR_PROJECT_ID',
34
metadata,
35
})

Usage

src/App.tsx

Terminal
TSX
1
import { OpenOceanWidget } from '@openocean.finance/widget'
2
import { WagmiProvider } from 'wagmi'
3
import { QueryClientProvider } from '@tanstack/react-query'
4
import { config } from './config/wagmi'
5
import { queryClient } from './config/queryClient'
6
7
export default function App() {
8
return (
9
<WagmiProvider config={config}>
10
<QueryClientProvider client={queryClient}>
11
<OpenOceanWidget
12
integrator="reown-example"
13
config={{
14
theme: {
15
container: {
16
border: '1px solid rgb(234, 234, 234)',
17
borderRadius: '16px',
18
},
19
},
20
}}
21
/>
22
</QueryClientProvider>
23
</WagmiProvider>
24
)
25
}

Key Points

  • Uses Reown (WalletConnect v4)
  • Requires project ID from WalletConnect Cloud
  • Full Wagmi integration

Dynamic

Installation

Terminal
SH
1
npm install @openocean.finance/widget @dynamic-labs/sdk-react-core\nnpm install @tanstack/react-query

Configuration

src/config/dynamic.ts

Terminal
TS
1
import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core'
2
3
export const dynamicConfig = {
4
environmentId: 'YOUR_ENVIRONMENT_ID',
5
}

Usage

src/App.tsx

Terminal
TSX
1
import { OpenOceanWidget } from '@openocean.finance/widget'
2
import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core'
3
import { QueryClientProvider } from '@tanstack/react-query'
4
import { queryClient } from './config/queryClient'
5
import { dynamicConfig } from './config/dynamic'
6
7
function App() {
8
return (
9
<DynamicContextProvider settings={dynamicConfig}>
10
<QueryClientProvider client={queryClient}>
11
<OpenOceanWidget
12
integrator="dynamic-example"
13
config={{
14
theme: {
15
container: {
16
border: '1px solid rgb(234, 234, 234)',
17
borderRadius: '16px',
18
},
19
},
20
}}
21
/>
22
</QueryClientProvider>
23
</DynamicContextProvider>
24
)
25
}

Key Points

  • Integrates with Dynamic Labs wallet SDK
  • Requires environment ID
  • Supports multiple wallet types

Zustand Widget Config

Installation

Terminal
SH
1
npm install @openocean.finance/widget zustand\nnpm install @mui/material

Usage

This example demonstrates using Zustand for widget configuration state management with form controls.

src/store/createWidgetConfigStore.ts

Terminal
TS
1
import { create } from 'zustand'
2
import type { WidgetConfig } from '@openocean.finance/widget'
3
4
interface WidgetConfigState {
5
config: Partial<WidgetConfig>
6
setConfig: (config: Partial<WidgetConfig>) => void
7
setFormValues: (formValues: Partial<WidgetConfig>) => void
8
}
9
10
export const useWidgetConfigStore = create<WidgetConfigState>((set, get) => ({
11
config: {
12
buildUrl: true,
13
theme: {
14
container: {
15
border: '1px solid rgb(234, 234, 234)',
16
borderRadius: '16px',
17
},
18
},
19
},
20
setConfig: (config) => set({ config }),
21
setFormValues: (formValues) => {
22
const currentConfig = get().config ?? {}
23
const { fromAmount, fromChain, fromToken, toAddress, toChain, toToken, ...rest } = currentConfig
24
set({
25
config: {
26
...rest,
27
...formValues,
28
},
29
})
30
},
31
}))

src/App.tsx

Terminal
TSX
1
import { Box } from '@mui/material'
2
import { FormControls } from './components/FormControls'
3
import { WidgetView } from './components/WidgetView'
4
5
function App() {
6
return (
7
<Box sx={{ display: 'flex', gap: 2 }}>
8
<FormControls />
9
<WidgetView />
10
</Box>
11
)
12
}

src/components/WidgetView.tsx

Terminal
TSX
1
import { OpenOceanWidget } from '@openocean.finance/widget'
2
import { useWidgetConfigStore } from '../store/createWidgetConfigStore'
3
4
export function WidgetView() {
5
const config = useWidgetConfigStore((state) => state.config)
6
7
return (
8
<OpenOceanWidget
9
integrator="zustand-example"
10
config={config}
11
/>
12
)
13
}

Key Points

  • Uses Zustand for state management
  • Separates form controls from widget view
  • Allows dynamic widget configuration updates
  • Good for complex state management scenarios
  • Supports form value updates without affecting other config

Deposit Flow

Installation

Terminal
SH
1
npm install @openocean.finance/widget

Usage

This example demonstrates a deposit flow integration with custom contract calls and deposit card.

src/App.tsx

Terminal
TSX
1
import type { ContractCall, WidgetConfig } from '@openocean.finance/widget'
2
import {
3
ChainType,
4
CoinKey,
5
DisabledUI,
6
HiddenUI,
7
OpenOceanWidget,
8
} from '@openocean.finance/widget'
9
import { useMemo } from 'react'
10
import { DepositCard } from './components/DepositCard'
11
import { contractTool } from './config'
12
13
const depositAddress = '0x4bF3E32de155359D1D75e8B474b66848221142fc'
14
const contractCalls: ContractCall[] = []
15
16
export function App() {
17
const widgetConfig: WidgetConfig = useMemo(() => {
18
return {
19
toAddress: {
20
...contractTool,
21
address: depositAddress,
22
chainType: ChainType.EVM,
23
},
24
subvariant: 'custom',
25
subvariantOptions: { custom: 'deposit' },
26
integrator: 'ProtocolName',
27
disabledUI: [DisabledUI.ToAddress],
28
hiddenUI: [HiddenUI.Appearance, HiddenUI.Language],
29
useRecommendedRoute: true,
30
theme: {
31
container: {
32
border: '1px solid rgb(234, 234, 234)',
33
borderRadius: '16px',
34
},
35
},
36
}
37
}, [])
38
39
return (
40
<OpenOceanWidget
41
contractComponent={
42
<DepositCard
43
token={{
44
chainId: 10,
45
address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
46
symbol: 'USDC',
47
name: 'USD Coin',
48
decimals: 6,
49
priceUSD: '1',
50
coinKey: CoinKey.USDC,
51
logoURI: '...',
52
}}
53
contractCalls={contractCalls}
54
/>
55
}
56
contractTool={contractTool}
57
config={widgetConfig}
58
integrator={widgetConfig.integrator}
59
/>
60
)
61
}

Key Points

  • Custom deposit flow with contract calls
  • Uses subvariant: 'custom' with custom: 'deposit'
  • Custom contractComponent for deposit UI
  • Disables and hides specific UI elements
  • Requires contractTool configuration

Common Configuration Options

All examples support these common configuration options:

Terminal
TS
1
{
2
integrator: string, // Required: Your integrator identifier
3
variant?: 'wide' | 'compact' | 'drawer',
4
subvariant?: 'split' | 'bridge' | 'swap',
5
appearance?: 'light' | 'dark' | 'auto',
6
theme?: {
7
container?: {
8
border?: string,
9
borderRadius?: string,
10
boxShadow?: string,
11
},
12
// ... more theme options
13
},
14
chains?: {
15
allow?: number[],
16
deny?: number[],
17
},
18
buildUrl?: boolean,
19
// ... more config options
20
}

Troubleshooting

SSR Issues

  • Use ClientOnly wrapper in Next.js/Nuxt
  • Disable SSR if not needed
  • Use WidgetSkeleton as fallback

Wallet Connection Issues

  • Ensure wallet providers are properly configured
  • Check network/chain configurations
  • Verify API keys and project IDs

Build Issues

  • Install required polyfills (buffer, process)
  • Configure Vite/Rollup for React components
  • Check transpilePackages in Next.js config

Support

For more information, visit:

Next Steps