Skip to main content
Version: 3.0.0

Getting Started with the Swap Widget

This guide walks you through the steps to embed the swap widget in your web3 decentralized application (dApp). With the swap widget, your users can trade tokens on the Uniswap Protocol without leaving your dApp!

Here’s a live preview of the swap widget. Please note that wallet connect is not supported here in the documentation. Your app will be responsible for providing a method to connect a wallet.

With the swap widget, your users can trade for any ERC-20 token without leaving your app! Example use cases include:

  • Building a custom frontend for the Uniswap Protocol
  • Swapping assets in a DeFi application
  • Acquiring a token to participate in your web3 community (e.g. FWB or a gaming token)
  • Converting to the required currency for an NFT purchase (e.g. WETH)

You can make the widget feel like a native part of your app by customizing the colors, font, and token list to match your app theme. This guide will teach you how.

Requirements​

The swap widget is a React component that can be easily imported into any React project. It supports trading on all networks where the Uniswap Protocol is deployed: Ethereum, Arbitrum, Optimism, and Polygon.

The swap widget is designed to work out of the box. Only one parameter is strictly required and that is a web3 provider. Additionally, a JSON RPC Endpoint is strongly recommended as described below. Additional optional parameters are available to customize the appearance and performance of the swap widget to fit your unique use case.

Web3 Provider​

The swap widget requires a web3 provider to fetch balances and submit transactions through the user’s connected wallet. If you’re building a dApp, you probably have a web3 provider already. Both the ethers and web3.js provider objects are compatible with the widget, as is any EIP-1193 provider. You can pass this directly into the provider prop.

If you don’t have a web3 provider yet, you can add a wallet connect flow to your app by using a library such as web3-react, BlockNative’s Onboard, or Aragon’s useWallet(). In a future release, we may make this wallet connect functionality available directly in the widget. If that would be useful for you, please file a feature request!

The widget will match the network currently selected by the user. If the user switches networks in your app or in their wallet, that change will propagate to the widget as well. If the user connects to a network that is not supported by the swap widget, the widget will gracefully disable itself.

JSON-RPC Endpoint​

We strongly recommend you provide a JSON-RPC endpoint URI in the widget’s jsonRpcEndpoint prop. The widget will use this endpoint to fetch on-chain data and submit transactions for signature.

If your dApp already has a JSON RPC endpoint, you can pass that in the jsonRpcEndpoint prop.

If you don’t yet have a JSON RPC endpoint, you can easily create one with services like Infura or Alchemy.

If you choose not to provide a JSON-RPC endpoint, the widget will be disabled until the user connects a wallet. The user will not be able to interact with the widget or fetch a price quote until a wallet is connected. Thus, it is strongly recommended that you provide your own JSON-RPC endpoint.

After the user connects a wallet, the widget will use the JSON-RPC provided by the wallet when possible.

Installing the Widgets Library​

To get started, install the widgets library using npm or Yarn. If you don’t already use it, you’ll need to install react-redux as well.

npm install --save @uniswap/widgets react-redux

Adding the Swap Widget to Your App​

Next, embed the React component in your application. Pass along the provider and jsonRpcEndpoint parameters.

import { SwapWidget } from '@uniswap/widgets'
import '@uniswap/widgets/fonts.css'

// Web3 provider as described in the requirements above
import { provider } from './your/provider'

// Infura endpoint
const jsonRpcEndpoint = 'https://mainnet.infura.io/v3/<YOUR_INFURA_PROJECT_ID>'

function App() {
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint}
/>
</div>
}

That’s it! You should now see a fully functional swap widget on your site. The widget is self-contained and gracefully handles all interactions with the Uniswap Protocol. It leverages the Auto Router to compute the best price across all Uniswap v2 and v3 pools.

Create React App V4

All code snippets will work seamlessly if you use Next.js or Create React App V5. However, if you’re using Create React App V4, you’ll need to use the following import statements instead:

import { SwapWidget } from '@uniswap/widgets/dist/index.js'
import '@uniswap/widgets/dist/fonts.css'

Customizing the Swap Widget

You can set optional parameters to tailor the appearance and functionality of the swap widget to fit your dApp.

Customizing the Width​

The swap widget has a fixed height of 348px and a default width of 360px. You cannot modify the height of the widget. You can modify the width up to a minimum width of 272px.

You can customize the width by passing a number (of pixels) or a valid CSS width to the width prop of the widget.

import { SwapWidget } from '@uniswap/widgets'
import '@uniswap/widgets/fonts.css'

function App() {
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint}
width={360} // Custom width in pixels
/>
</div>
}

For example:

  • width={360} sets the width to 360 pixels
  • width="100%" sets the width to dynamically fill 100% of the parent container
  • width="20em" sets the width to 20 * 16 = 320 pixels because 16px is the base font-size of the widget

The recommended and default width is 360 pixels.

Customizing the Theme​

You can customize the colors, font, and border radius of the swap widget to match the look and feel of your dApp. You can also toggle between light and dark modes. This section explains how to customize each attribute of the widget with your own theme.

All attributes below are color codes, except fontFamily (string), borderRadius (number between 0 and 1), and tokenColorExtraction(boolean). The next two sections show code examples using these attributes.

Check out examples of the swap widget, and the Figma file if you want to mock it up first!

Swap Widget Theme AttributesSwap Widget Theme AttributesSwap Widget Theme ExampleSwap Widget Theme Example

Overriding Attributes​

You can override specific attributes of the widget by creating a Theme object and defining the properties you wish to override. Any properties left undefined will fallback to the default theme. For example, here is a simple Theme that removes the border radius and sets a custom font family.

import { Theme, SwapWidget } from '@uniswap/widgets'

// Define a custom theme to override default attributes
const theme: Theme = {
borderRadius: 0,
fontFamily: '"Helvetica"',
}

function App() {
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint}
theme={theme}
/>
</div>
}

Please note that the borderRadius attribute is a multiplier from 0 to 1 of how much radius to apply. Since the widget uses different values of border radius (e.g. internal edges have tighter radii than external edges), borderRadius will apply your multiplier value on all instances so that the border radii still look proportionally correct.

Importing Fonts

The swap widget fonts must be imported explicitly with import '@uniswap/widgets/fonts.css'. However, if you’re overriding the swap widget fonts with your own, or with a default font such as Helvetica in the example above, you can remove this import statement.

Enabling Token Color Extraction​

By default, the background color of the output module will be set by the module attribute. You can optionally enable color extraction to flood the output module with the color of the selected output token. In the above example, DAI is the output token so the output module is flooded with DAI yellow.

To enable color extraction, set the tokenColorExtraction property to true in your Theme object.

import { Theme, SwapWidget } from '@uniswap/widgets'
import '@uniswap/widgets/fonts.css'

const enableColorExtractionTheme: Theme = {
tokenColorExtraction: true, // Enable color extraction of the output token
}

function App() {
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint}
theme={enableColorExtractionTheme}
/>
</div>
}

Toggling Light and Dark Mode​

The swap widget provides a default light theme and dark theme as a starting point. You can import each one and extend it to create your own theme. If your app can toggle between light and dark mode, you can propagate that state down to the widget by following the example below.

import { darkTheme, lightTheme, Theme, SwapWidget } from '@uniswap/widgets'
import '@uniswap/widgets/fonts.css'

let darkMode = true // Dynamically toggle dark mode on and off
function App() {
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint}
theme={darkMode ? darkTheme : lightTheme}
/>
</div>
}

Matching System Preference for Light and Dark Mode​

You can match the user’s system preference for light/dark mode by using the useSystemTheme hook. This will return the default widget light or dark theme according to the user’s system configuration. You can extend this base theme with further customizations, as you will see in the next section.

import { SwapWidget } from '@uniswap/widgets'
import '@uniswap/widgets/fonts.css'

function useSystemTheme() {
// Access
}

function App() {
const theme = useSystemTheme() // Get a theme that matches the user system preference
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint}
theme={theme}
/>
</div>
}

Extending Themes​

You can extend any theme with custom attributes. The below example extends the base light and dark themes with custom colors.

import { darkTheme, lightTheme, Theme, SwapWidget } from '@uniswap/widgets'
import '@uniswap/widgets/fonts.css'

const myLightTheme: Theme = {
...lightTheme, // Extend the lightTheme
accent: '#FF007A',
primary: '#000000',
secondary: '#565A69',
}

const myDarkTheme: Theme = {
...darkTheme, // Extend the darkTheme
accent: '#2172E5',
primary: '#FFFFFF',
secondary: '#888D9B',
}

let darkMode = true
function App() {
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint}
theme={darkMode ? myDarkTheme : myLightTheme}
/>
</div>
}

Customizing the Token Lists​

By default, the widget will use the Uniswap Labs default token list in the selector.

Customizing the Default Token List​

If you want to offer a different set of tokens in the widget, you can provide a custom tokenList parameter. You can browse popular token lists to find one that suits your needs and then pass the URL as a parameter.

import { SwapWidget } from '@uniswap/widgets'
import '@uniswap/widgets/fonts.css'

const CMC_TOKEN_LIST = 'https://api.coinmarketcap.com/data-api/v3/uniswap/all.json'

function App() {
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint}
tokenList={CMC_TOKEN_LIST} // Use the CoinMarketCap token list
/>
</div>
}

Alternatively, you can create your own token list. There are two ways to provide your own token list for the widget.

The first option is to create a full token list, host it at your own URI, and pass the URI as a parameter as in the above example. This option is recommended if you want to use the same token list in multiple places throughout your application or community.

The second and easiest option is to construct a custom token list inline as an array of tokens. The schema is equivalent to the tokens array from the tokenlist JSON schema. This option lets you skip deployment, hosting, and versioning of a full URI token list. Here is an example of an inline token list containing only the DAI, USDT, and USDC tokens (in addition to ETH which is always available, regardless of token list).

import { SwapWidget } from '@uniswap/widgets'
import '@uniswap/widgets/fonts.css'

// You can also pass a token list as JSON, as long as it matches the schema
const MY_TOKEN_LIST = [
{
"name": "Dai Stablecoin",
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"symbol": "DAI",
"decimals": 18,
"chainId": 1,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"
},
{
"name": "Tether USD",
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"decimals": 6,
"chainId": 1,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"
},
{
"name": "USD Coin",
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"symbol": "USDC",
"decimals": 6,
"chainId": 1,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
},
]

function App() {
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint}
tokenList={MY_TOKEN_LIST}
/>
</div>
}

Please note that the swap widget only enforces metadata validation on remotely hosted token lists, not on token list data passed as a literal value to the widget like in this example.

If you want to add Layer 2 tokens to the token list, you can add an extension field. See this GitHub issue for details.

Customizing the Default Input and Output Tokens​

You can set the defaultInputTokenAddress and the defaultOutputTokenAddress to pre-populate the input and output token fields respectively. This is useful when the widget appears in a context where you know which tokens the user is evaluating to trade. For example, if the widget appears on a page that displays the WBTC price chart, it would be helpful to pre-select WBTC as the output token in the widget.

If your page does not need any particular defaults, then the recommended default input token is the native asset of the active network (e.g. ETH) and no default output token is recommended. Since ETH does not have an address, you can pass 'NATIVE' as the parameter to set it as the default input or output token.

The following example sets the default input token to ETH and the default output token to WBTC.

import { SwapWidget } from '@uniswap/widgets'
import '@uniswap/widgets/fonts.css'

// Default token list from Uniswap
const UNISWAP_TOKEN_LIST = 'https://gateway.ipfs.io/ipns/tokens.uniswap.org'

// Use the native token of the connected chain as the default input token
const NATIVE = 'NATIVE' // Special address for native token

// WBTC as the default output token
const WBTC = '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599'

function App() {
<div className="Uniswap">
<SwapWidget
provider={provider}
jsonRpcEndpoint={jsonRpcEndpoint}
tokenList={UNISWAP_TOKEN_LIST}
defaultInputTokenAddress={NATIVE}
defaultOutputTokenAddress={WBTC}
/>
</div>
}

Understanding the Swap Widget States​

The widget has three main connectivity states depending if your app provides a JSON RPC endpoint and if the user has connected a wallet.

Swap Widget StatesSwap Widget States
  1. Before wallet connection, the widget has two possible states:
    1. If you did not provide a JSON-RPC, the swap widget will be disabled. Without a JSON-RPC endpoint the widget is unable to show token price data or fetch quotes. Without a web3 provider, the widget is unable to submit transactions. The widget will remain disabled until the user connects a wallet and you pass the provider and jsonRpcEndpoint parameters from the wallet into the widget.
    2. If your dApp provides a JSON-RPC, the widget will be interactive even prior to the user connecting a wallet. The widget will use your JSON-RPC endpoint to fetch token price data and provide trade quotes. For this reason, it is strongly recommended that your app provide a JSON RPC endpoint as an input parameter.
  2. After wallet connection, the widget will be fully functional. The user will be able to fetch trade quotes and submit swap transactions using the JSON-RPC endpoint and web3 provider from their connected wallet.
Questions?

Join the Discord channel to ask questions and get support from the Uniswap community.