@mosaicag/swap-widget
v2.0.1
Published
Self-contained swap widget for DeFi token swapping
Readme
@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:
npm install @mosaicag/swap-widgetpnpm add @mosaicag/swap-widgetyarn add @mosaicag/swap-widgetRequirements
Your app should already have:
reactandreact-dom18+- 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:
accountsignTransactionsignAndSubmitTransaction
Quick Start
1. Import styles once
Import widget CSS in your app entry file.
SwapWidget already imports @mosaicag/common-ui/styles internally.
import '@mosaicag/swap-widget/dist/index.css';2. Render the widget
wallet is the only required prop.
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.
<SwapWidget wallet={wallet} onConnectWallet={() => wallet.connect?.()} />Examples
Minimal Example
Use built-in defaults for Movement mainnet:
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
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.
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
<SwapWidget
wallet={wallet}
defaultTokenIn={tokenInFromUrl}
defaultTokenOut={tokenOutFromUrl}
onChangeTokenPair={(tokenIn, tokenOut) => {
setTokenInInUrl(tokenIn);
setTokenOutInUrl(tokenOut);
}}
/>Theme
SwapWidget supports a theme prop for color customization.
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
secondaryColoris not set, it may fall back totextColor, thenprimaryColor. - For best results, set both
primaryColorandsecondaryColorexplicitly.
Default Behavior
If you do not pass custom values, the widget uses these defaults:
rpcUrl:https://mainnet.movementnetwork.xyz/v1indexerUrl:https://indexer.mainnet.movementnetwork.xyz/v1/graphqlbffUrl:https://bff.mosaic.ag/api/v1useBffSession:falsenetworkType:mainnetminGasPreserve: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.cssonce in your app entry. - The button always shows
Connect Wallet: Make surewallet.accountis available after connecting. - Quote requests fail:
Check
rpcUrl,indexerUrl, andbffUrl. - Sponsored transactions do not work:
Set
useGasSponsor,gasStationId, andgasStationUrltogether. - Some themed states look darker/lighter than expected:
Set both
primaryColorandsecondaryColorinthemeto avoid fallback surprises.
