Add tokens
The ADD TOKENS flow simplifies the process of adding tokens to your wallet. This widget is powered by Squid.
Overview
The ADD TOKENS flow intelligently reads your users' balances and suggests the fastest and most cost-effective way to add the tokens they need, whether that's by bridging from another chain or swapping from a different token. Additionally, the ADD TOKENS flow offers On-ramp to fund your Immutable zkEVM wallet with fiat (e.g. EUR).
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 ADD_TOKENS
flow.
- React
- JavaScript
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 ADD TOKENS flow, optionally pass any AddTokensWidgetParams
widget.mount('mount-point', {
flow: checkout.CommerceFlowType.ADD_TOKENS,
});
})();
}, []);
return <div id="mount-point" />;
}
<html>
<head>
<!-- Load the SDK from jsdelivr -->
<script src="https://cdn.jsdelivr.net/npm/@imtbl/sdk/dist/browser/checkout/sdk.js"></script>
</head>
<body>
<div id="mount-point"></div>
<script>
// Initialize Checkout SDK
var checkout;
(async function () {
checkout = new ImmutableCheckout.Checkout();
const factory = await checkout.widgets({
config: { theme: ImmutableCheckout.WidgetTheme.DARK },
});
const widget = factory.create(
ImmutableCheckout.WidgetType.IMMUTABLE_COMMERCE
);
widget.mount('mount-point', {
flow: ImmutableCheckout.CommerceFlowType.ADD_TOKENS,
});
})();
</script>
</body>
</html>
Parameters
The mount()
function will take in a commercewidgetaddtokensflowparams object.
Parameters are treated as transient and will be reset after the widget is unmounted.
Property | Type | Description |
---|---|---|
flow | CommerceFlowType.ADD_TOKENS | The flow type to be used. |
showOnrampOption | boolean | Whether to show the onramp option. |
toTokenAddress | string | The address of the ERC20 token being added. Use NATIVE to set the token to IMX . This will prefill the token field in the form. |
toAmount | string | The amount of the token to add. |
toProvider | Web3Provider | The destination wallet provider, when requiring to lock destination of tokens. |
- React
- JavaScript
import { checkout, config, passport } from '@imtbl/sdk';
// Create Passport and Checkout instances
const passportInstance = new passport.Passport({
baseConfig: { environment: config.Environment.PRODUCTION },
clientId: 'CLIENT_ID',
redirectUri: 'https://localhost:3000/redirect',
logoutRedirectUri: 'http://localhost:3000/silent-logout',
audience: 'platform_api',
scope: 'openid offline_access email transact',
logoutMode: 'silent',
});
const checkoutInstance = new checkout.Checkout({
baseConfig: { environment: config.Environment.PRODUCTION },
passport: passportInstance,
});
// @ts-ignore
const widget = factory.create(checkout.WidgetType.IMMUTABLE_COMMERCE, {
config: { theme: checkout.WidgetTheme.DARK },
});
// Create Passport Provider
// @ts-ignore
const provider = await checkoutInstance.createProvider({
walletProviderName: checkout.WalletProviderName.PASSPORT,
});
// When calling the mount function,
// set flow to ADD_TOKENS and pass in the parameters to use
widget.mount('mount-point', {
flow: checkout.CommerceFlowType.ADD_TOKENS,
showOnrampOption: true,
// set add tokens parameters / 10 IMX
toTokenAddress: 'native', // IMX
toAmount: '10',
// set destination provider
toProvider: provider,
});
const { checkout, config, passport } = require('@imtbl/sdk');
// Create Passport and Checkout instances
const passportInstance = new passport.Passport({
baseConfig: { environment: config.Environment.PRODUCTION },
clientId: 'CLIENT_ID',
redirectUri: 'https://localhost:3000/redirect',
logoutRedirectUri: 'http://localhost:3000/silent-logout',
audience: 'platform_api',
scope: 'openid offline_access email transact',
logoutMode: 'silent',
});
const checkoutInstance = new checkout.Checkout({
baseConfig: { environment: config.Environment.PRODUCTION },
passport: passportInstance,
});
// Create the widget
const widget = factory.create(checkout.WidgetType.IMMUTABLE_COMMERCE, {
config: { theme: checkout.WidgetTheme.DARK },
});
// Create Passport Provider
const provider = await checkoutInstance.createProvider({
walletProviderName: checkout.WalletProviderName.PASSPORT,
});
// When calling the mount function,
// set flow to ADD_TOKENS and pass in the parameters to use
widget.mount('mount-point', {
flow: checkout.CommerceFlowType.ADD_TOKENS,
showOnrampOption: true,
// set add tokens parameters / 10 IMX
toTokenAddress: 'native', // IMX
toAmount: '10',
// set destination provider
toProvider: provider,
});
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.
Configuration will persist after the widget is unmounted. You can always update a widget's configuration later by calling the update()
method.
Property | Description |
---|---|
AddTokensWidgetConfiguration | The configuration type to be used with the Add Tokens Widget. |
- React
- JavaScript
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,
// add tokens flow configuration options
ADD_TOKENS: {},
},
});
// Update the widget config by calling update()
// @ts-ignore
widget.update({
config: {
theme: checkout.WidgetTheme.LIGHT,
ADD_TOKENS: {},
},
});
import { checkout } from '@imtbl/sdk';
// When creating the widget, pass in the configuration
const widget = factory.create(checkout.WidgetType.IMMUTABLE_COMMERCE, {
config: {
language: 'en',
theme: checkout.WidgetTheme.DARK,
// add tokens flow configuration options
ADD_TOKENS: {},
},
});
// Update the widget config by calling update()
widget.update({
config: {
theme: checkout.WidgetTheme.LIGHT,
ADD_TOKENS: {},
},
});
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 ADD_TOKENS
flow.
Event Type | Description | Event Payload |
---|---|---|
CommerceEventType.CLOSE | The user clicked the close button on the widget. This should usually be wired up to call the widget's unmount() function. | |
CommerceEventType.SUCCESS | The user has completed the flow successfully. | CommerceSuccessEvent |
CommerceEventType.FAILURE | There has been an error in the flow. | CommerceFailureEvent |
- React
- JavaScript
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 ADD TOKENS flow
widget.addListener(
checkout.CommerceEventType.SUCCESS,
(payload: checkout.CommerceSuccessEvent) => {
// narrow the event to a successfull add tokens event
if (payload.type === checkout.CommerceSuccessEventType.ADD_TOKENS_SUCCESS) {
const { transactionHash } = payload.data;
console.log('successfull add tokens', transactionHash);
}
}
);
widget.addListener(
checkout.CommerceEventType.SUCCESS,
(payload: checkout.CommerceSuccessEvent) => {
// narrow the event to a successfull add tokens connect event
if (payload.type === checkout.CommerceSuccessEventType.ADD_TOKENS_CONNECT_SUCCESS) {
const { providerType } = payload.data;
console.log('successfull add tokens connect', providerType);
}
}
);
widget.addListener(
checkout.CommerceEventType.FAILURE,
(payload: checkout.CommerceFailureEvent) => {
// narrow the event to a failed add tokens event
if (payload.type === checkout.CommerceFailureEventType.ADD_TOKENS_FAILED) {
const { reason } = payload.data;
console.log('add tokens failed', reason);
}
}
);
widget.addListener(checkout.CommerceEventType.CLOSE, () => {
widget.unmount();
console.log('widget closed');
});
// Remove event listeners for the ADD TOKENS flow
widget.removeListener(checkout.CommerceEventType.SUCCESS);
widget.removeListener(checkout.CommerceEventType.FAILURE);
widget.removeListener(checkout.CommerceEventType.CLOSE);
// Add event listeners for the ADD TOKENS flow
widget.addListener(ImmutableCheckout.CommerceEventType.SUCCESS, (payload) => {
// narrow the event to a successfull add tokens event
if (
payload.type === ImmutableCheckout.CommerceSuccessEventType.ADD_TOKENS_SUCCESS
) {
const { transactionHash } = payload.data;
console.log('successfull add tokens', transactionHash);
}
});
widget.addListener(ImmutableCheckout.CommerceEventType.FAILURE, (payload) => {
// narrow the event to a failed add tokens event
if (payload.type === ImmutableCheckout.CommerceFailureEventType.ADD_TOKENS_FAILED) {
const { reason } = payload.data;
console.log('add tokens failed', reason);
}
});
widget.addListener(ImmutableCheckout.CommerceEventType.CLOSE, () => {
widget.unmount();
console.log('widget closed');
});
// Remove event listeners for the ADD TOKENS flow
widget.removeListener(ImmutableCheckout.CommerceEventType.SUCCESS);
widget.removeListener(ImmutableCheckout.CommerceEventType.FAILURE);
widget.removeListener(ImmutableCheckout.CommerceEventType.CLOSE);
Sample code
This sample code gives you a good starting point for integrating the ADD TOKENS flow into your application and listening to its events.
- React
- JavaScript
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 ADD TOKENS 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;
// Add 10 IMX
widget.mount('mount-point', {
flow: checkout.CommerceFlowType.ADD_TOKENS,
showOnrampOption: true,
toTokenAddress: 'native', // IMX
toAmount: '10',
});
widget.addListener(
checkout.CommerceEventType.SUCCESS,
(payload: checkout.CommerceSuccessEvent) => {
const { type, data } = payload;
// detect successful add tokens
if (type === checkout.CommerceSuccessEventType.ADD_TOKENS_SUCCESS) {
console.log('successfull add tokens', data.transactionHash);
}
}
);
widget.addListener(
checkout.CommerceEventType.FAILURE,
(payload: checkout.CommerceFailureEvent) => {
const { type, data } = payload;
// detect when user fails to add tokens
if (type === checkout.CommerceFailureEventType.ADD_TOKENS_FAILED) {
console.log('failed to add tokens', 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" />;
}
<html>
<head>
<!-- Load the SDK from jsdelivr -->
<script src="https://cdn.jsdelivr.net/npm/@imtbl/sdk/dist/browser/checkout/sdk.js"></script>
</head>
<body>
<div id="mount-point"></div>
<script>
// Initialize Checkout SDK
var checkout;
var web3Provider;
(async function () {
checkout = new ImmutableCheckout.Checkout();
const factory = await checkout.widgets({
config: { theme: ImmutableCheckout.WidgetTheme.DARK, language: 'en' },
});
const widget = widgets.create(
ImmutableCheckout.WidgetType.IMMUTABLE_COMMERCE,
{
config: {
WALLET: { showNetworkMenu: false },
},
}
);
// Add 10 IMX
widget.mount('mount-point', {
flow: checkout.CommerceFlowType.ADD_TOKENS,
toAmount: '10',
toTokenAddress: 'native', // IMX
showOnrampOption: true,
});
widget.addListener(
ImmutableCheckout.CommerceEventType.SUCCESS,
(payload) => {
const { type, data } = payload;
// detect successful add tokens
if (
type === ImmutableCheckout.CommerceSuccessEventType.ADD_TOKENS_SUCCESS
) {
console.log('successfull add tokens', data.transactionHash);
}
}
);
widget.addListener(
ImmutableCheckout.CommerceEventType.FAILURE,
(payload) => {
const { type, data } = payload;
// detect failed add tokens
if (
type === ImmutableCheckout.CommerceFailureEventType.ADD_TOKENS_FAILED
) {
console.log('failed to add tokens', data.reason);
}
}
);
// remove widget from dom when closed
widget.addListener(ImmutableCheckout.CommerceEventType.CLOSE, () => {
widget.unmount();
});
// clean up event listeners
window.addEventListener('beforeunload', () => {
widget.removeListener(ImmutableCheckout.CommerceEventType.SUCCESS);
widget.removeListener(ImmutableCheckout.CommerceEventType.FAILURE);
widget.removeListener(ImmutableCheckout.CommerceEventType.CLOSE);
});
})();
</script>
</body>
</html>