Skip to main content

Swap tokens

The SWAP flow simplifies the process of swapping tokens on the Immutable zkEVM network.

Swap flowSwap flow

💡Allowlisted tokens
Only tokens that have been verified will be displayed on the widgets. To allowlist an ERC20 token please follow our Asset Verification procedure.
For additional questions, please contact our support team on Discord.
💡Geo-location restrictions
The swap UI may not be available in certain jurisdictions in development and production environments. This currently includes, United States, Australia and other jurisdictions subject to Immutable's compliance controls. Note the UI is available in all locations in a sandbox environment for testing purposes only.

Getting started

Once you have completed the setup, In order to initiate a flow call the mount() function passing in the id attribute of the target element you wish to mount the widget to, and the parameters required by the SWAP flow.

import { useEffect } from 'react';
import { checkout } from '@imtbl/sdk';

// Create a Checkout SDK instance
const checkoutSDK = new checkout.Checkout();

export function App() {
// Initialise the Commerce Widget
useEffect(() => {
(async () => {
// Create a factory
const factory = await checkoutSDK.widgets({
config: { theme: checkout.WidgetTheme.DARK, language: 'en' },
});

// Create a widget
const widget = factory.create(checkout.WidgetType.IMMUTABLE_COMMERCE);

// Mount a SWAP flow, optionally pass any SwapWidgetParams
widget.mount('mount-point', {
flow: checkout.CommerceFlowType.SWAP,
});
})();
}, []);

return <div id="mount-point" />;
}

Parameters

The mount() function will take in a commercewidgetswapFlowParams object.

Widget parameters

Parameters are treated as transient and will be reset after the widget is unmounted.

PropertyTypeDescription
flowCommerceFlowType.SWAPThe flow type to be used.
amountstringThe ERC20 token amount to swap.
fromTokenAddressstringThe address of the ERC20 contract swapping from. Use NATIVE to set the swapping from token to IMX. This will prefill the token field in the form.
toTokenAddressstringThe address of the ERC20 contract swapping to. Use NATIVE to set the swapping to token to IMX. This will prefill the token field in the form.
walletProviderNameWalletProviderNameThe wallet provider name to use for the swap widget.
autoProceedbooleanWhether the swap widget should display the form or automatically proceed with the swap.
directionSwapDirectionThe direction of the swap SwapDirection.FROM or SwapDirection.TO
showBackButtonbooleanWhether to show a back button on the first screen, on click triggers REQUEST_GO_BACK event
import { checkout } from '@imtbl/sdk';

// @ts-ignore
const widget = factory.create(checkout.WidgetType.IMMUTABLE_COMMERCE, {
config: { theme: checkout.WidgetTheme.DARK },
});

// When calling the mount function,
// set flow to SWAP and pass in the parameters to use
widget.mount('mount-point', {
flow: checkout.CommerceFlowType.SWAP,

// set amounts and tokens to swap from and to
amount: '100',
direction: checkout.SwapDirection.FROM,
fromTokenAddress: 'native', // IMX
toTokenAddress: '0x3B2d8A1931736Fc321C24864BceEe981B11c3c57', // USDC
});

Configuration

When you first create the widget, you can pass an optional configuration object to set it up. For example, passing in the theme will create the widget with that theme. If this is not passed the configuration will be set by default.

Widget configuration

Configuration will persist after the widget is unmounted. You can always update a widget's configuration later by calling the update() method.

PropertyDescription
SwapWidgetConfigurationThe configuration type to be used with the Swap Widget.
import { checkout } from '@imtbl/sdk';

// When creating the widget, pass in the configuration
// @ts-ignore
const widget = factory.create(checkout.WidgetType.IMMUTABLE_COMMERCE, {
config: {
language: 'en',
theme: checkout.WidgetTheme.DARK,

// swap flow configuration options
SWAP: {},
},
});

// Update the widget config by calling update()
// @ts-ignore
widget.update({
config: {
theme: checkout.WidgetTheme.LIGHT,
SWAP: {},
},
});

For more information on the configurations across all the Commerce Widgets (e.g. theme) review the Configuration section in our Setup page.

Events

The Commerce Widget emit events events when critical actions have been taken by the user or key states have been reached. Below is a table outlining the key events associated with a SWAP flow.

Event TypeDescriptionEvent Payload
CommerceEventType.CLOSEThe user clicked the close button on the widget. This should usually be wired up to call the widget's unmount() function.
CommerceEventType.SUCCESSThe user has completed the flow successfully.CommerceSuccessEvent
CommerceEventType.FAILUREThere has been an error in the flow.CommerceFailureEvent
import { checkout } from '@imtbl/sdk';

//@ts-ignore
const widget = factory.create(checkout.WidgetType.IMMUTABLE_COMMERCE, {
config: { theme: checkout.WidgetTheme.DARK },
});

// Add event listeners for the SWAP flow

widget.addListener(
checkout.CommerceEventType.SUCCESS,
(payload: checkout.CommerceSuccessEvent) => {
// narrow the event to a successfull swap event
if (payload.type === checkout.CommerceSuccessEventType.SWAP_SUCCESS) {
const { transactionHash } = payload.data;
console.log('successfull swap', transactionHash);
}
}
);

widget.addListener(
checkout.CommerceEventType.FAILURE,
(payload: checkout.CommerceFailureEvent) => {
// narrow the event to a failed swap event
if (payload.type === checkout.CommerceFailureEventType.SWAP_FAILED) {
const { reason, timestamp } = payload.data;
console.log('swap failed', reason, timestamp);
}
}
);

widget.addListener(checkout.CommerceEventType.CLOSE, () => {
widget.unmount();
console.log('widget closed');
});

// Remove event listeners for the SWAP flow

widget.removeListener(checkout.CommerceEventType.SUCCESS);
widget.removeListener(checkout.CommerceEventType.FAILURE);
widget.removeListener(checkout.CommerceEventType.CLOSE);

Sample code

This sample code gives you a good starting point for integrating the SWAP flow into your application and listening to its events.

import { useEffect, useState } from 'react';
import { checkout } from '@imtbl/sdk';

// create Checkout SDK
const checkoutSDK = new checkout.Checkout();

export function App() {
const [widget, setWidget] =
useState<checkout.Widget<typeof checkout.WidgetType.IMMUTABLE_COMMERCE>>();

// Initialise widget and mount a SWAP flow
useEffect(() => {
(async () => {
const factory = await checkoutSDK.widgets({
config: { theme: checkout.WidgetTheme.DARK, language: 'en' },
});

const checkoutWidget = factory.create(checkout.WidgetType.IMMUTABLE_COMMERCE);
setWidget(checkoutWidget);
})();
}, []);

// mount widget and add event listeners
useEffect(() => {
if (!widget) return;

// Swap 100 USDC worth of IMX
widget.mount('mount-point', {
flow: checkout.CommerceFlowType.SWAP,

amount: '100',
direction: checkout.SwapDirection.TO,
fromTokenAddress: 'native', // IMX
toTokenAddress: '0x3B2d8A1931736Fc321C24864BceEe981B11c3c57', // USDC
});

widget.addListener(
checkout.CommerceEventType.SUCCESS,
(payload: checkout.CommerceSuccessEvent) => {
const { type, data } = payload;
// detect successful swap
if (type === checkout.CommerceSuccessEventType.SWAP_SUCCESS) {
console.log('successfull swap', data.transactionHash);
}
}
);

widget.addListener(
checkout.CommerceEventType.FAILURE,
(payload: checkout.CommerceFailureEvent) => {
const { type, data } = payload;

// detect when user fails to swap, bridge, or on-ramp tokens
if (type === checkout.CommerceFailureEventType.SWAP_FAILED) {
console.log('failed to swap', data.reason);
}
}
);

// remove widget from view when closed
widget.addListener(checkout.CommerceEventType.CLOSE, () => {
widget.unmount();
});

// clean up event listeners
return () => {
widget.removeListener(checkout.CommerceEventType.SUCCESS);
widget.removeListener(checkout.CommerceEventType.CLOSE);
widget.removeListener(checkout.CommerceEventType.FAILURE);
};
}, [widget]);

return <div id="mount-point" />;
}