@nexus-cross/connect-kit-react
v1.3.6
Published
React components and hooks for @nexus-cross/connect-kit wallet connection
Readme
@nexus-cross/connect-kit-react
React provider, connect button, and hooks for crossx-kit. Drop
<CrossConnectKitProvider> at your tree root, render <ConnectButton />, and you
get a working multi-wallet connect flow for CROSSx (embedded / wallet /
extension) plus Reown-routed wallets (MetaMask, Binance) with a single config.
This is the primary entrypoint for DApp developers. If you need a headless
setup, use @nexus-cross/connect-kit-wagmi directly.
Install
pnpm add @nexus-cross/connect-kit-react \
wagmi viem @tanstack/react-query react react-dom@nexus-cross/connect-kit-react depends on
@nexus-cross/connect-kit-wagmi and @nexus-cross/dapp-ui, so most React
DApps install only the React package plus the peer dependencies above.
If your config uses toNexusAdapter(), add the private registry entry required
by the transitive @to-nexus/* packages:
@to-nexus:registry=https://package.cross-nexus.com/repository/cross-sdk-jsQuick start
// config.ts
import { createConnectKitConfig } from '@nexus-cross/connect-kit-react/client';
export const config = createConnectKitConfig({
crossProjectId: '...',
reownProjectId: '...',
app: { name: 'My DApp', url: 'https://example.com' },
});// App.tsx
import { CrossConnectKitProvider, ConnectButton } from '@nexus-cross/connect-kit-react';
import { config } from './config';
export function App() {
return (
<CrossConnectKitProvider config={config}>
<ConnectButton portfolio />
{/* your app */}
</CrossConnectKitProvider>
);
}That's it. createConnectKitConfig wires the CROSSx adapter, Reown adapter,
embedded social wallet, and default CROSS/BSC networks. Network defaults follow
NEXT_PUBLIC_CROSSX_ENVIRONMENT / VITE_CROSSX_ENVIRONMENT: production uses
mainnet, staging/development use testnet. ConnectButton portfolio also wires
wagmi's default sendTransactionAsync into the portfolio Send flow.
@nexus-cross/connect-kit-react/client imports the embedded connector, so use
it from a client/browser boundary. For Next.js server-side cookie hydration,
keep using the lower-level createCrossxConfig pattern shown in the SSR
section.
Components
<CrossConnectKitProvider>
<CrossConnectKitProvider
config={config}
initialState={initialState /* optional — SSR hydration */}
>
{children}
</CrossConnectKitProvider>Wraps children in WagmiProvider + QueryClientProvider + kit context. Swaps
the active wagmi config when the user picks a wallet from the other provider
(<WagmiProvider key={activeProvider}> triggers a clean remount), and
suppresses benign WalletConnect teardown noise in unhandledrejection.
- Reads the last-active provider from localStorage so reloads stay on the correct side.
- Persists the user's last wallet intent so
resolveCurrentWalletcan disambiguate EIP-6963 connector ID promotion (e.g.io.metamaskvsmetaMask).
SSR (Next.js App Router)
// app/layout.tsx (Server Component)
import { headers } from 'next/headers';
import { cookieToCrossConnectKitState } from '@nexus-cross/connect-kit-wagmi';
import { config } from './config';
import { Providers } from './providers';
export default async function RootLayout({ children }) {
const cookie = (await headers()).get('cookie');
const initialState = cookieToCrossConnectKitState(config, cookie);
return (
<html><body>
<Providers initialState={initialState}>{children}</Providers>
</body></html>
);
}// app/providers.tsx ('use client')
'use client';
import { CrossConnectKitProvider } from '@nexus-cross/connect-kit-react';
import { config } from './config';
export function Providers({ children, initialState }) {
return (
<CrossConnectKitProvider config={config} initialState={initialState}>
{children}
</CrossConnectKitProvider>
);
}Requires createCrossxConfig({ ssr: true }).
embeddedConnectorFactory imports the browser-only CROSSx SDK. In Next.js App
Router, do not import @nexus-cross/connect-kit-wagmi/embedded from a module
that is also imported by a Server Component. Keep SSR configs server-safe, or
build the embedded-enabled config inside a 'use client' boundary.
<ConnectButton>
<ConnectButton
label="Connect Wallet" // disconnected state label
portfolio // enable WalletPortfolio + Send
showBalance={true} // popover shows native balance
theme="dark" // or 'light'
className="my-btn" // optional — overrides built-in styles
style={{ /* WalletInfoStyle */ }}
/>Three visual states, driven by wagmi + the kit context:
- Disconnected — solid pill with
label, opens the unified connect modal on click. - Connecting / Reconnecting — spinner + "Connecting…".
- Connected — pill showing a platform icon + shortened address.
Clicking opens a popover powered by
@nexus-cross/dapp-ui'sWalletInfowith balance, copy-address, and a Disconnect footer.
The platform icon adapts per wallet:
cross_embedded— the OAuth provider icon (Google / Apple) when available, falls back to the CROSSx glyph.cross_wallet/cross_extension— CROSSx glyph.metamask/binance— the wallet's own brand mark.
For cross_embedded, the popover's My Wallet header is populated with
the saved wallet name from crossy-sdk 2.0 (sdk.getAddresses()) when one
exists.
Unified connect modal
import { useCrossConnectKit } from '@nexus-cross/connect-kit-react';
function MyCustomButton() {
const { openOtherWallets } = useCrossConnectKit();
return <button onClick={openOtherWallets}>Connect another wallet</button>;
}CrossConnectKitProvider renders the modal for you. Calling
openOtherWallets() opens the same unified modal used by <ConnectButton />,
including the social row and wallet list. CrossConnectModal and
OtherWalletsModal are exported for low-level integrations, but most DApps
should not render them directly.
Filter the wallet list with provider props:
<CrossConnectKitProvider
config={config}
walletAllowlist={['cross_wallet', 'cross_extension']}
extraWallets={{
verse8: () => window.alert('Verse8 support is coming soon'),
}}
>
{children}
</CrossConnectKitProvider>walletAllowlist={[]} hides the wallet-list rows and leaves only the social row
when embedded OAuth is configured. Disable the social row separately by omitting
embeddedConnectorFactory from createCrossxConfig.
Hooks
useCrossConnectKit()
const {
kitConfig,
connectorRegistry,
availableWallets, // registry entries with type !== 'embedded'
connect, // (walletId: WalletId) => Promise<void>
connectWallet, // () => Promise<void> — opens the unified connect modal
disconnect, // () => Promise<void>
selectWallet, // () => Promise<{ address, index } | null>
currentWallet, // WalletId | null
otherWalletsOpen,
openOtherWallets,
closeOtherWallets,
} = useCrossConnectKit();selectWallet is a no-op for non-embedded wallets (returns null) — only
the crossy-sdk 2.0 embedded wallet exposes a wallet-switcher.
For address, chain, balance, and signing use wagmi's own hooks
(useAccount, useBalance, useSignMessage, …). This package doesn't
reinvent them.
Re-exports
For convenience, @nexus-cross/connect-kit-react re-exports the types and the
WalletInfo component you normally need so you don't have to import from
three packages:
import {
WalletInfo, // cross-app-launcher compound component
ConnectorId,
ConnectionStatus,
formatBalance,
formatWei,
type WalletId,
type Account,
type ChainBalance,
type CrossConnectKitConfig,
type ConnectorRegistry,
type ConnectorEntry,
} from '@nexus-cross/connect-kit-react';Theming
CrossConnectKitProvider emits --cck-* CSS variables from
config.themeTokens. The dapp-ui surfaces (WalletInfo, WalletPortfolio,
WalletConnectModal, AppLauncher) read those variables, and the embedded SDK
receives the same theme tokens at runtime.
PIN Keyboard Configuration
Control which keyboard the mobile PIN modal shows when users enter their PIN for transaction confirmation or wallet setup. By default, the embedded SDK renders a virtual numpad on mobile; you can switch to the OS's native numeric keyboard instead.
export const config = createCrossxConfig({
// ... other options ...
pinKeyboard: 'native', // Use OS native numeric keyboard on mobile
});Options
| Value | Behavior |
|-------|----------|
| 'virtual' (default) | SDK renders a custom numpad on mobile. Desktop always shows input boxes. |
| 'native' | Mobile shows input boxes + OS numeric keyboard. Desktop unchanged. |
| () => 'native' \| 'virtual' | Function called each time PIN modal appears — resolve dynamically per user preference or A/B test. |
Examples
Static: Always use native keyboard
createCrossxConfig({
// ...
pinKeyboard: 'native',
});Dynamic: Follow user setting
createCrossxConfig({
// ...
pinKeyboard: () => userPreferences.nativePinKeyboard ? 'native' : 'virtual',
});Dynamic: A/B test
createCrossxConfig({
// ...
pinKeyboard: () => Math.random() > 0.5 ? 'native' : 'virtual',
});Allowed dependencies
This package may depend on: @nexus-cross/connect-kit-core,
@nexus-cross/connect-kit-wagmi, and @nexus-cross/dapp-ui. React, wagmi, and
TanStack Query stay peer dependencies of the consuming app.
It must not own low-level wallet transport logic. External SDK access belongs in the wagmi layer; this package composes providers, React context, hooks, and dapp-ui components.
Compatibility
react@^19,react-dom@^19wagmi>=2 <4,viem@^2@tanstack/react-query@^5
License
MIT
