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
USDC
into two paths via enso- Swap a portion of
USDC
towETH
via sushiswap-router - Keep a portion of
USDC
- Swap a portion of
- Deposit
USDC
andwETH
toSLP
via 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
USDC
must be split into 2 tokens:AUSD
andUSDC
, using Enso’ssplit
action that converts 50% of USDC into AUSD, and keeps the rest untouched - Deposit using
depositclmm
action ofsushiswap-v3
protocol. tokenIn
are the pool’s tokens (USDC/AUSD
)amountIn
is an array of amounts obtained from the split intoUSDC
andAUSD
respectively, using dynamic quantity reference (useOutputOfCallAt
).- The
tokenOut
value 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
WBTC
into two paths via enso- Swap a portion of
WBTC
toUSDC
via sushiswap-router - Swap a portion
WBTC
towETH
via sushiswap-router
- Swap a portion of
- Deposit
USDC
andwETH
toSLP
via 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
USDT
toUSDC
via sushiswap-router - Deposit
USDC
tosteakUSDC
via 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
bbqAUSD
toAUSD
via morpho-blue-vaults - Swap
AUSD
toWBTC
via 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
bbqUSDC
toUSDC
via morpho-blue-vaults - Swap
USDC
towETH
via sushiswap-router - Deposit
wETH
toyvvbETH
via 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
USDT
towETH
via sushiswap-router - Deposit
wETH
toyvvbETH
via 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
USDC
toWBTC
andwETH
via enso- Swap a portion of
USDC
toWBTC
- Swap a portion
USDC
towETH
- Swap a portion of
- Deposit
WBTC
andwETH
toWBTCETH30
via 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
USDCETH5
toUSDC
andwETH
via charm-alpha-vaults-v2 - Merge
USDC
andwETH
toAUSD
via 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
USDC
touSOL
via sushiswap-router - Deposit
uSOL
tomRe7SOL
via 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
USDC
into two paths via enso- Swap a portion
USDC
toSUSHI
via sushiswap-router - Keep a portion as
USDC
- Swap a portion
- Deposit
SUSHI
andUSDC
toSTEERUV12
via 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
WBTC
touSOL
via sushiswap-router - Deposit
uSOL
tomRe7SOL
via 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 |
|