npm.io
0.2.0 • Published yesterday

@wheelx-widget/widget

Licence
MIT
Version
0.2.0
Deps
15
Size
17.1 MB
Vulns
0
Weekly
0

@wheelx-widget/widget

An open-source, framework-agnostic React widget for cross-chain token swaps and bridges. Built-in wallet connection support (EVM + Solana), configurable theme system, and ready-to-use demo application.

Features

  • Cross-chain Swap & Bridge — Full trading flow with quote polling, gas estimation, approval handling
  • Built-in Wallet Connection — Dynamic SDK + Wagmi v2 supporting EVM (MetaMask, OKX, etc.) and Solana (Phantom)
  • Configurable Theme — 14 color tokens for custom skinning
  • Framework Agnostic — Works with any React framework (Next.js, Vite, Create React App, etc.)
  • ESM + CJS — Dual-format builds with full TypeScript declarations
  • Configurable Default Tokens — Set default from/to chains and tokens
  • Deep Link Support — Wallet app launch support in WebView (React Native) — see Deep Link Guide

Installation

npm install @wheelx-widget/widget @chakra-ui/react @emotion/react

Note: @chakra-ui/react and @emotion/react are required peer dependencies.

Quick Start

If you don't have a project yet, scaffold one first:

npm create vite@latest my-swap-page -- --template react-ts
cd my-swap-page

Then install the widget and required peer dependencies:

npm install @wheelx-widget/widget @chakra-ui/react @emotion/react
// main.tsx — wrap with ChakraProvider
import { ChakraProvider, defaultSystem } from '@chakra-ui/react'
import { createRoot } from 'react-dom/client'
import App from './App'

createRoot(document.getElementById('root')!).render(
  <ChakraProvider value={defaultSystem}>
    <App />
  </ChakraProvider>
)
// App.tsx
// Import the CSS for animations (required!)
import '@wheelx-widget/widget/styles.css'
import { WheelXProvider, WheelXWidget } from '@wheelx-widget/widget'

function App() {
  return (
    <WheelXProvider>
      <WheelXWidget />
    </WheelXProvider>
  )
}

Configuration

Theme Customization

Customize 14 visual tokens:

<WheelXProvider config={{
  theme: {
    defaultTextColor: '#1A1D26',
    highlightTextColor: '#007B9D',
    weakTextColor: '#5D6270',
    defaultBgColor: '#FFFFFF',
    highlightBgColor: '#E6F7FB',
    assistBgColor: '#F5F6F8',
    defaultBorderColor: '#E2E4E8',
    highlightBorderColor: '#007B9D',
    highlightButtonBg: '#007B9D',
    highlightButtonText: '#FFFFFF',
    normalButtonBg: '#F5F6F8',
    normalButtonText: '#1A1D26',
    disabledButtonBg: '#E2E4E8',
    disabledButtonText: '#A0A4AE'
  }
}}>
  <WheelXWidget />
</WheelXProvider>
Default Chain/Token Configuration
<WheelXProvider config={{
  from: {
    chains: [8453, 1],           // Only show Base and Ethereum as from chains
    defaultChainId: 8453          // Default to Base
  },
  to: {
    chains: [1868],               // Only show Soneium as to chain
    defaultChainId: 1868          // Default to Soneium
  }
}}>
  <WheelXWidget />
</WheelXProvider>
Custom Dynamic Environment ID
<WheelXProvider config={{
  dynamicEnvironmentId: 'your-dynamic-environment-id'
}}>
  <WheelXWidget />
</WheelXProvider>
Fixed Recipient Address (Different Address)

Configure fixed recipient addresses for EVM or Solana chains. When set, the widget will:

  • Display the configured address in the To field instead of showing "Connect Wallet"
  • Query the token balance of the configured address
  • Skip wallet connection for the target chain (only the source chain wallet is required for signing)
  • Show GetGas when the configured address has insufficient native token balance

This is useful for exchange or merchant scenarios where funds should always be sent to a specific address regardless of which wallet the user connects.

Priority order for recipient address:

  1. Configured fixed address (evmDifferentAddress / solanaDifferentAddress)
  2. User manually entered different address (via Different Address dialog)
  3. Connected wallet address
<WheelXProvider config={{
  evmDifferentAddress: '0xAbCdEf1234567890...',  // Fixed recipient for EVM chains (0x format)
  solanaDifferentAddress: '9zQX...'               // Fixed recipient for Solana chains (base58 format)
}}>
  <WheelXWidget />
</WheelXProvider>

Note: You can configure one, both, or neither. The widget will only use the relevant one based on the selected To chain.

API Reference

<WheelXProvider>

The root provider component that sets up wallet connections, React Query, and theme.

Prop Type Default Description
config WidgetConfig {} Widget configuration
children React.ReactNode Child components
<WheelXWidget>

The main trading widget component.

Prop Type Default Description
config WidgetConfig {} Widget configuration
WidgetConfig
interface WidgetConfig {
  theme?: Partial<WidgetTheme>

  from?: {
    chains?: number[]
    defaultChainId?: number
    chainTokens?: Record<number, TokenConfig[]>
    defaultToken?: { chainId: number; address: string }
  }
  to?: {
    chains?: number[]
    defaultChainId?: number
    chainTokens?: Record<number, TokenConfig[]>
    defaultToken?: { chainId: number; address: string }
  }
  routerCallback?: {
    onPathnameChange?: (pathname: string) => void
    onRouteLeave?: () => void
    getCurrentPathname?: () => string
  }
  dynamicEnvironmentId?: string
  onDeepLink?: (url: string) => void  // See Deep Link Guide for WebView environments

  /** Fixed recipient address for EVM chains (0x format). Takes priority over wallet address and manual different address */
  evmDifferentAddress?: string
  /** Fixed recipient address for Solana chains (base58 format). Takes priority over wallet address and manual different address */
  solanaDifferentAddress?: string
}
WidgetTheme
interface WidgetTheme {
  defaultTextColor: string
  highlightTextColor: string
  weakTextColor: string
  defaultBgColor: string
  highlightBgColor: string
  assistBgColor: string
  defaultBorderColor: string
  highlightBorderColor: string
  highlightButtonBg: string
  highlightButtonText: string
  normalButtonBg: string
  normalButtonText: string
  disabledButtonBg: string
  disabledButtonText: string
  /** Color palette for the GetGas switch component. e.g. 'purple', 'blue', 'green'. Default: 'purple' */
  getGasSwitchColorPalette?: string
}

Demo

A demo https://widget.wheelx.fi

API Endpoint

This widget connects to the WheelX API at https://api.wheelx.fi. The API domain is not configurable.

React Native / WebView Integration

If you embed the Widget into a React Native WebView, additional configuration is required to properly launch wallet apps.

Please refer to: Mobile Wallet Launch Guide (DEEP_LINK_GUIDE.md)

In short, three things are required:

  1. Add onMessage listener in the WebView
  2. Configure <queries> declaration in Android's AndroidManifest.xml
  3. Configure LSApplicationQueriesSchemes in iOS's Info.plist

Troubleshooting

Problem Symptom Solution
Missing ChakraProvider White screen or unstyled component Wrap your app in <ChakraProvider value={defaultSystem}> — the widget depends on Chakra's context
Forgot to import CSS Component works but has no styling/animations Add import '@wheelx-widget/widget/styles.css' in your entry file
Vite dev server starts slow vite dev takes 30+ seconds Normal — Vite pre-bundles large wallet dependencies (wagmi, viem, ethers, etc.). Subsequent starts with cache are faster
Build output is large dist/ folder tens of MB, main bundle ~7.5MB (1.9MB gzipped) Expected — the widget bundles all wallet SDKs. Use code-splitting or lazy-loading in your host app if needed
React hooks errors "Invalid hook call" or context mismatch You may have duplicate React instances. Ensure react and react-dom are peer dependencies in your project, and use a single version (18 or 19)

License

MIT

Keywords