Integrate Enso DeFi Shortcuts¶
Enso DeFi Shortcuts simplify protocol interactions by offering a unified interface to different DeFi protocols via SDK and REST API.
Enso’s crosschain APIs return executable atomic transaction objects that implement the optimal route between DeFi ositions:
- /route API: Define input/output positions and receive optimized execution pathways.
- /bundle API: Construct custom sequences of protocol interactions.
Info
This guide was written by the Enso team. For up-to-date guides refer to Enso developer documentation. For any questions or integration reach out to Enso developer group.
flowchart LR
A((USDC)) --> B{enso.split}
subgraph split ["enso.split"]
B -->|<b>swap</b> via<br/>sushiswap-router| E((SUSHI))
B -->|<b>keep as</b><br/>USDC| F((USDC))
end
E -->|<b>deposit</b> via<br/>steer| G((STEERUV12))
F -->|<b>deposit</b> via<br/>steer| G
The supporting APIs provide comprehensive data about:
- available positions,
- integrated projects and protocols,
- interaction methods - the standardized interfaces enabling declarative route construction,
- portfolio holdings and DeFi positions for any wallet address.
For additional examples, browse the Use Case Library.
Integration¶
To accelerate development, explore:
- Cross-chain routing & asset bridging
- Building with Enso through REST API & SDK
- Crosschain Swap Widget: an off-the-shelf React component enabling one-signature crosschain routing of DeFi positions and native tokens, available as a standalone application or to embed into your UI
- Supported projects and positions

Crosschain Lending¶
This example shows crosschain minting and liquidity provisioning. The rUSD stablecoin is minted on Ethereum Mainnet, brirdget (through wsrUSD) and deposited in the appropriate Morpho vault.
flowchart LR
subgraph ethereum ["🌐 Ethereum"]
USDC_ETH((USDC))
USDC_ETH -->|enso<br/>route| wsrUSD_ETH((wsrUSD))
end
wsrUSD_ETH -.->|stargate<br/>bridge| wsrUSD_KATANA((wsrUSD))
subgraph katana ["⚔️ Katana"]
wsrUSD_KATANA -->|morpho-markets-v1<br/>deposit| MORPHO_SHARES((Morpho<br/>wsrUSD/vbUSD))
end
style MORPHO_SHARES stroke-dasharray: 5 5
const KATANA_ID = 747474;
const ETHEREUM_ID = 1;
// Common addresses
const WALLET_ADDRESS = "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11"; // User wallet
// Token addresses
const MORPHO = "0xD50F2DffFd62f94Ee4AEd9ca05C61d0753268aBc";
const USDC_ETHEREUM = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const wsrUSD_KATANA = "0x4809010926aec940b550D34a46A52739f996D75D";
const wsrUSD_ETHEREUM = "0xd3fd63209fa2d55b07a0f6db36c2f43900be3094";
const wsrUSD_MORPHO_POSITION_ID =
"0xd8a93a4cd16f843c385391e208a9a9f2fd75aedfcca05e4810e5fbfcaa6baec6";
const client = new EnsoClient({
apiKey: process.env.ENSO_API_KEY!,
});
// LayerZero pool addresses
const wsrEthToKatanaPools = await client.getLayerZeroPool({
chainId: ETHEREUM_ID,
token: wsrUSD_ETHEREUM,
destinationChainId: KATANA_ID,
destinationToken: wsrUSD_KATANA,
});
console.log(JSON.stringify(wsrEthToKatanaPools), !wsrEthToKatanaPools.length);
if (!wsrEthToKatanaPools.length) {
throw new Error("Required pools not available");
}
const bundle = await client.getBundleData(
{
chainId: ETHEREUM_ID,
fromAddress: WALLET_ADDRESS,
spender: WALLET_ADDRESS,
routingStrategy: "router",
},
[
// mint rUSD on Ethereum, swap for wsrUSD_ETHEREUM in 1 action
{
protocol: "enso",
action: "route",
args: {
amountIn: parseUnits("1000", 6).toString(), // 1000 USDC
tokenIn: USDC_ETHEREUM,
receiver: WALLET_ADDRESS,
tokenOut: wsrUSD_ETHEREUM,
},
},
{
protocol: "stargate",
action: "bridge",
args: {
primaryAddress: wsrEthToKatanaPools[0].pool,
destinationChainId: KATANA_ID,
tokenIn: wsrUSD_ETHEREUM,
amountIn: { useOutputOfCallAt: 0 },
receiver: WALLET_ADDRESS,
callback: [
// Step 1: Check wsrUSD_KATANA balance on Katana after bridge
{
protocol: "enso",
action: "balance",
args: {
token: wsrUSD_KATANA,
},
},
{
protocol: "morpho-markets-v1",
action: "deposit",
args: {
amountIn: { useOutputOfCallAt: 0 },
tokenIn: wsrUSD_KATANA,
receiver: WALLET_ADDRESS,
primaryAddress: MORPHO,
positionId: wsrUSD_MORPHO_POSITION_ID,
},
},
],
},
},
]
);
Zap deposit USDC to SushiSwap USDC-wETH Liquidity Pool¶
This route creates SushiSwap LP tokens by splitting USDC and providing liquidity to the USDC/wETH pool.
flowchart LR
A((USDC)) --> B{enso.split}
subgraph split ["enso.split"]
B -->|<b>swap</b> via<br/>sushiswap-router| E((WETH))
B -->|<b>keep as</b><br/>USDC| F((USDC))
end
E -->|<b>addLiquidity</b> via<br/>sushiswap-v2| G((USDC/ETH LP))
F -->|<b>addLiquidity</b> via<br/>sushiswap-v2| G
Route mechanics:
- Split
USDCinto two paths via enso- Swap a portion of
USDCtowETHvia sushiswap-router - Keep a portion of
USDC
- Swap a portion of
- Deposit
USDCandwETHtoSLPvia sushiswap-v2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
Deposit into a SushiSwap V3 LP¶
To deposit into Sushiswap V3 AUSD/USDC pool, you need to use the bundle API.
flowchart LR
A((USDC)) --> B{enso.split}
subgraph split ["enso.split"]
B -->|<b>swap</b> via<br/>enso| E((AUSD))
B -->|<b>keep as</b><br/>USDC| F((USDC))
end
E -->|<b>depositclmm</b> via<br/>sushiswap-v3| G((AUSD/USDC<br/>LP))
F -->|<b>depositclmm</b> via<br/>sushiswap-v3| G
Bundle Design:
- Input of 100
USDCmust be split into 2 tokens:AUSDandUSDC, using Enso’ssplitaction that converts 50% of USDC into AUSD, and keeps the rest untouched - Deposit using
depositclmmaction ofsushiswap-v3protocol. tokenInare the pool’s tokens (USDC/AUSD)amountInis an array of amounts obtained from the split intoUSDCandAUSDrespectively, using dynamic quantity reference (useOutputOfCallAt).- The
tokenOutvalue is the address of Sushiswap’s position manager contract. - Provide correct fee and ticks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | |
Deposit WBTC to SushiSwap V2 USDC-ETH LP Position via Multi-Swap¶
This route uses WBTC to create SushiSwap LP tokens through token splitting and liquidity provision.
flowchart LR
A((WBTC)) --> B{enso.split}
subgraph split ["enso.split"]
B -->|<b>swap</b> via<br/>sushiswap-router| E((USDC))
B -->|<b>swap</b> via<br/>sushiswap-router| F((wETH))
end
E -->|<b>addLiquidity</b> via<br/>sushiswap-v2| G((SLP))
F -->|<b>addLiquidity</b> via<br/>sushiswap-v2| G
Route mechanics:
- Split
WBTCinto two paths via enso- Swap a portion of
WBTCtoUSDCvia sushiswap-router - Swap a portion
WBTCtowETHvia sushiswap-router
- Swap a portion of
- Deposit
USDCandwETHtoSLPvia sushiswap-v2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
Deposit USDT to Morpho Blue steakUSDC Lending Vault¶
This route deposits USDT to steakUSDC through a simple swap and deposit mechanism using Morpho Blue vaults.
Route mechanics:
- Swap
USDTtoUSDCvia sushiswap-router - Deposit
USDCtosteakUSDCvia morpho-blue-vaults
flowchart LR
A((USDT)) -->|<b>swap</b> via<br/>sushiswap-router| B((USDC))
B -->|<b>deposit</b> via<br/>morpho-blue-vaults| C((steakUSDC))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
Withdraw from Morpho Blue with conversion¶
This route withdraws from a Morpho Blue vault position and converts the underlying asset to WBTC. The function redeems the vault token to get the underlying AUSD and then swaps it to WBTC.
flowchart LR
A((bbqAUSD)) -->|<b>redeem</b> via<br/>morpho-blue-vaults| B((AUSD))
B -->|<b>swap</b> via<br/>sushiswap-router| C((WBTC))
Route mechanics:
- Redeem
bbqAUSDtoAUSDvia morpho-blue-vaults - Swap
AUSDtoWBTCvia sushiswap-router
export async function withdrawFromMorphoBlueAndSwapToWbtc() {
const chainId = 747474;
const TOKEN_IN = "0xdE6a4F28Acfe431DD1CfA2D9c7A3d8301624a841"; // bbqAUSD
const TOKEN_OUT = "0x0913DA6Da4b42f538B445599b46Bb4622342Cf52"; // WBTC
const amountIn = parseUnits("1", 18);
const routeParams: RouteParams = {
fromAddress: userAddress,
receiver: userAddress,
chainId: chainId,
destinationChainId: 747474,
amountIn: [amountIn.toString()],
tokenIn: [TOKEN_IN],
tokenOut: [TOKEN_OUT],
routingStrategy: "router",
slippage: "150",
referralCode: "build-on-katana"
};
happyPathLog(routeParams);
const approvalData = await client.getApprovalData({
amount: amountIn.toString(),
chainId: chainId,
tokenAddress: TOKEN_IN,
fromAddress: userAddress,
});
await sendEoa(approvalData.tx, approvalData.gas);
const route = await client.getRouteData(routeParams);
await sendEoa(route.tx, route.gas);
return route;
}
Strategy vault position migration: Morpho to Yearn¶
This route redeems bbqUSDC, converts to ETH, and deposits into a Yearn vbETH vault.
flowchart LR
A((bbqUSDC)) -->|<b>redeem</b> via<br/>morpho-blue-vaults| B((USDC))
B -->|<b>swap</b> via<br/>sushiswap-router| C((wETH))
C -->|<b>deposit</b> via<br/>yearn-v3| D((yvvbETH))
Route mechanics:
- Redeem
bbqUSDCtoUSDCvia morpho-blue-vaults - Swap
USDCtowETHvia sushiswap-router - Deposit
wETHtoyvvbETHvia yearn-v3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
Zap deposit USDT to Yearn vbETH vault¶
This route swaps USDT to ETH and deposits into a Yearn vault for vbETH exposure.
flowchart LR
A((USDT)) -->|<b>swap</b> via<br/>sushiswap-router| B((wETH))
B -->|<b>deposit</b> via<br/>yearn-v3| C((yvvbETH))
Route mechanics:
- Swap
USDTtowETHvia sushiswap-router - Deposit
wETHtoyvvbETHvia yearn-v3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
Deposit USDC to Charm Alpha¶
This route deposits USDC into a Charm Alpha vault position containing WBTC and ETH. The function splits the input USDC between WBTC and wETH tokens before depositing them into the vault.
flowchart LR
A((USDC)) --> B{enso.split}
subgraph split ["enso.split"]
B -->|<b>swap</b> via<br/>sushiswap-router| E((WBTC))
B -->|<b>swap</b> via<br/>sushiswap-router| F((wETH))
end
E -->|<b>deposit</b> via<br/>charm-alpha-vaults-v2| G((CHARM_VAULT))
F -->|<b>deposit</b> via<br/>charm-alpha-vaults-v2| G
Route mechanics:
- Split
USDCtoWBTCandwETHvia enso- Swap a portion of
USDCtoWBTC - Swap a portion
USDCtowETH
- Swap a portion of
- Deposit
WBTCandwETHtoWBTCETH30via charm-alpha-vaults-v2
export async function depositUsdcToCharmWbtcEth03() {
const chainId = 747474;
const TOKEN_IN = "0x203A662b0BD271A6ed5a60EdFbd04bFce608FD36"; // USDC
const TOKEN_OUT = "0x85b88F8ACEB5CaA67e240E6C2567F954B0C58D99"; // WBTCETH30
const amountIn = parseUnits("100", 6);
const routeParams: RouteParams = {
fromAddress: userAddress,
receiver: userAddress,
chainId: chainId,
destinationChainId: 747474,
amountIn: [amountIn.toString()],
tokenIn: [TOKEN_IN],
tokenOut: [TOKEN_OUT],
routingStrategy: "router",
slippage: "150",
referralCode: "build-on-katana"
};
happyPathLog(routeParams);
const approvalData = await client.getApprovalData({
amount: amountIn.toString(),
chainId: chainId,
tokenAddress: TOKEN_IN,
fromAddress: userAddress,
});
await sendEoa(approvalData.tx, approvalData.gas);
const route = await client.getRouteData(routeParams);
await sendEoa(route.tx, route.gas);
return route;
}
Withdraw from Charm Alpha vault with conversion¶
This route redeems a Charm Alpha vault position and converts the underlying assets to AUSD. The function withdraws USDC and wETH from the vault and swaps both tokens to the target AUSD token.
flowchart LR
A((USDCETH5)) -->|<b>redeem</b> via<br/>charm-alpha-vaults-v2| B((USDC))
A -->|<b>redeem</b> via<br/>charm-alpha-vaults-v2| C((wETH))
B --> D{enso.merge}
C --> D
subgraph merge ["enso.merge"]
D -->|<b>swap</b> via<br/>sushiswap-router| E((AUSD))
D -->|<b>swap</b> via<br/>sushiswap-router| E
end
Route mechanics:
- Redeem
USDCETH5toUSDCandwETHvia charm-alpha-vaults-v2 - Merge
USDCandwETHtoAUSDvia enso with swapping
export async function withdrawCharmVbusdcVbeth005ToAusd() {
const chainId = 747474;
const TOKEN_IN = "0xc78c51F88adFbAdcDfafCfeF7F5E3d3c6C7d5129"; // USDCETH5
const TOKEN_OUT = "0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a"; // AUSD
const amountIn = parseUnits("1", 18);
const routeParams: RouteParams = {
fromAddress: userAddress,
receiver: userAddress,
chainId: chainId,
destinationChainId: 747474,
amountIn: [amountIn.toString()],
tokenIn: [TOKEN_IN],
tokenOut: [TOKEN_OUT],
routingStrategy: "router",
slippage: "150",
referralCode: "build-on-katana"
};
happyPathLog(routeParams);
const approvalData = await client.getApprovalData({
amount: amountIn.toString(),
chainId: chainId,
tokenAddress: TOKEN_IN,
fromAddress: userAddress,
});
await sendEoa(approvalData.tx, approvalData.gas);
const route = await client.getRouteData(routeParams);
await sendEoa(route.tx, route.gas);
return route;
}
Deposit USDC to Midas Restaked SOL (Re7SOL)¶
This route deposits USDC to Midas Re7SOL tokens.
Route mechanics:
- Swap
USDCtouSOLvia sushiswap-router - Deposit
uSOLtomRe7SOLvia midas-rwa
flowchart LR
A((USDC)) -->|<b>swap</b> via<br/>sushiswap-router| B((uSOL))
B -->|<b>deposit</b> via<br/>midas-rwa| C((mRe7SOL))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
Deposit USDC to Steer SUSHI-USDC Automated LP Management¶
This route creates a Steer UniV3 vault position by splitting USDC into SUSHI and USDC components.
Route mechanics:
- Split
USDCinto two paths via enso- Swap a portion
USDCtoSUSHIvia sushiswap-router - Keep a portion as
USDC
- Swap a portion
- Deposit
SUSHIandUSDCtoSTEERUV12via steer
flowchart LR
A((USDC)) --> B{enso.split}
subgraph split ["enso.split"]
B -->|<b>swap</b> via<br/>sushiswap-router| E((SUSHI))
B -->|<b>keep as</b><br/>USDC| F((USDC))
end
E -->|<b>deposit</b> via<br/>steer| G((STEERUV12 <br/> LP))
F -->|<b>deposit</b> via<br/>steer| G
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
Transform WBTC to Midas Restaked SOL with High Slippage¶
This route converts WBTC to Midas Re7SOL tokens through SOL bridging with extremely high price impact.
flowchart LR
A((WBTC)) -->|<b>swap</b> via<br/>sushiswap-router| B((uSOL))
B -->|<b>deposit</b> via<br/>midas-rwa| C((mRe7SOL))
Route mechanics:
- Swap
WBTCtouSOLvia sushiswap-router - Deposit
uSOLtomRe7SOLvia midas-rwa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |