Skip to content
TokenFlight SDK

React Integration

TokenFlight is exposed publicly as <tokenflight-widget> plus the TokenFlightWidget imperative class.

The imperative API is the most reliable approach across React versions. Use useRef for the container and useEffect for lifecycle management:

import { useEffect, useRef, useMemo } from 'react';
import { TokenFlightWidget } from '@tokenflight/swap';
import { WagmiWalletAdapter } from '@tokenflight/adapter-wagmi';
function PaymentWidget({ wagmiConfig, theme = 'dark' }) {
const containerRef = useRef<HTMLDivElement>(null);
const walletAdapter = useMemo(
() => new WagmiWalletAdapter(wagmiConfig),
[wagmiConfig]
);
useEffect(() => {
if (!containerRef.current) return;
const widget = new TokenFlightWidget({
container: containerRef.current,
config: {
toToken: { chainId: 8453, address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' },
tradeType: 'EXACT_OUTPUT',
amount: '100',
theme,
},
walletAdapter,
callbacks: {
onSwapSuccess: (data) => console.log('Payment completed:', data.orderId),
onSwapError: (error) => console.error(`[${error.code}] ${error.message}`),
},
});
widget.initialize();
return () => widget.destroy();
}, [walletAdapter, theme]);
return <div ref={containerRef} style={{ minHeight: 560 }} />;
}

If you prefer the custom element directly, register the widget once and use <tokenflight-widget> in JSX:

import { useEffect } from 'react';
import { registerWidgetElement } from '@tokenflight/swap/widget';
import { WagmiWalletAdapter } from '@tokenflight/adapter-wagmi';
function App({ wagmiConfig }) {
useEffect(() => {
registerWidgetElement({
walletAdapter: new WagmiWalletAdapter(wagmiConfig),
callbacks: {
onSwapSuccess: (data) => console.log('Payment completed:', data.orderId),
onSwapError: (error) => console.error(`[${error.code}] ${error.message}`),
},
});
}, [wagmiConfig]);
return (
<tokenflight-widget
to-token="eip155:8453:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
trade-type="EXACT_OUTPUT"
amount="100"
theme="dark"
/>
);
}

For per-instance callbacks, use a ref:

import { useEffect, useRef } from 'react';
import { registerWidgetElement } from '@tokenflight/swap/widget';
registerWidgetElement();
function WidgetWithCallbacks() {
const ref = useRef<HTMLElement>(null);
useEffect(() => {
if (!ref.current) return;
ref.current.__callbacks = {
onSwapSuccess: (data) => console.log('Done:', data),
onConnectWallet: () => myWalletModal.open(),
};
}, []);
return (
<tokenflight-widget
ref={ref}
to-token="eip155:8453:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
trade-type="EXACT_OUTPUT"
amount="100"
theme="dark"
/>
);
}

In React 18 and earlier, custom-element props are usually serialized as attributes:

  • Objects cannot be passed via JSX.
  • Functions cannot be passed via JSX.
  • String and boolean HTML attributes work normally.

That is why declarative usage relies on registerWidgetElement() defaults or ref.__callbacks for non-string values.

Add one import to get typed JSX tags for <tokenflight-widget>:

import "@tokenflight/swap/custom-elements";
  • Cache adapter instances with useMemo.
  • Call destroy() in the cleanup function.
  • Recreate the widget when config changes after initialize().
  • There is no separate React wrapper package; use the public widget directly.