npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hongming-wang/usdc-bridge-widget

v0.3.4

Published

A reusable USDC cross-chain bridge widget powered by Circle CCTP

Downloads

70

Readme

USDC Bridge Widget

A reusable React widget for cross-chain USDC transfers powered by Circle's CCTP (Cross-Chain Transfer Protocol).

Features

  • Cross-chain USDC transfers with native token minting
  • No bridge fees (only gas costs)
  • Customizable theme and styling
  • Built-in chain switching
  • TypeScript support
  • Works with any wagmi-compatible wallet

Installation

npm install @honeypot-finance/usdc-bridge-widget
# or
yarn add @honeypot-finance/usdc-bridge-widget
# or
pnpm add @honeypot-finance/usdc-bridge-widget

Peer Dependencies

Make sure you have these peer dependencies installed:

npm install react react-dom wagmi viem @tanstack/react-query

Quick Start

import { BridgeWidget } from "@honeypot-finance/usdc-bridge-widget";
import { WagmiProvider, createConfig, http } from "wagmi";
import { mainnet, arbitrum, base, optimism, polygon } from "viem/chains";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { injected } from "wagmi/connectors";

// Create wagmi config - IMPORTANT: Include transports for ALL chains you want to fetch balances from
const config = createConfig({
  chains: [mainnet, arbitrum, base, optimism, polygon],
  connectors: [injected()],
  transports: {
    [mainnet.id]: http(),
    [arbitrum.id]: http(),
    [base.id]: http(),
    [optimism.id]: http(),
    [polygon.id]: http(),
  },
});

const queryClient = new QueryClient();

function App() {
  // You need to provide onConnectWallet to handle wallet connection
  const handleConnectWallet = () => {
    // For RainbowKit: use openConnectModal from useConnectModal()
    // For ConnectKit: use open from useModal()
    // For web3modal: use open from useWeb3Modal()
  };

  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <BridgeWidget
          defaultSourceChainId={1}
          defaultDestinationChainId={8453}
          onConnectWallet={handleConnectWallet}
          onBridgeSuccess={({ txHash, amount }) => {
            console.log(`Bridged ${amount} USDC: ${txHash}`);
          }}
        />
      </QueryClientProvider>
    </WagmiProvider>
  );
}

RainbowKit Integration

import { useConnectModal } from '@rainbow-me/rainbowkit';
import { useAccount } from 'wagmi';

function App() {
  const { openConnectModal } = useConnectModal();
  const { isConnected } = useAccount();

  // Prevent opening modal if already connected or reconnecting
  const handleConnectWallet = () => {
    if (!isConnected && openConnectModal) {
      openConnectModal();
    }
  };

  return (
    <BridgeWidget
      onConnectWallet={handleConnectWallet}
      // ... other props
    />
  );
}

Important Integration Notes

Wagmi Config Must Match Widget Chains

The widget fetches USDC balances for all chains passed via the chains prop. Your wagmi config must include transports for every chain you want to display:

import { createConfig, http } from 'wagmi';
import { mainnet, base, arbitrum } from 'viem/chains';
import { createChainConfig } from '@honeypot-finance/usdc-bridge-widget';

// ✅ Good: Wagmi config matches widget chains
const config = createConfig({
  chains: [mainnet, base, arbitrum],
  transports: {
    [mainnet.id]: http(),
    [base.id]: http(),
    [arbitrum.id]: http(),
  },
});

const widgetChains = [
  createChainConfig(mainnet),
  createChainConfig(base),
  createChainConfig(arbitrum),
];

<BridgeWidget chains={widgetChains} />

If a chain is in the widget but not in your wagmi config, balance fetching will fail for that chain.

Handling Wallet Reconnection

The widget handles reconnecting states automatically, showing "Connecting..." during wagmi's auto-reconnect. Your onConnectWallet callback only needs a simple isConnected check since the widget handles reconnecting states internally:

const { isConnected } = useAccount();

const handleConnectWallet = () => {
  if (!isConnected) {
    openConnectModal?.();
  }
};

Props

BridgeWidgetProps

| Prop | Type | Default | Description | |------|------|---------|-------------| | chains | BridgeChainConfig[] | All CCTP chains | Array of supported chains | | defaultSourceChainId | number | First chain | Default source chain ID | | defaultDestinationChainId | number | Second chain | Default destination chain ID | | onBridgeStart | function | - | Called when bridge starts | | onBridgeSuccess | function | - | Called on successful bridge | | onBridgeError | function | - | Called on bridge error | | onConnectWallet | function | - | Recommended. Called when "Connect Wallet" clicked. Required for wallet connection to work. | | theme | BridgeWidgetTheme | Default theme | Custom theme overrides | | borderless | boolean | false | Remove borders/shadows for seamless integration | | enablePersistence | boolean | true | Persist bridge state to localStorage for recovery | | onPendingBridgeDetected | function | - | Called when incomplete bridges are found on load | | onRecoveryComplete | function | - | Called when a recovered bridge completes | | onRecoveryError | function | - | Called when bridge recovery fails | | className | string | - | Custom CSS class | | style | CSSProperties | - | Custom inline styles |

BridgeChainConfig

interface BridgeChainConfig {
  chain: Chain;                      // viem Chain object
  usdcAddress: `0x${string}`;        // USDC contract address
  tokenMessengerAddress?: `0x${string}`; // Circle TokenMessenger address
  iconUrl?: string;                  // Optional chain icon URL
}

BridgeWidgetTheme

interface BridgeWidgetTheme {
  primaryColor?: string;      // Default: "#6366f1"
  secondaryColor?: string;    // Default: "#a855f7"
  backgroundColor?: string;   // Default: "rgba(15, 15, 25, 0.8)"
  cardBackgroundColor?: string;
  textColor?: string;         // Default: "#ffffff"
  mutedTextColor?: string;
  borderColor?: string;
  successColor?: string;      // Default: "#22c55e"
  errorColor?: string;        // Default: "#ef4444"
  hoverColor?: string;        // Default: "rgba(255, 255, 255, 0.05)"
  borderRadius?: number;      // Default: 12
  fontFamily?: string;
}

Custom Chain Configuration

import { BridgeWidget, createChainConfig, USDC_ADDRESSES } from "@honeypot-finance/usdc-bridge-widget";
import { mainnet, arbitrum, base } from "viem/chains";
import { defineChain } from "viem";

// Use helper function
const chains = [
  createChainConfig(mainnet, {
    iconUrl: "https://example.com/eth-icon.png",
  }),
  createChainConfig(arbitrum),
  createChainConfig(base),
];

// Or define manually
const customChain = defineChain({
  id: 12345,
  name: "Custom Chain",
  // ... other chain config
});

const customChainConfig = {
  chain: customChain,
  usdcAddress: "0x..." as `0x${string}`,
  tokenMessengerAddress: "0x..." as `0x${string}`,
  iconUrl: "https://example.com/custom-icon.png",
};

<BridgeWidget chains={[...chains, customChainConfig]} />

Custom Theme

<BridgeWidget
  chains={DEFAULT_CHAIN_CONFIGS}
  theme={{
    primaryColor: "#00ff00",
    secondaryColor: "#00cc00",
    backgroundColor: "#1a1a2e",
    borderRadius: 16,
    fontFamily: "Inter, sans-serif",
  }}
/>

Borderless Mode

Use the borderless prop for seamless integration into your existing UI. This removes all borders, shadows, and backgrounds from the widget container and its child components:

<BridgeWidget borderless />

{/* Or combine with custom styling */}
<div className="my-custom-container">
  <BridgeWidget
    borderless
    style={{ padding: 0 }}
  />
</div>

Callbacks

<BridgeWidget
  chains={DEFAULT_CHAIN_CONFIGS}
  onBridgeStart={({ sourceChainId, destChainId, amount }) => {
    console.log(`Starting bridge: ${amount} USDC from ${sourceChainId} to ${destChainId}`);
  }}
  onBridgeSuccess={({ sourceChainId, destChainId, amount, txHash }) => {
    console.log(`Bridge successful! TX: ${txHash}`);
  }}
  onBridgeError={(error) => {
    console.error("Bridge failed:", error.message);
  }}
  onConnectWallet={() => {
    // Open your wallet modal
    openWalletModal();
  }}
/>

Bridge Recovery

The widget automatically persists bridge state to localStorage. If a user closes the tab during bridging (e.g., during the ~15 min attestation wait), a recovery banner appears on next visit allowing them to resume.

<BridgeWidget
  enablePersistence={true} // default
  onPendingBridgeDetected={(bridges) => {
    console.log(`Found ${bridges.length} incomplete bridge(s)`);
  }}
  onRecoveryComplete={({ sourceChainId, destChainId, amount, txHash }) => {
    console.log(`Recovery complete: ${amount} USDC, tx: ${txHash}`);
  }}
  onRecoveryError={(error) => {
    console.error("Recovery failed:", error.message);
  }}
/>

Advanced consumers can use the recovery hook and storage utilities directly:

import { useRecovery, loadPendingBridges } from "@honeypot-finance/usdc-bridge-widget";

Using Individual Hooks

The widget exports its internal hooks for advanced usage:

import {
  useUSDCBalance,
  useAllUSDCBalances,
  useUSDCAllowance,
  useBridge,
  useBridgeQuote,
  useRecovery,
} from "@honeypot-finance/usdc-bridge-widget";

function CustomComponent() {
  const chainConfig = { chain: mainnet, usdcAddress: "0x..." };

  // Balance hooks
  const { balance, balanceFormatted } = useUSDCBalance(chainConfig);
  const { balances, isLoading } = useAllUSDCBalances([chainConfig]);

  // Allowance hook
  const { needsApproval, approve, isApproving } = useUSDCAllowance(chainConfig);

  // Bridge execution hook
  const { bridge, state, reset } = useBridge();
  // state.status: "idle" | "loading" | "approving" | "burning" | "fetching-attestation" | "minting" | "success" | "error"

  // Quote hook (returns static CCTP estimates)
  const { quote, isLoading: quoteLoading } = useBridgeQuote(1, 8453, "100");

  // Build your own UI
}

Deprecated Hooks

The following hooks are deprecated and will be removed in a future version:

  • useBridgeEstimate - Use useBridgeQuote instead
  • useFormatNumber - Use the formatNumber utility function directly

Supported Chains

The widget includes pre-configured USDC and TokenMessenger addresses for all CCTP V2 EVM chains:

| Chain | Chain ID | |-------|----------| | Ethereum | 1 | | Arbitrum | 42161 | | Base | 8453 | | Optimism | 10 | | Polygon | 137 | | Avalanche | 43114 | | Linea | 59144 | | Unichain | 130 | | Sonic | 146 | | World Chain | 480 | | Monad | 10200 | | Sei | 1329 | | XDC | 50 | | HyperEVM | 999 | | Ink | 57073 | | Plume | 98866 | | Codex | 81224 |

See Circle CCTP Docs for the latest supported chains

Circle Bridge Kit Integration

For full bridge functionality, install Circle's Bridge Kit:

npm install @circle-fin/bridge-kit @circle-fin/adapter-viem-v2

Then integrate with the widget's callbacks to execute actual transfers.

License

MIT