npm package: @mosaicag/swap-widget
Description: Self-contained swap widget for DeFi token swapping
Latest version: 2.0.1

# @mosaicag/swap-widget

Ready-to-embed swap widget for Movement ecosystem apps.

## Overview

`@mosaicag/swap-widget` gives you a complete swap UI out of the box:

- token input and output
- quote refresh and route summary
- slippage and liquidity source settings
- wallet submit flow with callbacks
- sensible Movement mainnet defaults

If you want a swap experience that works quickly with minimal setup, this package is the entry point.

## Installation

Install the widget package:

```bash
npm install @mosaicag/swap-widget
```

```bash
pnpm add @mosaicag/swap-widget
```

```bash
yarn add @mosaicag/swap-widget
```

## Requirements

Your app should already have:

- `react` and `react-dom` 18+
- a wallet object compatible with `WalletStandard`
- access to the target network RPC and indexer if you want custom endpoints

The minimum wallet fields used by the swap flow are:

- `account`
- `signTransaction`
- `signAndSubmitTransaction`

## Quick Start

### 1. Import styles once

Import widget CSS in your app entry file.

`SwapWidget` already imports `@mosaicag/common-ui/styles` internally.

```tsx
import '@mosaicag/swap-widget/dist/index.css';
```

### 2. Render the widget

`wallet` is the only required prop.

```tsx
import { SwapWidget } from '@mosaicag/swap-widget';
import '@mosaicag/swap-widget/dist/index.css';

type Props = {
  wallet: any;
};

export function SwapSection({ wallet }: Props) {
  return <SwapWidget wallet={wallet} />;
}
```

### 3. Handle connect wallet action

When the wallet is not connected, the main button becomes `Connect Wallet`.

```tsx
<SwapWidget wallet={wallet} onConnectWallet={() => wallet.connect?.()} />
```

## Examples

### Minimal Example

Use built-in defaults for Movement mainnet:

```tsx
import { SwapWidget } from '@mosaicag/swap-widget';
import '@mosaicag/swap-widget/dist/index.css';

export function SwapCard({ wallet }: { wallet: any }) {
  return <SwapWidget wallet={wallet} />;
}
```

### Example With Connect Action

```tsx
import { SwapWidget } from '@mosaicag/swap-widget';
import '@mosaicag/swap-widget/dist/index.css';

export function SwapCard({
  wallet,
  connectWallet,
}: {
  wallet: any;
  connectWallet: () => void;
}) {
  return (
    <SwapWidget
      wallet={wallet}
      onConnectWallet={connectWallet}
      className='w-full max-w-[450px]'
    />
  );
}
```

### Full Config Example

This is the recommended pattern when you want explicit control over endpoints, gas sponsorship, callbacks, and the initial token pair.

```tsx
import { SwapWidget } from '@mosaicag/swap-widget';
import '@mosaicag/swap-widget/dist/index.css';

type SwapContainerProps = {
  wallet: any;
  connectWallet: () => void;
  rpcUrl: string;
  indexerUrl: string;
  bffUrl: string;
  gasStationUrl?: string;
  gasStationId?: string;
  rpcAuthorizationKey?: string;
  defaultTokenIn?: string;
  defaultTokenOut?: string;
};

export function SwapContainer({
  wallet,
  connectWallet,
  rpcUrl,
  indexerUrl,
  bffUrl,
  gasStationUrl,
  gasStationId,
  rpcAuthorizationKey,
  defaultTokenIn,
  defaultTokenOut,
}: SwapContainerProps) {
  return (
    <SwapWidget
      wallet={wallet}
      rpcUrl={rpcUrl}
      indexerUrl={indexerUrl}
      rpcAuthorizationKey={rpcAuthorizationKey}
      bffUrl={bffUrl}
      useBffSession
      defaultTokenIn={defaultTokenIn}
      defaultTokenOut={defaultTokenOut}
      useGasSponsor={Boolean(gasStationUrl && gasStationId)}
      gasStationUrl={gasStationUrl}
      gasStationId={gasStationId}
      onConnectWallet={connectWallet}
      onChangeTokenPair={(tokenIn, tokenOut) => {
        console.log('pair changed', { tokenIn, tokenOut });
      }}
      onTxSubmit={({ hash, metadata }) => {
        console.log('swap submitted', hash, metadata);
      }}
      onTxFail={({ error, metadata, hash }) => {
        console.error('swap failed', { error, metadata, hash });
      }}
      className='w-full max-w-[450px]'
    />
  );
}
```

### Example With URL Synced Pair

```tsx
<SwapWidget
  wallet={wallet}
  defaultTokenIn={tokenInFromUrl}
  defaultTokenOut={tokenOutFromUrl}
  onChangeTokenPair={(tokenIn, tokenOut) => {
    setTokenInInUrl(tokenIn);
    setTokenOutInUrl(tokenOut);
  }}
/>
```

## Theme

`SwapWidget` supports a `theme` prop for color customization.

```tsx
import { SwapWidget, type CustomThemeType } from '@mosaicag/swap-widget';

const widgetTheme: CustomThemeType = {
  primaryColor: '#53CBF3',
  secondaryColor: '#A8E6FA',
  textColor: '#000000',
  primaryBackgroundColor: '#FFFFFF',
  secondaryBackgroundColor: '#F5F5F5',
  borderColor: '#53CBF3',
  showBorder: true,
};

<SwapWidget wallet={wallet} theme={widgetTheme} />;
```

### Theme Fields

- `primaryColor`: primary accent color used by actions/highlights.
- `secondaryColor`: secondary accent color used by supporting states.
- `textColor`: base text color.
- `primaryBackgroundColor`: main surface background.
- `secondaryBackgroundColor`: secondary surface background.
- `borderColor`: border color for themed surfaces.
- `showBorder`: toggles themed borders on/off.
- `mode`: optional (`light` | `dark`) for future compatibility.

### Theme Notes

- Accepts hex (`#RRGGBB` / `#RGB`) and rgb/rgba-like values.
- If `secondaryColor` is not set, it may fall back to `textColor`, then `primaryColor`.
- For best results, set both `primaryColor` and `secondaryColor` explicitly.

## Default Behavior

If you do not pass custom values, the widget uses these defaults:

- `rpcUrl`: `https://mainnet.movementnetwork.xyz/v1`
- `indexerUrl`: `https://indexer.mainnet.movementnetwork.xyz/v1/graphql`
- `bffUrl`: `https://bff.mosaic.ag/api/v1`
- `useBffSession`: `false`
- `networkType`: `mainnet`
- `minGasPreserve`: `0.2`

## Props

| Prop                  | Type                                  | Required | Default                        | Description                                                   |
| --------------------- | ------------------------------------- | -------- | ------------------------------ | ------------------------------------------------------------- |
| `wallet`              | `WalletStandard`                      | Yes      | -                              | Wallet used for signing and submitting transactions.          |
| `className`           | `string`                              | No       | `undefined`                    | Extra classes for the widget root.                            |
| `useGasSponsor`       | `boolean`                             | No       | `false`                        | Enables gas sponsorship flow.                                 |
| `gasStationId`        | `string`                              | No       | `undefined`                    | Gas station ID when sponsorship is enabled.                   |
| `gasStationUrl`       | `string`                              | No       | `undefined`                    | Gas station URL when sponsorship is enabled.                  |
| `rpcUrl`              | `string`                              | No       | Movement mainnet RPC           | Custom RPC endpoint.                                          |
| `indexerUrl`          | `string`                              | No       | Movement mainnet indexer       | Custom indexer endpoint.                                      |
| `rpcAuthorizationKey` | `string`                              | No       | `undefined`                    | Optional auth key for RPC requests.                           |
| `queryClient`         | `QueryClient`                         | No       | Internal instance              | Pass your own client if you want shared cache behavior.       |
| `bffUrl`              | `string`                              | No       | `https://bff.mosaic.ag/api/v1` | Backend URL for token and price data.                         |
| `useBffSession`       | `boolean`                             | No       | `false`                        | Enables cookie session for BFF requests.                      |
| `networkType`         | `NetworkType`                         | No       | `NetworkType.MAINNET`          | Target network.                                               |
| `defaultTokenIn`      | `string`                              | No       | Widget default                 | Initial sell token.                                           |
| `defaultTokenOut`     | `string`                              | No       | Widget default                 | Initial buy token.                                            |
| `onChangeTokenPair`   | `(tokenIn, tokenOut) => void`         | No       | `undefined`                    | Called when the selected pair changes.                        |
| `onConnectWallet`     | `() => void`                          | No       | `undefined`                    | Called when the user clicks connect.                          |
| `onTxSubmit`          | `({ hash, metadata }) => void`        | No       | `undefined`                    | Called when a transaction hash is received.                   |
| `onTxFail`            | `({ error, metadata, hash }) => void` | No       | `undefined`                    | Called when transaction submit fails.                         |
| `onTxSuccess`         | `({ hash, metadata }) => void`        | No       | `undefined`                    | Called when the widget reports a successful transaction flow. |
| `minGasPreserve`      | `number`                              | No       | `0.2`                          | Native token amount reserved for gas.                         |
| `theme`               | `CustomThemeType`                     | No       | `undefined`                    | Overrides widget color tokens and themed surfaces.            |

## Transaction Metadata

`onTxSubmit`, `onTxSuccess`, and `onTxFail` work with swap metadata that typically includes:

- source token
- destination token
- source amount
- destination amount
- transaction hash when available

Common use cases:

- activity history
- analytics
- toast notifications
- updating URL or local state after submit

## Next.js

The package is client-side (`"use client"`). Render `SwapWidget` inside a client component.

## Troubleshooting

- Widget is unstyled:
  Import `@mosaicag/swap-widget/dist/index.css` once in your app entry.
- The button always shows `Connect Wallet`:
  Make sure `wallet.account` is available after connecting.
- Quote requests fail:
  Check `rpcUrl`, `indexerUrl`, and `bffUrl`.
- Sponsored transactions do not work:
  Set `useGasSponsor`, `gasStationId`, and `gasStationUrl` together.
- Some themed states look darker/lighter than expected:
  Set both `primaryColor` and `secondaryColor` in `theme` to avoid fallback surprises.