Skip to content

AppKit

Use AppKit when you want WalletConnect UX plus optional multi-chain providers in one modal.

Live projectOpen in StackBlitz

This page shows the TokenFlight helper that creates AppKit, registers EVM support, and passes Solana signing support when you include Solana networks.

The embedded project is a runnable demo. The React example below is the canonical setup pattern for apps that create and clean up TokenFlightWidget from a client component.

Install

bash
npm install @tokenflight/swap @tokenflight/adapter-appkit @reown/appkit @reown/appkit-adapter-wagmi @reown/appkit-adapter-solana @solana/web3.js wagmi viem
bash
pnpm add @tokenflight/swap @tokenflight/adapter-appkit @reown/appkit @reown/appkit-adapter-wagmi @reown/appkit-adapter-solana @solana/web3.js wagmi viem
bash
yarn add @tokenflight/swap @tokenflight/adapter-appkit @reown/appkit @reown/appkit-adapter-wagmi @reown/appkit-adapter-solana @solana/web3.js wagmi viem
bash
bun add @tokenflight/swap @tokenflight/adapter-appkit @reown/appkit @reown/appkit-adapter-wagmi @reown/appkit-adapter-solana @solana/web3.js wagmi viem

Example

tsx
import { mainnet, base } from '@reown/appkit/networks';
import { TokenFlightWidget } from '@tokenflight/swap';
import { createAppKitAdapter } from '@tokenflight/adapter-appkit';
import { VersionedTransaction } from '@solana/web3.js';
import { useEffect, useRef } from 'react';

// Get your project ID from https://cloud.reown.com
const projectId = import.meta.env.VITE_REOWN_PROJECT_ID;
const networks = [mainnet, base] as const;

export default function App() {
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    let cancelled = false;
    let widget: TokenFlightWidget | undefined;
    let walletAdapter: Awaited<ReturnType<typeof createAppKitAdapter>>['adapter'] | undefined;

    async function mountWidget() {
      if (!containerRef.current) return;

      const result = await createAppKitAdapter({
        projectId,
        networks,
        solana: { VersionedTransaction },
        metadata: {
          name: 'TokenFlight Example',
          description: 'TokenFlight + AppKit',
          url: window.location.origin,
          icons: [],
        },
      });
      walletAdapter = result.adapter;

      if (cancelled) {
        walletAdapter.destroy?.();
        return;
      }

      widget = new TokenFlightWidget({
        container: containerRef.current,
        config: {
          toToken: { chainId: 8453, address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' },
          amount: '100',
          tradeType: 'EXACT_OUTPUT',
          theme: 'light',
        },
        walletAdapter,
      });
      widget.initialize();
    }

    void mountWidget();

    return () => {
      cancelled = true;
      widget?.destroy();
      walletAdapter?.destroy?.();
    };
  }, []);

  return <div ref={containerRef} style={{ minHeight: 560 }} />;
}

Set VITE_REOWN_PROJECT_ID in your .env file. Get a project ID from cloud.reown.com.

If your app is EVM-only, keep EVM networks in networks. If you add Solana networks to AppKit, keep the solana: { VersionedTransaction } option so the adapter can sign Solana transactions.

How It Works

  1. Create the AppKit adaptercreateAppKitAdapter() creates the AppKit instance, EVM wallet adapter, Solana adapter, and TokenFlight walletAdapter.

  2. Pass the TokenFlight adapter — the returned adapter implements the IWalletAdapter interface that TokenFlight widgets expect. Chain IDs are auto-derived from AppKit networks.

  3. Initialize with useEffect — mount the widget in a React effect to ensure the DOM container exists. Clean up both widget.destroy() and walletAdapter.destroy?.() when the component unmounts.

  4. Keep adapter identity stable — create the adapter in a client-only lifecycle or memoize it in your app, so wallet state does not reset on every render.

Adding Callbacks

tsx
const widget = new TokenFlightWidget({
  container: '#widget',
  config: {
    toToken: { chainId: 8453, address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' },
    amount: '100',
    tradeType: 'EXACT_OUTPUT',
    theme: 'light',
  },
  walletAdapter,
  callbacks: {
    onDepositSuccess: (data) => {
      console.log('Payment completed:', data.orderId, data.txHash);
    },
    onDepositError: (error) => {
      console.error(`[${error.code}] ${error.message}`);
    },
    onWalletConnected: ({ address, chainType }) => {
      console.log(`Connected: ${address} (${chainType})`);
    },
  },
});

See Events & Callbacks for all available callbacks.