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

@socket.tech/bungee

v1.0.0

Published

Bungee is a swap and bridge widget for moving tokens across blockchains. The `@socket.tech/bungee` package exposes a React component you can embed in your app.

Downloads

854

Readme

@socket.tech/bungee

What is Bungee?

Bungee is a swap and bridge widget for moving tokens across blockchains. The @socket.tech/bungee package exposes a React component you can embed in your app.

v1.0.0 Breaking Change: The widget no longer bundles wagmi or a wallet provider. Your app provides a minimal wallet adapter via config.wallet, and the widget handles routing, reads, writes, balances, receipts, and signing internally.

Before You Start

Bungee is a widget, not a full wallet/connect solution.

  • Provide wallet state and wallet connect UI.
  • Mount QueryClientProvider above <Bungee />.
  • Pass a minimal wallet adapter via config.wallet.
  • Support EVM only, Solana only, Tron only, or any combination by providing the matching adapter methods. You only need to pass the methods for the chains you support — e.g. for EVM-only apps, provide getEVMWalletClient and switchChain; you do not need to pass getSolanaSigner or getTronWeb.

Minimal React Query setup:

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const queryClient = new QueryClient();

root.render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>
);

Install

Install the package and its peer dependencies:

pnpm install @socket.tech/bungee react react-dom viem @tanstack/react-query

Peer dependencies are not installed automatically.

This installs the widget, not a wallet/connect solution. You must already have, or choose, wallet infrastructure in your app.

Import the widget styles in your app entrypoint:

import "@socket.tech/bungee/styles.css";
import "@socket.tech/bungee/fonts.css";

Quickstart

For a transaction-capable integration, the setup is:

  1. Install the package and peer dependencies.
  2. Mount QueryClientProvider.
  3. Import the widget CSS.
  4. Add a minimal wallet adapter.
  5. Render <Bungee config={config} />.

Choose the smallest path that matches your app:

  • EVM only: provide accounts, getEVMWalletClient, and usually switchChain. You do not need to pass getSolanaSigner or getTronWeb.
  • Solana only: provide accounts, getSolanaSigner, and rpcs.solana.
  • Tron only (for deposit/direct-deposit flows): provide accounts (including a TRON account) and getTronWeb.
  • EVM + Solana: combine EVM and Solana adapters in the same wallet object.
  • EVM + Tron: add getTronWeb and TRON accounts for Tron-supported routes.

EVM-Only Example

This is the smallest recommended setup if your app already uses an EVM wallet library such as wagmi.

Your connect modal or connect button still belongs to your app.

import { Bungee, type BungeeConfig } from "@socket.tech/bungee";
import { getWalletClient } from "@wagmi/core";
import { useMemo } from "react";
import { useAccount, useConfig, useSwitchChain } from "wagmi";

export function BungeeWidget() {
  const { address, chain, isConnected } = useAccount();
  const { switchChainAsync } = useSwitchChain();
  const wagmiConfig = useConfig();

  const accounts = useMemo(
    () =>
      address && isConnected
        ? [
            {
              address,
              chainType: "EVM" as const,
              chainId: chain?.id,
              isConnected: true,
            },
          ]
        : [],
    [address, chain?.id, isConnected],
  );

  const config: BungeeConfig = {
    // apiKey is optional when using the default public backend; required for dedicated backend
    apiKey: "your-api-key",
    wallet: {
      accounts,
      getEVMWalletClient: async (chainId) => {
        return getWalletClient(wagmiConfig, { chainId });
      },
      switchChain: async (chainId) => {
        await switchChainAsync({ chainId });
        return true;
      },
    },
    eventHandlers: {
      onOpenWalletConnect: () => {
        // Open your app's wallet modal or navigate to your connect screen.
        openYourWalletModal();
      },
    },
  };

  return <Bungee config={config} />;
}

Solana-Only Example

This example assumes Solana wallet-adapter providers are already mounted higher in your app.

import { Bungee, type BungeeConfig } from "@socket.tech/bungee";
import { useMemo } from "react";
import { useWallet } from "@solana/wallet-adapter-react";
import { useWalletModal } from "@solana/wallet-adapter-react-ui";

export function BungeeSolanaWidget() {
  const wallet = useWallet();
  const { setVisible } = useWalletModal();

  const accounts = useMemo(
    () =>
      wallet.publicKey
        ? [
            {
              address: wallet.publicKey.toBase58(),
              chainType: "SVM" as const,
              isConnected: wallet.connected,
            },
          ]
        : [],
    [wallet.connected, wallet.publicKey],
  );

  const config: BungeeConfig = {
    // apiKey is optional when using the default public backend; required for dedicated backend
    apiKey: "your-api-key",
    rpcs: {
      solana: "https://api.mainnet-beta.solana.com",
    },
    wallet: {
      accounts,
      getSolanaSigner: async () => {
        if (!wallet.connected) return null;
        return {
          signAndSendTransaction: wallet.sendTransaction ?? undefined,
          signTransaction: wallet.signTransaction ?? undefined,
        };
      },
    },
    eventHandlers: {
      onOpenWalletConnect: () => {
        setVisible(true);
      },
    },
  };

  return <Bungee config={config} />;
}

To support both EVM and Solana, combine this signer with the EVM adapter shown above in the same wallet object.

Both EVM and Solana

If your app supports both networks:

  • pass both account types in wallet.accounts
  • provide both getEVMWalletClient and getSolanaSigner
  • keep switchChain for EVM
  • route eventHandlers.onOpenWalletConnect(network) to the correct host wallet modal

Adding Tron (optional)

To support Tron deposit or direct-deposit flows:

  • include TRON accounts in wallet.accounts (with chainType: "TRON")
  • provide getTronWeb returning your app's TronWeb instance (must satisfy the TronWebLike interface)
  • route eventHandlers.onOpenWalletConnect("tron") to open your Tron wallet/connect UI

If you do not pass getTronWeb, the widget works as before; Tron routes simply won't be available for sending.

Configuration Reference

BungeeConfig Interface

Required Properties

  • wallet (WalletAdapter): Minimal wallet adapter for connected-wallet flows. Only this property is mandatory. See Wallet Adapter.

Optional Properties (required by backend type)

  • apiKey (string): Your Bungee API key. Optional when using the default public backend. Required when using the dedicated backend URL.
  • baseUrl (string): API base URL. If not passed, the widget uses the public backend: https://public-backend.bungee.exchange/api/v1. See Base URL and API key / affiliate requirements.
  • affiliateId (string): For integrator tracking. Optional for the public backend. Required for the backend and dedicated URLs.
  • theme (Theme): Theming configuration. See Theme Configuration.
  • widgetTitle (string): Optional title shown in the widget header. Default is "Swap". Only set if you need to customize the header label.
  • rpcs (object): Custom RPC URLs (all optional)
    • solana (string): Solana RPC URL. Only needed if you want Solana support and pass getSolanaSigner.
    • eip155 (string): Custom Ethereum Mainnet RPC URL for transactions.
  • initialValues (object): Default values
    • fromChain (number): Default source chain ID
    • toChain (number): Default destination chain ID
    • inputTokens (string[]): Default input token addresses
    • outputTokens (string[]): Default output token addresses
    • amount (string[]): Default amounts
    • outputRatio (number[]): Output ratios
    • locale (SupportedLocale): UI locale (currently only "en-US")
    • sortPreference ("fast" | "best"): Route sorting preference
    • swapSlippage (number): Default slippage tolerance
  • supportedTokens (object): Restrict available tokens. See Token Configuration Details.
    • from (object): Tokens by chain ID for source. Structure: { [chainId: string]: Token[] }
    • to (object): Tokens by chain ID for destination. Structure: { [chainId: string]: Token[] }
  • supportedChains (object): Restrict available chains
    • from (number[]): Available source chains
    • to (number[]): Available destination chains
  • eventHandlers (EventHandlers): Event callbacks. See Event Handlers.
  • feeParams (object): Integrator fee configuration
    • feeTakerAddress (string): Wallet address that receives the fee
    • feeBps (number): Fee in basis points (for example 10 = 0.1%)
  • features (object): Feature flags
    • internalToasts (boolean): Show or hide internal toasts (default: true)
    • internalTxHistory (boolean): Show or hide transaction history (default: true)
    • internalInflight (boolean): Show or hide the inflight screen as a non-blocking toast (default: true)
    • autoRouting (boolean): Auto-routing feature (not implemented)
    • refuel (boolean): Refuel feature (not implemented)
  • postSwapAction (object): Customize the post-swap screen
    • ctaLabel (string): Label for the call-to-action button
    • ctaAction ((hash: string) => Promise<void>): Async action triggered when the CTA button is clicked
    • bannerAddon (ReactNode): Custom React element to render in the post-swap banner
    • bannerAddonClassNames (string): CSS class names for the banner addon container
    • onSwapCompleted ((hash: string) => void): Callback fired when a swap completes successfully
    • isPending (boolean): Whether the CTA action is in progress

Base URL and API key / affiliate requirements

The widget supports three backend URLs. Requirements for apiKey and affiliateId depend on which URL you use (or the default when you omit baseUrl):

| Base URL | apiKey | affiliateId | |----------|--------|-------------| | Public (default) — https://public-backend.bungee.exchange/api/v1 | Optional | Optional | | Backendhttps://backend.bungee.exchange/api/v1 | Optional | Required | | Dedicatedhttps://dedicated-backend.bungee.exchange/api/v1 | Required | Required |

  • If you do not pass baseUrl, the widget uses the public backend. No API key or affiliate ID is required.
  • For the backend URL, you must provide affiliateId in config; the widget will show a validation error otherwise.
  • For the dedicated URL, you must provide both apiKey and affiliateId; the widget will show a validation error if either is missing.
  • Using an unsupported or invalid baseUrl may result in runtime validation errors or API failures.

Wallet Adapter

The wallet object is the only host integration point the widget needs. You provide connected accounts and the network-specific wallet hooks you support; the widget handles the rest internally.

| Property | Type | Required | Description | |---|---|---|---| | accounts | AccountInfo[] | Yes | Connected wallet accounts | | getEVMWalletClient | (chainId: number) => Promise<WalletClient \| null> | EVM only | Returns a viem WalletClient for the requested chain | | getSolanaSigner | () => Promise<SolanaSigner \| null> | Solana only | Returns a Solana signer for signing transactions | | getTronWeb | () => TronWebLike \| undefined | Tron only | Returns the wallet-connected TronWeb instance for Tron transactions and deposit flows | | switchChain | (chainId: number, account?) => Promise<boolean> | Recommended for EVM | Switches the wallet's active EVM chain |

What the widget handles internally

When you provide getEVMWalletClient, the widget automatically implements:

  • sendTransaction (including EIP-5792 batched calls)
  • signTypedData
  • writeContract
  • readContract (via viem public clients)
  • getBalance (native + ERC-20)
  • getTransactionReceipt
  • getBytecode
  • getEnsAddress
  • getWalletCapabilities (EIP-5792)
  • getCallsStatus (EIP-5792)

When you provide getSolanaSigner and config.rpcs.solana, the widget additionally handles:

  • Solana transaction building and sending (VersionedTransaction with lookup tables)
  • SOL and SPL token balance fetching (including Token-2022)
  • Solana transaction receipt polling

When you provide getTronWeb, the widget additionally handles:

  • Tron transaction building, signing, and broadcasting (for deposit and direct-deposit flows)
  • TRX and TRC-20 balance and transaction receipt via the host-supplied TronWeb instance

accounts

An array of currently connected wallet accounts:

accounts: Array<{
  address: string;
  chainType: "EVM" | "SVM" | "TRON";
  chainId?: number;
  isConnected: boolean;
  connector?: {
    id?: string;
    name?: string;
    icon?: string;
  };
}>

getEVMWalletClient

Returns a viem WalletClient for the requested chain. The widget uses this to send transactions, sign typed data, write contracts, and query EIP-5792 capabilities.

getEVMWalletClient: (chainId: number) => Promise<WalletClient | null>

The return type is any in the adapter interface so hosts are free to use any viem version; the widget casts internally.

getSolanaSigner

Returns a Solana signer object. The widget builds the transaction internally (instructions, lookup tables, blockhash) and passes it to the signer. If the signer provides signAndSendTransaction, the widget prefers it; otherwise it falls back to signTransaction + sendRawTransaction via its internal Connection.

getSolanaSigner: () => Promise<{
  signAndSendTransaction?: (...args: any[]) => Promise<any>;
  signTransaction?: (...args: any[]) => Promise<any>;
} | null>

getTronWeb

Returns the wallet-connected TronWeb instance from your app. The widget uses it to build, sign, and broadcast Tron transactions for deposit and direct-deposit flows. The instance must implement the minimal TronWebLike interface (see type export). If you do not support Tron, omit this property.

getTronWeb: () => TronWebLike | undefined

switchChain

Switches the wallet's active EVM chain. The optional account parameter targets a specific wallet when multiple are connected.

Treat this as a success-or-throw contract in practice:

  • resolve when the chain switch succeeds
  • reject or throw if the switch is cancelled or fails
switchChain: (
  chainId: number,
  account?: { address?: string; chainType: "EVM" | "SVM" | "TRON" }
) => Promise<boolean>

Token Configuration Details

Token Interface

When using supportedTokens, tokens must follow this structure:

interface Token {
  address: string;
  chainId: number;
  decimals: number;
  logoURI: string;
  name: string;
  symbol: string;
  isVerified?: boolean; // Must be true to avoid warnings
}

Using supportedTokens

Important notes:

  • When supportedTokens are provided, the widget will not automatically set a default token.
  • To show a default source token, you must pass initialValues.fromChain and initialValues.inputTokens.
  • Set isVerified: true for tokens in supportedTokens to avoid warnings.
  • inputTokens addresses must match tokens from your supportedTokens.from[chainId] list.

Fetching Token Data

When using supportedTokens, you can fetch token data from the Bungee API endpoints:

  • /tokens/list: Returns a curated list of trending tokens (verified) or the complete token list
  • /tokens/search: Search for tokens by address, name, or symbol

Tokens fetched from these endpoints include the isVerified field. For detailed request and response formats, see the Bungee API token endpoints documentation.

Theme Configuration

Customize the widget appearance with the theme property:

const theme = {
  width: 420, // or "full" for full width
  borderRadius: "base", // "none" | "sm" | "base" | "md" | "lg"
  fonts: {
    primary: "Inter, sans-serif",
    secondary: "Roboto, sans-serif",
  },
  colors: {
    text: {
      primary: "#FFFFFF",
      secondary: "#A0A0A0",
      button: "#000000",
      theme: "#3B82F6",
      accent1: "#10B981",
      accent2: "#F59E0B",
      accent3: "#EF4444",
      accent4: "#8B5CF6",
    },
    bg: {
      layer1: "#1F2937",
      layer2: "#374151",
      layer3: "#4B5563",
      accent1: "#10B981",
      accent3: "#EF4444",
      accent4: "#8B5CF6",
      main: "#111827",
      theme: "#3B82F6",
    },
    border: {
      strong: "#6B7280",
      theme: "#3B82F6",
    },
    icon: {
      primary: "#FFFFFF",
      secondary: "#A0A0A0",
      theme: "#3B82F6",
    },
  },
};

Colors support both hex (#FFFFFF) and RGB (rgb(255, 255, 255)) formats.

Event Handlers

Handle user interactions and widget events:

const eventHandlers = {
  onFromTokenChange: (token: Token) => {
    console.log("Source token changed:", token);
  },
  onToTokenChange: (token: Token) => {
    console.log("Destination token changed:", token);
  },
  onFromChainChange: (chain: Chain) => {
    console.log("Source chain changed:", chain);
  },
  onToChainChange: (chain: Chain) => {
    console.log("Destination chain changed:", chain);
  },
  onEvent: (eventType: "success" | "error" | "warning", eventData: EventData) => {
    console.log("Widget event:", eventType, eventData);
  },
  onOpenWalletConnect: (network: "solana" | "eip155" | "tron") => {
    openWalletModal(network);
  },
  onSwapInitiated: (data: { chainId: number; hash: string; type: OrderFlowType }) => {
    console.log("Swap initiated:", data);
  },
  onTransactionStatusChange: (data: { requestHash: string; statusCode: number }) => {
    console.log("Transaction status:", data);
  },
  logEvent: (log: { event: Event; error: unknown; context?: Record<string, unknown> }) => {
    console.log("Analytics event:", log);
  },
  toggleExternalHistorySection: () => {
    toggleHistorySidebar();
  },
  showToast: (title, message, type, duration) => {
    // Display a custom toast notification
  },
};

Imperative API

The imperative API allows parent components to control widget state programmatically.

Use case example: when a user clicks a history item in a sidebar, the parent can navigate the widget to the inflight screen for that transaction.

import { useRef } from "react";
import { Bungee, type BungeeImperativeAPIType } from "@socket.tech/bungee";

export default function App() {
  const bungeeRef = useRef<BungeeImperativeAPIType>(null);

  const handleSetInflightData = (data: OrderData) => {
    bungeeRef.current?.setInflightData(data);
  };

  return <Bungee config={config} ref={bungeeRef} />;
}

Available method:

  • setInflightData(data: OrderData): Track pending transactions and navigate to inflight screen

Type Exports

import type {
  BungeeConfig,
  BungeeImperativeAPIType,
  WalletAdapter,
  TronWebLike,
} from "@socket.tech/bungee";

Migration from v0.25.x

What Changed

In v0.25.x (up to v0.25.4), the widget bundled its own wallet provider (wagmi + Reown/WalletConnect). You did not need to pass wallet configuration; the widget managed connections, chain switching, transactions, and contract reads internally.

In v1.0.0, the widget is wallet-provider-agnostic. Your app owns wallet connection state and UI, and Bungee only consumes the minimal adapter you pass through config.wallet.

| | v0.25.x | v1.0.0 | |---|---|---| | Wallet provider | Built-in (wagmi + Reown) | Your choice | | Config | apiKey only | wallet required; apiKey optional for default public backend | | Wallet connections | Widget handled internally | Host app handles via onOpenWalletConnect | | Blockchain reads | Widget handled internally | Widget handles internally via viem public clients | | Blockchain writes | Widget handled internally | Widget handles internally via getEVMWalletClient or getSolanaSigner |

Migration Checklist

  1. Remove old assumptions that the widget will open or manage wallets for you.
  2. Add QueryClientProvider above <Bungee />.
  3. Build wallet.accounts from your host wallet provider.
  4. Provide getEVMWalletClient for EVM support.
  5. Provide switchChain for EVM chain switching. Reject or throw if switching fails.
  6. Provide getSolanaSigner and rpcs.solana for Solana support.
  7. Implement eventHandlers.onOpenWalletConnect so the widget can ask your app to open the correct wallet modal.

Troubleshooting

  • React Query error or No QueryClient set Mount QueryClientProvider above <Bungee />.

  • Clicking connect does nothing Implement eventHandlers.onOpenWalletConnect.

  • Transactions fail because no wallet client is available for the selected chain Make sure getEVMWalletClient(chainId) returns a client for the requested chain, not only the currently active chain.

  • Chain switch handling feels inconsistent Make switchChain reject or throw on cancellation or failure instead of silently resolving unsuccessfully.

  • Solana actions fail immediately Mount Solana wallet-adapter providers higher in the app and pass both getSolanaSigner and rpcs.solana.

  • Tron deposit/direct-deposit fails or is unavailable Pass getTronWeb returning a TronWeb instance that implements TronWebLike, and include TRON accounts in wallet.accounts. If you do not need Tron, you can omit getTronWeb.

  • Widget has no styling Import @socket.tech/bungee/styles.css and @socket.tech/bungee/fonts.css.

Links