Smart Checkout
Smart Checkout provides the functionality to calculate different options for a user to fund their wallet before completing their buy, swap or cancel actions. The funding routes can be used to craft a better checkout experience by guiding the user to top up their balance to be able to complete their desired actions.
How it works
Purchasing an asset requires the user to have enough tokens to fill the order as well as having enough IMX to pay the gas fees associated with the transactions. During the checkout process, there may be an ERC20 token approval transaction as well as the order fulfillment transaction. Smart Checkout takes out all the work from having to calculate the total transaction costs, and suggests funding routes for how a user can get enough of the tokens they need to complete their purchase.
Smart checkout considers whether the Swap feature is enabled and is available for the user's region before suggesting founding routes for them.
Here are a couple of examples:
A simple swap example
- At checkout time, a user may not have enough of token A to make the purchase, but they have more than the equivalent amount in token B.
- Smart Checkout will provide options for the user to swap their tokens before completing the purchase, taking into account all gas fees that need to be covered.
User needs IMX to pay gas fees
- At checkout time a user may be low on IMX and cannot pay the gas fees to complete the purchase.
- Smart Checkout will provide options for the user to onramp IMX using their fiat currency or alternatively if they have IMX on layer 1 it will suggest a bridge.
Getting funding routes using Smart Checkout
To get the funding routes using Checkout SDK call the smartCheckout()
method. If the user doesn't have enough funds to fulfil the purchase they will receive funding routes. The parameters for this method are listed below:
Parameter | Description |
---|---|
provider | The provider used to sign transactions. |
itemRequirements | An array of item requirements for the transaction. The array can contain item requirements of typeNativeItemRequirement , ERC20ItemRequirement , or ERC721ItemRequirement . |
transactionOrGasAmount | Optional parameter where you can provide a transaction or a gas amount. If nothing is provided, the gas calculation will be skipped. |
routingOptions | Optional parameter to override which funding routes to consider. By default, all routes including swap, bridge and onramp will be considered. |
onComplete | Optional parameter to provide a callback to be executed once all funding routes are found. |
onFundingRoute | Optional parameter to provide a callback to be executed on each funding route found. |
fundingRouteFullAmount | Optional parameter to flag whether to get funding routed based on full or partial amount. By default smart checkout processes partial amounts. |
Call the checkout smart checkout method
import { checkout, config } from '@imtbl/sdk';
import { BigNumber } from 'ethers';
async function getFundingRoutes(orderId: string) {
// setup checkout instance, create provider and ensure connected
const checkoutSDK = new checkout.Checkout({
baseConfig: { environment: config.Environment.SANDBOX },
});
const { provider } = await checkoutSDK.createProvider({
walletProviderName: checkout.WalletProviderName.METAMASK,
});
const connectResult = await checkoutSDK.connect({ provider });
// call checkoutSDK.smartCheckout to get funding routes for a transaction
const fundingRoutes: checkout.SmartCheckoutResult =
await checkoutSDK.smartCheckout({
provider,
itemRequirements: [
{
type: checkout.ItemType.NATIVE,
amount: '1',
},
{
type: checkout.ItemType.ERC20,
amount: '2',
tokenAddress: '0x',
spenderAddress: '0x',
},
],
transactionOrGasAmount: {
type: checkout.TransactionOrGasType.GAS,
gasToken: {
type: checkout.GasTokenType.NATIVE,
limit: BigNumber.from('1'),
},
},
});
if (fundingRoutes.sufficient == true) {
// the transaction is sufficient and can be processed
}
if (fundingRoutes.sufficient == false) {
// the transaction is insufficient and requires more funds to be processed
const { routingOutcome } = fundingRoutes.router!;
if (routingOutcome.type === checkout.RoutingOutcomeType.ROUTES_FOUND) {
// there are ways to resolve the insufficient balance through the funding routes
routingOutcome.fundingRoutes.forEach((route) => {
// each route returned will have a list of steps to take
// to fund the users wallet with the amount they need
// of the token that they need
route.steps.forEach((step) => {
console.log({
type: step.type, // the step type to perform: bridge, swap, onramp
fundingItem: {
type: step.fundingItem.type, // the type of token needed
token: step.fundingItem.token, // token info of the item to bridge, swap or onramp
fundsRequired: step.fundingItem.fundsRequired, // how much the user needs to bridge, swap or onramp
userBalance: step.fundingItem.userBalance, // users balance of the item
},
});
});
});
} else if (
routingOutcome.type === checkout.RoutingOutcomeType.NO_ROUTES_FOUND
) {
// no possible swap/bridge/onramp funding routes were found for the transaction
}
}
}