npm package: @rash2x/bridge-widget
Description: Cross-chain bridge widget powered by Stargate Protocol with multi-chain wallet support
Author: EVAA Finance
Latest version: 0.8.13

# EVAA Bridge Widget

A production-ready cross-chain bridge widget powered by Stargate Protocol with comprehensive multi-chain wallet support (Ethereum, TON, Tron).

![npm version](https://img.shields.io/npm/v/@evaa/bridge-widget)
![license](https://img.shields.io/npm/l/@evaa/bridge-widget)

## Features

- 🔗 **Multi-Chain Support**: Ethereum, TON, Tron, and other EVM chains
- 🦊 **Wallet Integration**: MetaMask, TonConnect, TronLink, WalletConnect
- 💱 **Real-time Quotes**: Get instant cross-chain swap quotes via Stargate Protocol
- ⚡ **Transaction Management**: Built-in transaction monitoring and status tracking
- 📊 **Balance Tracking**: Real-time wallet balance updates
- 🎨 **Themeable**: Light/dark mode with customizable styling
- 🌐 **i18n**: Built-in internationalization (EN/RU, easily extensible)
- 📱 **Responsive**: Mobile-friendly design

## Installation

```bash
npm install @evaa/bridge-widget
# or
yarn add @evaa/bridge-widget
# or
pnpm add @evaa/bridge-widget
```

### Peer Dependencies

Install required peer dependencies:

```bash
npm install react react-dom @tanstack/react-query
```

For specific chain support, install additional peer dependencies:

```bash
# For Ethereum/EVM chains
npm install wagmi ethers connectkit

# For TON
npm install @tonconnect/ui-react @ton/core @ton/crypto @ton/ton

# For Tron (with specific WalletConnect versions)
npm install @tronweb3/tronwallet-adapter-react-hooks @tronweb3/tronwallet-adapters tronweb @walletconnect/universal-provider@^2.23.0 @walletconnect/modal@^2.7.0
```

> **⚠️ Important:** When using TRON WalletConnect support, ensure you install the exact versions specified above (`@walletconnect/modal@^2.7.0` and `@walletconnect/universal-provider@^2.23.0`) to avoid runtime errors like `this.client.core.relayer.publishCustom is not a function`.

### Version Lock (Recommended)

To prevent version conflicts, add these overrides to your `package.json`:

```json
{
  "overrides": {
    "@walletconnect/modal": "^2.7.0",
    "@walletconnect/universal-provider": "^2.23.0"
  }
}
```

For **yarn**, use `resolutions` instead of `overrides`. For **pnpm**, add to your `.npmrc`:

```
@walletconnect/modal=^2.7.0
@walletconnect/universal-provider=^2.23.0
```

### Required shadcn/ui Components

This library requires certain shadcn/ui components to be installed in your project. The library does **not bundle** these components to avoid duplication and allow you to use your own styled versions.

**Required components:** `accordion`, `button`, `card`, `dialog`, `input`, `skeleton`, `switch`, `tooltip`

Install them using shadcn CLI:

```bash
npx shadcn@latest add accordion button card dialog input skeleton switch tooltip
```

**Important:** Your project must have the following path aliases configured:

- `@/components/ui` - for UI components
- `@/lib/utils` - for the `cn` utility function

For detailed setup instructions, see [SHADCN_COMPONENTS.md](./SHADCN_COMPONENTS.md).

## Quick Start

### 1. Basic Setup

```tsx
import { animated, useSpring } from '@react-spring/web';
import { useTranslation } from 'react-i18next';
import { WalletProvider } from '@tronweb3/tronwallet-adapter-react-hooks';
import { TronLinkAdapter } from '@tronweb3/tronwallet-adapters';
import { ConnectKitProvider } from 'connectkit';
import { EvaaBridge } from '@rash2x/bridge-widget';
import { TransactionConfirmVector } from '@/components/vectors/TransactionConfirm';
import { TransactionProgressVector } from '@/components/vectors/TransactionProgress';
import { TransactionSuccessVector } from '@/components/vectors/TransactionSuccess';
import Fireworks from 'react-canvas-confetti/dist/presets/fireworks';
import { TransactionFailedVector } from '@/components/vectors/TransactionFailed';
import { useMemo } from 'react';
import { WagmiProvider, createConfig, http } from 'wagmi';
import { mainnet, arbitrum, polygon, base, bsc } from 'wagmi/chains';
import { injected, walletConnect, metaMask } from 'wagmi/connectors';
import { Card } from '@/components/ui/card';

const walletConnectProjectId = import.meta.env.VITE_WALLETCONNECT_PROJECT_ID || '5e81fa2f7739ab20482103c77a1b5cbf';

const config = createConfig({
  chains: [mainnet, arbitrum, polygon, base, bsc],
  connectors: [injected(), metaMask(), walletConnect({ projectId: walletConnectProjectId })],
  transports: {
    [mainnet.id]: http(),
    [arbitrum.id]: http(),
    [polygon.id]: http(),
    [base.id]: http(),
    [bsc.id]: http()
  }
});

export const BridgePage = () => {
  const { t, i18n } = useTranslation();
  const [props] = useSpring(() => ({
    from: { opacity: 0 },
    to: { opacity: 1 }
  }));

  const tronAdapters = useMemo(() => [new TronLinkAdapter()], []);

  const transactionIcons = useMemo(
    () => ({
      confirm: (
        <>
          <TransactionConfirmVector />
          <div className="on-circle on-circle-confirm-small under-noise"></div>
          <div className="on-circle on-circle-confirm-big under-noise"></div>
        </>
      ),
      progress: (
        <>
          <TransactionProgressVector className="progress-rocket" />
          <div className="on-circle on-circle-progress-small under-noise"></div>
          <div className="on-circle on-circle-progress-big under-noise"></div>
          <div className="meteors-container under-noise">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
          </div>
        </>
      ),
      success: (
        <>
          <TransactionSuccessVector />
          <Fireworks
            autorun={{
              speed: 3,
              duration: 1000,
              delay: 300
            }}
          />
          <div className="on-circle on-circle-success-small under-noise"></div>
          <div className="on-circle on-circle-success-big under-noise"></div>
        </>
      ),
      failed: (
        <>
          <TransactionFailedVector />
          <div className="on-circle on-circle-failed-small under-noise"></div>
          <div className="on-circle on-circle-failed-big under-noise"></div>
        </>
      )
    }),
    []
  );

  return (
    <animated.div style={props} className="space-y-4 pb-5 overflow-auto">
      <Card className="bg-master rounded-lg py-6 px-5 md:grid md:grid-cols-2 gap-8 lg:gap-10">
        <header className="px-5 space-y-3 md:px-0">
          <h1 className="font-display font-black shrink-0 text-5xl">{t('bridge')}</h1>
          <p className="text-sm text-muted-foreground">{t('bridgeDescription')}</p>
        </header>
        <WagmiProvider config={config}>
          <ConnectKitProvider>
            <WalletProvider adapters={tronAdapters} disableAutoConnectOnLoad={true}>
              <EvaaBridge defaultLanguage={i18n.language} transactionIcons={transactionIcons} />
            </WalletProvider>
          </ConnectKitProvider>
        </WagmiProvider>
      </Card>
    </animated.div>
  );
};
```

### 2. With Event Handlers and Language

```tsx
<EvaaBridge
  defaultLanguage="ru" // Set default language (en, ru)
  onSwapSuccess={(data) => {
    console.log("Swap completed:", data);
  }}
  onSwapError={(error) => {
    console.error("Swap failed:", error);
  }}
  onInitialized={() => {
    console.log("Bridge initialized");
  }}
  onDataUpdate={(data) => {
    console.log("Bridge data updated:", data);
  }}
/>
```

## Props

### EvaaBridgeProps

| Prop              | Type                                        | Description                                                             |
| ----------------- | ------------------------------------------- | ----------------------------------------------------------------------- |
| `className`       | `string`                                    | Optional CSS class for custom styling                                   |
| `defaultLanguage` | `string`                                    | Language for the widget UI (default: `'en'`). Supported: `'en'`, `'ru'` |
| `tonClient`       | `TonClient`                                 | Optional TON client instance                                            |
| `tonApiKey`       | `string`                                    | Optional TON API key                                                    |
| `onInitialized`   | `() => void`                                | Callback when bridge is initialized                                     |
| `onSwapStart`     | `(data: SwapStartData) => void`             | Callback when swap starts                                               |
| `onSwapSuccess`   | `(data: SwapSuccessData) => void`           | Callback when swap succeeds                                             |
| `onSwapError`     | `(error: SwapErrorData) => void`            | Callback when swap fails                                                |
| `onDataUpdate`    | `(data: BridgeExternalData) => void`        | Unified callback with chains/tokens/url params and quote details        |

### Bridge Data Callback

`onDataUpdate` fires whenever the user changes the amount, token, chains or when a new quote arrives.  
The `BridgeExternalData` payload includes:

- `fromChain` / `toChain` – currently selected networks
- `sourceToken` / `destinationToken` – token metadata per chain
- `amount` & `urlParams` – current form state (ready to persist in URL/router)
- `quoteDetails` – parsed amounts, min received, and fee breakdown (no raw quote exposure)

This makes it easy to persist widget state, update analytics, or show custom UI in a host app with a single subscription.  
If you prefer to pull the same snapshot from your own components (without using the callback) you can call the exported `useBridgeExternalData` hook directly.

### Theme Customization

Customize the widget's appearance by overriding CSS variables in your own stylesheet:

```css
:root {
  --primary: #0095f9; /* Primary brand color */
  --background: #ffffff; /* Background color */
  --foreground: #171717; /* Text color */
  --card: #f2f2f2; /* Card background */
  --border: #00000029; /* Border color */
  --radius: 0.625rem; /* Border radius */
  /* ... see dist/styles.css for all available variables */
}

[data-theme="dark"] {
  --primary: #5200ff;
  --background: #000000;
  --foreground: #ffffff;
  /* ... dark theme overrides */
}
```

## Supported Chains

- Ethereum (Mainnet)
- Arbitrum
- Polygon
- Base
- BNB Chain
- TON (The Open Network)
- Tron

## API Integration

The widget integrates with Stargate Protocol API for:

- Cross-chain token swaps
- Real-time quotes
- Transaction routing
- Fee estimation

## TypeScript

The package is written in TypeScript and includes full type definitions.

```tsx
import type { EvaaBridgeProps, Chain, Token } from "@evaa/bridge-widget";
```

## Development

```bash
# Install dependencies
npm install

# Run development server
npm run dev

# Build library
npm run build:lib

# Lint
npm run lint
```

## Troubleshooting

### WalletConnect Error: `this.client.core.relayer.publishCustom is not a function`

This error occurs due to version conflicts with WalletConnect packages. To fix:

1. **Ensure exact versions are installed**:
   ```bash
   npm install @walletconnect/modal@^2.7.0 @walletconnect/universal-provider@^2.23.0
   ```

2. **Add package overrides** to your `package.json`:
   ```json
   {
     "overrides": {
       "@walletconnect/modal": "^2.7.0",
       "@walletconnect/universal-provider": "^2.23.0"
     }
   }
   ```

3. **Delete `node_modules` and lock file**, then reinstall:
   ```bash
   rm -rf node_modules package-lock.json
   npm install
   ```

4. **For yarn users**, use `resolutions` instead of `overrides`:
   ```json
   {
     "resolutions": {
       "@walletconnect/modal": "^2.7.0",
       "@walletconnect/universal-provider": "^2.23.0"
     }
   }
   ```

5. **For pnpm users**, add to `.npmrc`:
   ```
   @walletconnect/modal=^2.7.0
   @walletconnect/universal-provider=^2.23.0
   ```

### Other Common Issues

- **Missing peer dependencies**: Check that all required peer dependencies are installed for your chain (see Installation section)
- **shadcn/ui component errors**: Ensure all required shadcn components are installed (see Required shadcn/ui Components)
- **Theme not working**: Make sure you have CSS variables configured properly (see Theme Customization)

## Contributing

Contributions are welcome! Please open an issue or submit a pull request.

## License

MIT © EVAA Finance

## Links

- [GitHub Repository](https://github.com/evaa-finance/bridge-widget)
- [Stargate Protocol](https://stargate.finance)
- [EVAA Finance](https://evaa.finance)

## Support

For issues and questions:

- GitHub Issues: https://github.com/evaa-finance/bridge-widget/issues
- Email: support@evaa.finance