# Account ID Source: https://docs.enso.build/api-reference/account/account-id public/openapi.json get /api/v1/account/accountId Gives the Account ID associated with the current user # Approve Enso contract Source: https://docs.enso.build/api-reference/defi-shortcuts/approve-enso-contract public/openapi.json get /api/v1/wallet/approve Returns a transaction that approves your Enso contracts to spend the given amount of specified tokens. Approve before sending the route transaction on-chain. # Bundle a list of actions Source: https://docs.enso.build/api-reference/defi-shortcuts/bundle-a-list-of-actions public/openapi.json post /api/v1/shortcuts/bundle Returns a single transaction bundling the submitted actions. For available actions, see `/actions` endpoint. # Get transaction for IPOR shortcut Source: https://docs.enso.build/api-reference/defi-shortcuts/get-transaction-for-ipor-shortcut public/openapi.json post /api/v1/shortcuts/static/ipor # Optimal route between two tokens Source: https://docs.enso.build/api-reference/defi-shortcuts/optimal-route-between-two-tokens public/openapi.json get /api/v1/shortcuts/route Calculates optimal transaction with the best route between two tokens, which may involve several actions that interact with various DeFi protocols. To enter a non-tokenized position, use GET `shortcuts/route/nontokenized`. # Optimal route between two tokens Source: https://docs.enso.build/api-reference/defi-shortcuts/optimal-route-between-two-tokens-1 public/openapi.json post /api/v1/shortcuts/route Calculates optimal transaction with the best route between two tokens, which may involve several actions that interact with various DeFi protocols. To enter a non-tokenized position, use the GET `/shortcuts/route/nontokenized`. # Routing to a non-tokenized position Source: https://docs.enso.build/api-reference/defi-shortcuts/routing-to-a-non-tokenized-position public/openapi.json get /api/v1/shortcuts/route/nontokenized Calculates optimal transaction with the best route entering a non-tokenized position, which may involve several actions that interact with various DeFi protocols. # Chain and transactions volume Source: https://docs.enso.build/api-reference/defi/chain-and-transactions-volume public/openapi.json get /api/v1/volume/{chainId} Returns total USD and transactions volume for the given chainId. # Wallet balances Source: https://docs.enso.build/api-reference/defi/wallet-balances public/openapi.json get /api/v1/wallet/balances Returns tokens balances for Enso Wallet associated with the given address across all supported chains.
With `useEoa` set to true, it returns balances for the given EOA address instead. # Actions for protocol Source: https://docs.enso.build/api-reference/integration/actions-for-protocol public/openapi.json get /api/v1/actions/{slug} # Aggregators Source: https://docs.enso.build/api-reference/integration/aggregators public/openapi.json get /api/v1/aggregators Fetches aggregators supported by Enso # All Protocols Source: https://docs.enso.build/api-reference/integration/all-protocols public/openapi.json get /api/v1/protocols Returns all available protocols with supported chains # LayerZero pool Source: https://docs.enso.build/api-reference/integration/layerzero-pool public/openapi.json get /api/v1/layerzero/pool Returns the LayerZero Stargate pool address for a given token address and chain ID. Returns null if no pool exists for the token on that chain. # Networks Source: https://docs.enso.build/api-reference/integration/networks public/openapi.json get /api/v1/networks Returns networks supported by Enso # Projects Source: https://docs.enso.build/api-reference/integration/projects public/openapi.json get /api/v1/projects Returns supported projects (e.g. `aave`) or platforms associated with available projects # Protocols in a project Source: https://docs.enso.build/api-reference/integration/protocols-in-a-project public/openapi.json get /api/v1/projects/{project}/protocols Returns all protocols available within the given project. For supported projects, see the `/projects` endpoint. # Standard per protocol Source: https://docs.enso.build/api-reference/integration/standard-per-protocol public/openapi.json get /api/v1/standards/{slug} Returns a standard matching the given `slug`, containing supported actions, exact `inputs`, and a list of chains the standard's supported on. # Standards Source: https://docs.enso.build/api-reference/integration/standards public/openapi.json get /api/v1/standards Returns standards available for bundling. Each element represents a protocol, with list of supported actions and chains the standard's supported on. # Supported actions Source: https://docs.enso.build/api-reference/integration/supported-actions public/openapi.json get /api/v1/actions Returns actions that can be bundled with `/shortcuts/bundle` endpoint. For specific protocol actions and exact action inputs, see [`/actions/{slug}`](/api-reference/integration/actions-for-a-given-protocol) endpoint. # Nontokenized positions Source: https://docs.enso.build/api-reference/tokens/nontokenized-positions public/openapi.json get /api/v1/nontokenized Returns a list of all nontokenized positions with details. # Token Price Source: https://docs.enso.build/api-reference/tokens/token-price public/openapi.json get /api/v1/prices/{chainId}/{address} Returns token price for the given address and chainId. # Tokens Source: https://docs.enso.build/api-reference/tokens/tokens public/openapi.json get /api/v1/tokens Returns tokens and their details. This APi includes cursor-based pagination with default 1000 items per page. # Tokens Prices Batched Source: https://docs.enso.build/api-reference/tokens/tokens-prices-batched public/openapi.json get /api/v1/prices/{chainId} Returns prices for a batch of tokens on a given chain. # Enso Developer Documentation Source: https://docs.enso.build/home Enso Developer Documentation

Enso Developer Documentation

Shortcuts to executable calldata for DeFi Workflows.

Get started with Enso's core APIs and essential integration guides Comprehensive API documentation for developers and integrators Try out different widgets and use them the plug-and-play React templates to add blockchain functionality to your app
# Overview Source: https://docs.enso.build/pages/api-reference/overview Learn about Enso API and its capabilities. export const date_0 = "2025-08-13" The Enso API provides developers with a comprehensive set of tools to interact with DeFi protocols and execute complex transactions across multiple blockchain networks. ## Getting Started Explore detailed documentation for each API endpoint using the API sandbox. The Sandbox doesn't require authentication. For building and production use cases, use a dedicated API key. ### Authentication In production, all API requests require authentication using an API key, as the API is [rate-limited](/pages/build/reference/faq##what-is-the-default-rate-limit-for-the-api?). ```bash theme={null} -H "Authorization: Bearer YOUR_API_KEY" ``` 1. Create an account on the [Enso Dashboard](https://developers.enso.build) 2. Generate an API key from your dashboard 3. Use this key in all API requests ## API Groups The Enso API is organized into several functional groups: ### Shortcuts Execute optimized token swaps and complex DeFi operations with single transactions. * [`GET /v1/shortcuts/route`](/api-reference/defi-shortcuts/optimal-route-between-two-tokens) - Find optimal token swap routes * [`POST /v1/shortcuts/bundle`](/api-reference/defi-shortcuts/bundle-a-list-of-actions) - Bundle multiple actions atomically * [`GET /v1/wallet/approve`](/api-reference/defi-shortcuts/approve-enso-contract) - Approve token spending ### Integration Access metadata about supported protocols, standards, and available actions. * [`GET /v1/standards`](/api-reference/integration/standards) - Get available integration standards * [`GET /v1/actions`](/api-reference/integration/supported-actions) - Get supported DeFi actions * [`GET /v1/protocols`](/api-reference/integration/all-protocols) - Get all supported protocols * [`GET /v1/networks`](/api-reference/integration/networks) - Get supported blockchain networks * [`GET /v1/projects`](/api-reference/integration/projects) - Get protocol project groupings ### Tokens Query token data including positions, prices, and wallet holdings. * [`GET /v1/tokens`](/api-reference/tokens/tokens) - Get token details and metadata * [`GET /v1/nontokenized`](/api-reference/tokens/nontokenized-positions) - Get non-tokenized DeFi positions * [`GET /v1/prices/{chainId}/{address}`](/api-reference/tokens/token-price) - Get token price data ### DeFi Access real-time DeFi metrics and wallet information. * [`GET /v1/wallet/balances`](/api-reference/defi/wallet-balances) - Get wallet token balances * [`GET /v1/volume/{chainId}`](/api-reference/defi/chain-and-transactions-volume) - Get chain trading volume * [`GET /v1/aggregators`](/api-reference/integration/aggregators) - Get supported DEX aggregators ## Key Concepts Before using the Enso API, familiarize yourself with these key concepts: * [Projects, protocols, and standards](/pages/build/reference/concepts) - Understand the structure of Enso's data model * [Shortcuts](/pages/build/examples/shortcuts) - Pre-configured paths for common DeFi operations * [Actions](/pages/build/reference/actions) - Standardized interactions with DeFi protocols * [Routing Strategies](/pages/build/reference/routing-strategies) - Different approaches to transaction execution

Updated {date_0}

# SDK Source: https://docs.enso.build/pages/api-reference/sdk Enso SDK is a JavaScript library for interacting with Enso API. export const date_0 = "2025-08-07" The Enso SDK provides a set of tools and methods to interact with the Enso API. It includes functionalities for token approvals, routing, quoting, and balance checking. The Route API is a highly-efficient DeFi aggregation and smart order routing REST API. With it, developers can easily tap into optimized routes for DeFi tokens/positions and multi-token swaps across various chains. ## Installation Install the Enso SDK using your preferred package manager: ```bash npm theme={null} npm install @ensofinance/sdk ``` ```bash yarn theme={null} yarn add @ensofinance/sdk ``` ```bash pnpm theme={null} pnpm add @ensofinance/sdk ``` ```bash bun theme={null} bun add @ensofinance/sdk ``` ## Quick Start This example shows how to swap ETH directly to a Yearn vault position: ```typescript theme={null} import { EnsoClient } from '@ensofinance/sdk'; const enso = new EnsoClient({ apiKey: 'YOUR_API_KEY', }); async function enterYearnVault() { // First, get the transaction data const routeData = await enso.getRouteData({ fromAddress: '0xYourWalletAddress', receiver: '0xYourWalletAddress', spender: '0xYourWalletAddress', chainId: 1, amountIn: ['1000000000000000000'], // 1 ETH tokenIn: ['0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'], // ETH tokenOut: ['0xa258C4606Ca8206D8aA700cE2143D7db854D168c'], // yvWETH slippage: 50, routingStrategy: 'router', }); // The routeData.tx object can now be sent using your preferred web3 library // Example with ethers.js: // const provider = new ethers.providers.Web3Provider(window.ethereum); // const signer = provider.getSigner(); // const tx = await signer.sendTransaction(routeData.tx); // await tx.wait(); console.log('Transaction data:', routeData.tx); console.log('Expected yvWETH amount:', routeData.amountOut); } enterYearnVault(); ``` ## Core Concepts The Enso SDK abstracts complex DeFi operations through several key components: 1. **EnsoClient**: The main entry point for all SDK functionalities 2. **Routing Strategies**: Different execution paths for transactions 3. **Bundle Actions**: Compose multiple DeFi operations in a single transaction 4. **Approvals**: Manage token allowances for DeFi interactions 5. **Token Data**: Retrieve detailed information about tokens and protocols ## Routing Strategies There are 3 routing strategies available depending on your use case: * **`router`** - Uses a single contract which acts as a universal router * **`delegate`** - Returns calldata in the form of delegateCalls for smart accounts * **`delegate-legacy`** - Legacy version of delegate routing * **`router-legacy`** - Legacy version of router routing ## Complete Methods Reference ### Primary Methods #### getRouteData(params: RouteParams) Calculates the optimal route for token swaps or entering/exiting DeFi positions. **Parameters:** * `fromAddress` (Address): Ethereum address of the wallet to send the transaction from * `receiver?` (Address): Ethereum address of the receiver of the tokenOut * `spender?` (Address): Ethereum address of the spender of the tokenIn * `chainId` (number): Chain ID of the network to execute the transaction on * `destinationChainId?` (number): Chain ID of the destination network for cross-chain bridging * `amountIn` (Quantity\[]): Amount of tokenIn to swap in wei * `slippage?` (Quantity): Slippage in basis points (1/10000) * `minAmountOut?` (Quantity\[]): Minimum amount out in wei * `tokenIn` (Address\[]): Ethereum address of the token to swap from * `tokenOut` (Address\[]): Ethereum address of the token to swap to * `routingStrategy` (RoutingStrategy): Routing strategy to use * `fee?` (Quantity\[]): Fee in basis points for each amountIn value * `feeReceiver?` (Address): Address that will receive the collected fee * `ignoreAggregators?` (string\[]): List of swap aggregators to ignore * `ignoreStandards?` (string\[]): List of standards to ignore * `toEoa?` (boolean): Flag indicating if gained tokenOut should be sent to EOA * `referralCode?` (string): Referral code included in on-chain event **Returns:** `Promise` ```typescript theme={null} const routeData = await enso.getRouteData({ fromAddress: '0xYourWalletAddress', receiver: '0xYourWalletAddress', spender: '0xYourWalletAddress', chainId: 1, amountIn: ['1000000000000000000'], // 1 ETH in wei tokenIn: ['0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'], // ETH tokenOut: ['0x6b175474e89094c44da98b954eedeac495271d0f'], // DAI slippage: 50, // 0.5% routingStrategy: 'router', }); ``` #### getApprovalData(params: ApproveParams) Generates transaction data for approving tokens to be spent by Enso contracts. **Parameters:** * `fromAddress` (Address): Ethereum address of the wallet to send the transaction from * `tokenAddress` (Address): ERC20 token address of the token to approve * `chainId` (number): Chain ID of the network to execute the transaction on * `amount` (Quantity): Amount of tokens to approve in wei **Returns:** `Promise` ```typescript theme={null} const approvalData = await enso.getApprovalData({ fromAddress: '0xYourWalletAddress', tokenAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH chainId: 1, amount: '1000000000000000000', // 1 WETH in wei }); ``` #### getBundleData(params: BundleParams, actions: BundleAction\[]) Constructs bundled transaction data for multiple DeFi operations in a single transaction. **Parameters:** * `chainId` (number): Chain ID of the network to execute the transaction on * `fromAddress` (Address): Ethereum address of the wallet to send the transaction from * `routingStrategy` (RoutingStrategy): Routing strategy to use * `receiver?` (Address): Ethereum address of the receiver of the tokenOut * `spender?` (Address): Ethereum address of the spender of the tokenIn * `ignoreAggregators?` (string\[]): List of swap aggregators to ignore * `referralCode?` (string): Referral code included in on-chain event * `ignoreStandards?` (string\[]): List of standards to ignore * `actions` (BundleAction\[]): Array of actions to bundle **Returns:** `Promise` ```typescript theme={null} const bundle = await enso.getBundleData( { chainId: 1, fromAddress: '0x123...', routingStrategy: 'delegate', }, [ { protocol: 'enso', action: 'route', args: { tokenIn: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', amountIn: '1000000000', receiver: '0x123...' } } ] ); ``` ### Data Retrieval Methods #### getBalances(params: BalanceParams) Retrieves token balances for a given wallet address. **Parameters:** * `chainId?` (number): Chain ID of the network to execute the transaction on * `eoaAddress` (Address): Address of the EOA to associate with the ensoWallet for balances * `useEoa?` (boolean): If true, returns balances for the provided eoaAddress instead of the associated ensoWallet **Returns:** `Promise` ```typescript theme={null} const balances = await enso.getBalances({ chainId: 1, eoaAddress: '0xYourWalletAddress', useEoa: true, }); ``` #### getTokenData(params: TokenParams) Fetches detailed information about tokens, including DeFi tokens and their underlying assets. **Parameters:** * `project?` (string): The overarching project or platform associated with the DeFi token * `protocolSlug?` (string): The specific standard integration or version of the DeFi project * `underlyingTokens?` (MultiAddress): Underlying tokens of defi token * `underlyingTokensExact?` (MultiAddress): Exact composition of underlying tokens * `primaryAddress?` (MultiAddress): Ethereum addresses for contract interaction * `address?` (MultiAddress): Ethereum addresses of the tokens * `chainId?` (number): Chain ID of the network of the token * `type?` (TokenType): Type of token ('defi' | 'base') * `apyFrom?` (Quantity): Only include tokens with APY over this value * `apyTo?` (Quantity): Only include tokens with APY below this value * `tvlFrom?` (Quantity): Only include tokens with TVL over this value * `tvlTo?` (Quantity): Only include tokens with TVL below this value * `page?` (number): Pagination page number (pages are of length 1000) * `cursor?` (number): Cursor for pagination * `includeMetadata?` (boolean): Whether to include token metadata * `name?` (string\[]): Names of the tokens * `symbol?` (string\[]): Symbols of the tokens **Returns:** `Promise` ```typescript theme={null} const tokens = await enso.getTokenData({ chainId: 1, type: 'defi', includeMetadata: true, page: 1 }); ``` #### getPriceData(params: PriceParams) Gets the current price data for a specific token. **Parameters:** * `chainId` (number): Chain ID of the network to search for * `address` (Address): Address of the token to search for **Returns:** `Promise` ```typescript theme={null} const price = await enso.getPriceData({ chainId: 1, address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH }); ``` #### getMultiplePriceData(params: MultiPriceParams) Gets price data for multiple tokens. **Parameters:** * `chainId` (number): Chain ID of the network to search for * `addresses` (Address\[]): Addresses of tokens to check prices for **Returns:** `Promise` ```typescript theme={null} const prices = await enso.getMultiplePriceData({ chainId: 1, addresses: [ '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' // USDC ] }); ``` ### Protocol and Standard Methods #### getProtocolData(params?: ProtocolParams) Retrieves information about DeFi protocols supported by Enso. **Parameters:** * `chainId?` (number | string): Chain ID of the network to search for * `slug?` (string): Slug of the project to search for **Returns:** `Promise` ```typescript theme={null} // Get all protocols const allProtocols = await enso.getProtocolData(); // Get protocols for a specific chain const ethereumProtocols = await enso.getProtocolData({ chainId: 1 }); // Get a specific protocol const aaveProtocol = await enso.getProtocolData({ slug: 'aave-v3' }); ``` #### getStandards() Returns standards available for bundling with protocol information and supported actions. **Returns:** `Promise` ```typescript theme={null} const standards = await enso.getStandards(); ``` #### getStandardBySlug(slug: string) Returns a standard matching the given slug with supported actions and chains. **Parameters:** * `slug` (string): The protocol slug **Returns:** `Promise` ```typescript theme={null} const aaveStandard = await enso.getStandardBySlug('aave-v3'); ``` #### getActions() Returns all actions that can be bundled with the `/shortcuts/bundle` endpoint. **Returns:** `Promise` ```typescript theme={null} const actions = await enso.getActions(); ``` #### getActionsBySlug(slug: string) Gets actions for a specific protocol. **Parameters:** * `slug` (string): The protocol slug **Returns:** `Promise` ```typescript theme={null} const aaveActions = await enso.getActionsBySlug('aave-v3'); ``` ### Specialized Methods #### getRouteNonTokenized(params: RouteNonTokenizedParams) Gets execution data for best route to non-tokenized positions. **Parameters:** * `chainId` (number): Chain ID of the network to execute the transaction on * `fromAddress` (Address): Ethereum address of the wallet to send the transaction from * `routingStrategy` ('delegate' | 'delegate-legacy'): Routing strategy to use * `tokenIn` (Address\[]): Input tokens * `positionOut` (Address): Non-tokenized position to receive * `slippage?` (Quantity): Slippage in basis points * `fee?` (Quantity\[]): Fee in basis points * `feeReceiver?` (Address): Fee receiver address * `amountIn` (Quantity\[]): Amount to send * `receiver` (Address): Receiver address * `spender?` (Address): Spender address * `referralCode?` (string): Referral code **Returns:** `Promise` ```typescript theme={null} const route = await enso.getRouteNonTokenized({ fromAddress: '0x123...', chainId: 1, routingStrategy: 'delegate', tokenIn: ['0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'], positionOut: '0xPositionAddress', amountIn: ['1000000000'], receiver: '0x123...', slippage: 50, }); ``` #### getIporShortcut(params, data: IporShortcutInputData) Returns a transaction for IPOR shortcut operations. **Parameters:** * `chainId?` (number): Chain ID (optional) * `fromAddress` (string): Ethereum address of the wallet * `data` (IporShortcutInputData): IPOR shortcut input data **Returns:** `Promise` ```typescript theme={null} const iporShortcut = await enso.getIporShortcut( { chainId: 1, fromAddress: '0x123...' }, { amountIn: '1000000000000000000', tokenIn: '0xTokenAddress', tokenBToBuy: '0xTokenBAddress', percentageForTokenB: 5000, // 50% slippage: 50, simulate: true } ); ``` #### getNonTokenizedPositions(params?: NonTokenizedParams) Gets all non-tokenized positions with details. **Parameters:** * `project?` (string): The overarching project or platform * `protocolSlug?` (string): The specific standard integration * `chainId?` (number): Chain ID of the network * `destinationChainId?` (number): Destination chain ID for cross-chain bridging * `address?` (Address\[]): Ethereum addresses of positions * `primaryAddress?` (Address\[]): Ethereum addresses for contract interaction * `page?` (number): Pagination page number * `cursor?` (number): Cursor for pagination **Returns:** `Promise` ```typescript theme={null} const nonTokenizedPositions = await enso.getNonTokenizedPositions({ chainId: 1, project: 'aave' }); ``` ### Network and Utility Methods #### getNetworks(params?: NetworkParams) Returns networks supported by Enso. **Parameters:** * `name?` (string): Name of the network to search for * `chainId?` (string): Chain ID of the network to search for **Returns:** `Promise` ```typescript theme={null} const networks = await enso.getNetworks(); const ethereum = await enso.getNetworks({ chainId: "1" }); ``` #### getProjects() Returns supported projects or platforms associated with available protocols. **Returns:** `Promise` ```typescript theme={null} const projects = await enso.getProjects(); ``` #### getProtocolsByProject(project: string) Returns all protocols available within the given project. **Parameters:** * `project` (string): The project name **Returns:** `Promise` ```typescript theme={null} const aaveProtocols = await enso.getProtocolsByProject('aave'); ``` #### getAggregators(chainId?: number) Fetches aggregators supported by Enso. **Parameters:** * `chainId?` (number): Chain ID to filter aggregators for **Returns:** `Promise` ```typescript theme={null} const aggregators = await enso.getAggregators(1); ``` #### getVolume(chainId: number) Returns total USD and transactions volume for the given chainId. **Parameters:** * `chainId` (number): Chain ID to get volume for **Returns:** `Promise` ```typescript theme={null} const volume = await enso.getVolume(1); ``` #### getAccountId() Gets the account ID associated with the API key. **Returns:** `Promise` ```typescript theme={null} const accountId = await enso.getAccountId(); ``` ## Working with Large Numbers The SDK properly handles large numbers common in blockchain transactions: ```typescript theme={null} // Using string representation for large numbers (recommended) const largeAmount = "1000000000000000000000000"; // 1 million tokens with 18 decimals // You can also use JavaScript numbers for smaller values const smallAmount = 1000000; // 1 USDC with 6 decimals ``` ## Bundle Actions The Bundle API supports a variety of actions for interacting with DeFi protocols. For an up-to-date reference of all available actions and their parameters: ```typescript theme={null} // Get all available actions const actions = await enso.getActions(); // Get actions for a specific protocol const aaveActions = await enso.getActionsBySlug("aave-v3"); ``` Common bundle actions include: * **Route**: Token swaps and conversions * **Deposit**: Deposit tokens into DeFi protocols * **Redeem**: Withdraw tokens from DeFi protocols * **Approve**: Token approvals * **Borrow**: Borrow tokens from lending protocols * **Repay**: Repay loans to lending protocols * **Transfer**: Transfer tokens between addresses * **Bridge**: Cross-chain token transfers ## Error Handling The SDK includes proper error handling with custom error types: ```typescript theme={null} import { EnsoClient, EnsoApiError } from '@ensofinance/sdk'; try { const routeData = await enso.getRouteData(params); } catch (error) { if (error instanceof EnsoApiError) { console.error('API Error:', error.statusCode, error.responseData); } else { console.error('Request Error:', error.message); } } ``` ## Best Practices 1. **Use String Representations**: Always use string representations for token amounts to avoid precision issues with large numbers 2. **Handle Slippage**: Set appropriate slippage values (in basis points) to protect against price movements 3. **Gas Estimation**: Use the returned `gas` estimate to set appropriate gas limits 4. **Error Handling**: Implement proper error handling for network issues and API errors 5. **Rate Limiting**: Be mindful of API rate limits when making multiple requests ## Next Steps Explore these resources to fully leverage the Enso SDK: * [Routing Strategies](/pages/build/reference/routing-strategies) - Learn about the different routing options and when to use each one * [Available Actions for Bundle API](/pages/build/reference/actions) - Explore all supported DeFi actions like swaps, deposits, borrows, and more * [Shortcuts](/pages/build/examples/shortcuts) - See practical examples of common DeFi operations implemented with the SDK * [Non-tokenized Positions](/pages/build/examples/route-nontokenized) - Discover how to interact with non-tokenized DeFi positions like Aave borrows or Liquity CDPs * [GitHub Repository](https://github.com/EnsoBuild/sdk-ts) - Access the source code, report issues, or contribute to the SDK * [Developer Chat](https://t.me/enso_shortcuts) - Join our Telegram group for technical support and discussions

Updated {date_0}

# Swagger Source: https://docs.enso.build/pages/api-reference/swagger Swagger TODO # Custom Contract Calls Bundle Source: https://docs.enso.build/pages/build/examples/custom-call-bundle Bundle routing with non-standard ways to interact with protocols Enso supports export const date_0 = "2025-08-07" When a standard `enso:route` isn't enough for protocols with unique function signatures (e.g., requiring a referral code as an argument), you can use the `/bundle` endpoint. By chaining actions like `enso:route` and `enso:call`, you can combine optimal routing with custom contract calls. ### Use Case: Swap and Deposit with a Custom Referral Code Let's explore a scenario where a user wants to swap `USDT` for `STAKED_HYPE`, and then deposit it for `LHYPE`, through a contract whose `deposit` function requires a custom `communityCode` argument. When the transaction is from an EOA, the Enso Router contract executes the sequence. This requires explicit approvals for the router to operate on input tokens. #### Bundle Design In pseudo-code, the bundle looks as follows: ``` 0: enso.route(in: USDT, out: STAKED_HYPE, receiver: ENSO_ROUTER) 1: erc20.approve(STAKED_HYPE, HYPE_DEPOSITOR, amount: outputOfCallAt(1)) 2: enso.call( HYPE_DEPOSITOR.deposit(STAKED_HYPE, outputOf(1), 0, SENDER, "0x1234") ) ``` * **Setup: approve transaction**. The user approves the Enso Router to spend their input `USDT`, which is a required first step to grant the router permission for the swap. * **Action 0: `enso:route`**. The router swaps `USDT` for `STAKED_HYPE`. The `receiver` is critically set to the `ENSO_ROUTER` itself so it can hold the tokens for the next steps. * **Action 1: `erc20:approve`**. The Enso Router approves the final `HYPE_DEPOSITOR` contract, using `{ useOutputOfCallAt: 1 }` to dynamically set the approval amount to the exact output from the previous swap. * **Action 2: `enso:call`**. The router calls the final `deposit` function, passing the dynamic swap amount (again with `{ useOutputOfCallAt: 1 }`), the user's address as the recipient, and the required static `communityCode`. ```ts routeCustomCallEOA.ts theme={null} import { EnsoClient } from "@ensofinance/sdk"; const client = new EnsoClient({ apiKey: "YOUR_API_KEY", // Replace with your Enso API key }); // Define asset and contract addresses const USDT = "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb"; const STAKED_HYPE = "0xffaa4a3d97fe9107cef8a3f48c069f577ff76cc1"; const HYPE_DEPOSITOR = "0x6e358dd1204c3fb1D24e569DF0899f48faBE5337"; const SENDER = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // The user's EOA address const ENSO_ROUTER = "0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf"; // Enso's Router contract // Approve Enso router to use USDT const approval = await client.getApprovalData({ amount: USDT_AMOUNT, chainId: 999, fromAddress: SENDER, tokenAddress: USDT, }); // create the bundle const bundle = await client.getBundleData( { chainId: 999, fromAddress: SENDER, routingStrategy: "router", receiver: SENDER, }, [ { protocol: "enso", action: "route", args: { tokenIn: USDT, tokenOut: STAKED_HYPE, amountIn: USDT_AMOUNT, }, }, { protocol: "erc20", action: "approve", args: { amount: { useOutputOfCallAt: 0 }, spender: HYPE_DEPOSITOR, token: STAKED_HYPE, }, }, { protocol: "enso", action: "call", args: { tokenIn: STAKED_HYPE, tokenOut: LOOPED_HYPE, address: HYPE_DEPOSITOR, args: [ STAKED_HYPE, { useOutputOfCallAt: 0 }, 0, SENDER, "0x1234", ], method: "deposit", abi: "function deposit(address depositAsset, uint256 depositAmount, uint256 minimumMint, address to, bytes communityCode) external returns (uint256 shares)", }, }, ], ); await signEoa(approval.tx, approval.gas); await signEoa(bundle.tx, bundle.gas); console.log("Approval", {gas: approval.gas, tx: approval.tx}) console.log("Bundle", JSON.stringify(bundle, null, 2)); ``` ### Smart Wallet Example (`routingStrategy: 'delegate'`) With a Smart Wallet, the wallet executes the bundle directly, simplifying the approval flow into fewer steps. #### Bundle Design In pseudo-code, we need to do the following: ``` 0: enso.route(in: USDT, out: STAKED_HYPE, receiver: SENDER) | 1: erc20.approve(STAKED_HYPE, HYPE_DEPOSITOR, amount: outputOfCallAt(0)) | 2: enso.call( HYPE_DEPOSITOR.deposit(STAKED_HYPE, outputOf(0), 0, SENDER, "0x1234") ) ``` * **Action 0: `enso:route`**. The Smart Wallet swaps `USDT` for `STAKED_HYPE` and receives the output tokens directly. * **Action 1: `erc20:approve`**. The Smart Wallet approves the final `HYPE_DEPOSITOR` contract, using `{ useOutputOfCallAt: 0 }` to dynamically approve the exact amount received from the swap. * **Action 2: `enso:call`**. The Smart Wallet calls the custom `deposit` function, passing the dynamic swap amount (again using `{ useOutputOfCallAt: 0 }`), the user's address as the recipient, and the required static `communityCode`. ```ts routeCustomCallSmartWallet.ts theme={null} import { EnsoClient } from "@ensofinance/sdk"; const client = new EnsoClient({ apiKey: "YOUR_API_KEY", // Replace with your Enso API key }); // Define asset and contract addresses const USDT = "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb"; const STAKED_HYPE = "0xffaa4a3d97fe9107cef8a3f48c069f577ff76cc1"; const HYPE_DEPOSITOR = "0x6e358dd1204c3fb1D24e569DF0899f48faBE5337"; const SENDER = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; const bundle = await client.getBundleData( { chainId: 999, fromAddress: SENDER, routingStrategy: "delegate", receiver: SENDER, }, [ { protocol: "enso", action: "route", args: { tokenIn: USDT, tokenOut: STAKED_HYPE, amountIn: "100000000", receiver: SENDER, }, }, { protocol: "erc20", action: "approve", args: { token: STAKED_HYPE, spender: HYPE_DEPOSITOR, amount: { useOutputOfCallAt: 0 }, }, }, { protocol: "enso", action: "call", args: { address: HYPE_DEPOSITOR, method: "deposit", abi: "function deposit(address depositAsset, uint256 depositAmount, uint256 minimumMint, address to, bytes communityCode) external returns (uint256 shares)", args: [STAKED_HYPE, { useOutputOfCallAt: 0 }, 0, SENDER, "0x1234"], }, }, ] ); console.log(JSON.stringify(bundle, null, 2)); ```

Updated {date_0}

# Request Tracking Source: https://docs.enso.build/pages/build/examples/request-referral Tag requests with a referral code to track usage and rewards. export const date_0 = "2025-08-14" With `/bundle` and `/route` APIs you can tag transactions with a `referralCode`, allowing you to track usage and rewards associated with that code. Every transaction these APIs create will emit a `ShortcusExecuted` event with the referral code: ```solidity theme={null} ShortcusExecuted(accountId: bytes32, requestId: bytes32) ``` To implement the tracking, you'll need to analyze the `ShortcusExecuted` events emitted by the Enso smart contract executing your transaction. This event contains two key pieces of information: * Use `accountId`, uniquely associated with your account, to identify all requests made through your project's integration with Enso. * Use the `requestId` (a unique identifier for each request) where the higher 16 bytes represent contain the `referralCode`.

Updated {date_0}

# Non-tokenized DeFi Positions Source: https://docs.enso.build/pages/build/examples/route-nontokenized Get calldata for routing to non-tokenized positions. export const date_0 = "2025-07-07" The [GET `shortcuts/route/nontokenized`](/api-reference/defi-shortcuts/routing-to-a-non-tokenized-position) endpoint constructs an optimal conversion route. This API allows entering a non-tokenized DeFi position from any ERC20 or native token. You must use `delegate` strategy when working with non-tokenized positions. 1. Create an API key using [Enso Dashboard](https://developers.enso.build). 2. Securely store your API key and make it available in your environment: ```bash authentication.sh theme={null} ENSO_API_KEY="$ENSO_API_KEY" echo $ENSO_API_KEY >> .env git ignore .env source .env ``` Unlike tokenized positions where you receive a token representing your position (like aTokens in Aave), non-tokenized positions are stored directly in a smart contract (usually a Smart Wallet). This endpoint is specifically designed for interacting with these types of positions. Common examples include: * Borrowing on lending protocols * Creating CDPs (Collateralized Debt Positions) * Complex multi-step DeFi interactions Note: This endpoint requires the use of a Smart Wallet or a delegatecall-compatible contract. Send the transaction via a Smart Wallet, by using the `tx.to` for recipient, and `tx.data` to get the calldata. The transaction will be sent to the [`EnsoShortcutsDelegate`](/pages/build/reference/deployments), which will handle the execution of the route. * Explore the [Shortucts Library](/pages/build/examples/shortcuts) for common DeFi workflows. * Check out the [API Reference](/api-reference/defi-shortcuts/routing-to-a-non-tokenized-position) for full parameter details

Updated {date_0}

# Shortcuts Library Source: https://docs.enso.build/pages/build/examples/shortcuts Explore shortcuts for common DeFi workflows. export const date_0 = "2025-11-03" The Enso Shortcuts system offers two powerful APIs for building DeFi workflows: * **Automated Routing**: The [POST `shortcuts/route`](/api-reference/defi-shortcuts/optimal-route-between-two-tokens) API calculates optimized multi-step paths for entering/exiting DeFi positions or swapping ERC20 tokens. It automatically creates a path between two positions specified in the request. * **Bundling DeFi Actions**: The [POST `shortcuts/bundle`](/api-reference/defi-shortcuts/bundle-a-list-of-actions) API lets you orchestrate DeFi workflows by composing multi-step sequences of [Actions](/pages/build/reference/actions) of your choosing. **Would `route` do the job?**
The `route` API might be the simpler way to route your assets. Before using the bundle API, check if `route` would work using [happypath](https://happypath.enso.build).
Both APIs return a transaction object with calldata representing your workflow, ready to be submitted to [`EnsoShortcutRouter`](https://etherscan.io/address/0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E#code) for execution. ## 1. Automated Routing The POST `route` API is suitable for single-path operations with automatic optimization. ### Token Swaps Optimize conversions between tokens by leveraging automated routing across DEXs. **Example**: Swapping 1 ETH to USDC with the best execution price and 0.5% slippage * **Input**: 1 ETH * **Slippage**: 0.5% * **Output**: USDC worth of 1 ETH ```ts Typescript SDK theme={null} import { parseUnits } from "ethers/lib/utils"; const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token Addresses const ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const USDC = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; // Define amount const amountInEth = parseUnits("1", 18); // 1 ETH const route = await ensoClient.getRouteData({ chainId, fromAddress, receiver: fromAddress, routingStrategy: "router", tokenIn: [ETH], tokenOut: [USDC], amountIn: [amountInEth], slippage: "50" // 0.5% }); ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/route' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "router", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], "tokenOut": ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"], "amountIn": ["1000000000000000000"], "slippage": "50" }' | jq ```
### Multi-Token Deposits Deposit multiple tokens simultaneously into a liquidity pool to receive LP tokens in a single transaction. **Example**: Depositig 10 DAI + 10 USDC + 10 USDT to 3Crv LP tokens (Curve 3pool) in one step * **Input**: 10 DAI, 10 USDC, 10 USDT * **Slippage**: 0.5% * **Output**: 3Crv LP tokens ```ts SDK theme={null} const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; const receiver = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"; // Token Addresses const DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; const USDT = "0xdAC17F958D2ee523a2206206994597C13D831ec7"; const curve3poolLp = "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"; // Define amounts const amountInDAI = parseUnits("10", 18); const amountInUSDC = parseUnits("10", 6); const amountInUSDT = parseUnits("10", 6); const route = await ensoClient.getRouteData({ chainId, fromAddress, receiver, routingStrategy: "delegate", tokenIn: [DAI, USDC, USDT], tokenOut: [curve3poolLp], amountIn: [ amountInDAI, amountInUSDC, amountInUSDT, ], slippage: "50" // 0.5% }); ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/route' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "delegate", "receiver": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "tokenIn": [ "0x6B175474E89094C44Da98b954EedeAC495271d0F", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xdAC17F958D2ee523a2206206994597C13D831ec7" ], "tokenOut": ["0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"], "amountIn": [ "10000000000000000000", "10000000", "10000000" ], "slippage": "50" }' | jq ``` ### LST Staking Entry Transform base tokens directly into staked liquid staking positions with a single call. **Example**: Converting 1 ETH to stETH (Lido Staked ETH) in one step * **Input**: 1 ETH * **Slippage**: 0.5% * **Output**: stETH ```typescript SDK theme={null} import { parseUnits } from "ethers/lib/utils"; const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token Addresses const ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const stETH = "0xae7ab96520de3a18e5e111b5eaab095312d7fe84"; // Define amount const amountIn = parseUnits("1", 18); // 1 ETH const route = await ensoClient.getRouteData({ chainId, fromAddress, receiver: fromAddress, routingStrategy: "router", tokenIn: [ETH], tokenOut: [stETH], amountIn: [amountIn], slippage: "50" // 0.5% }); ``` ```bash theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/route' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "router", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], "tokenOut": ["0xae7ab96520de3a18e5e111b5eaab095312d7fe84"], "amountIn": ["1000000000000000000"], "slippage": "50" }' | jq ```
### Yield Position Entry Enter yield-generating positions from base assets. **Example**: Moving from 1 WETH to a Yearn vault (yvWETH) * **Input**: 1 WETH Output: yvWETH (exact amount depends on the vault's share price) * **Slippage**: 0.5% ```ts SDK theme={null} const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token Addresses const WETH = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; const yvWETH = "0xa258c4606ca8206d8aa700ce2143d7db854d168c"; // Define amount const amountIn = parseUnits("1", 18); // 1 WETH const route = await ensoClient.getRouteData({ chainId, fromAddress, receiver: fromAddress, routingStrategy: "router", tokenIn: [WETH], tokenOut: [yvWETH], amountIn: [amountIn], slippage: "50" // 0.5% }); ``` ```bash theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/route' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "router", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"], "tokenOut": ["0xa258c4606ca8206d8aa700ce2143d7db854d168c"], "amountIn": ["1000000000000000000"], "slippage": "50" }' | jq ```
### Position Exit (Single Token) Exit completely from a DeFi position back to a single base token. **Example**: Converting 1 yvWETH (Yearn ETH vault) back to WETH * **Input**: 1 yvWETH * **Output**: WETH (actual amount depends on accrued yield) * **Slippage**: 0.5% ```typescript SDK theme={null} import { parseUnits } from "ethers/lib/utils"; const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token Addresses const yvWETH = "0xa258c4606ca8206d8aa700ce2143d7db854d168c"; const WETH = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; // Define amount const amountIn = parseUnits("1", 18); // 1 yvWETH const route = await ensoClient.getRouteData({ chainId, fromAddress, receiver: fromAddress, routingStrategy: "router", tokenIn: [yvWETH], tokenOut: [WETH], amountIn: [amountIn], slippage: "50" // 0.5% }); ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/route' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "router", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xa258c4606ca8206d8aa700ce2143d7db854d168c"], "tokenOut": ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"], "amountIn": ["1000000000000000000"], "slippage": "50" }' ```
### LP Position Entry Enter into LP token positions with automatic routing and slippage protection. **Example**: Going from 1 ETH to ETH/USDC Uniswap LP tokens * **Output**: \~0.92 ETH/USDC LP tokens (varies with pool composition) * **Slippage**: 1% ```ts SDK theme={null} const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token Addresses const ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const uniswap_ETH_USDC_LP = "0x06325440d014e39736583c165c2963ba99faf14e"; // Define amount const amountIn = parseUnits("1", 18); // 1 ETH const route = await ensoClient.getRouteData({ chainId, fromAddress, receiver: fromAddress, routingStrategy: "router", tokenIn: [ETH], tokenOut: [uniswap_ETH_USDC_LP], amountIn: [amountIn], slippage: "100" // 1% }); ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/route' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "router", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], "tokenOut": ["0x06325440d014e39736583c165c2963ba99faf14e"], "amountIn": ["1000000000000000000"], "slippage": "100" }' | jq ```
### Zap into a Morpho Blue Vault Zap a Morpho USDC vault position, represented by `0xc1fc3492f7b9c64871389d2a223eef6ccc165fb0`. **Example**: Going from 1 ETH to Morpho USDC position * **Output**: Morpho Blue USDC vault tokens * **Slippage**: 3% ```typescript SDK theme={null} import { parseUnits } from "ethers/lib/utils"; const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token Addresses const ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const morphoUsdcVault = "0xBEeFFF209270748ddd194831b3fa287a5386f5bC"; // Define amount const amountIn = parseUnits("1", 18); // 1 ETH const route = await ensoClient.getRouteData({ chainId, fromAddress, receiver: fromAddress, routingStrategy: "router", tokenIn: [ETH], tokenOut: [morphoUsdcVault], amountIn: [amountIn], slippage: "300" // 3% }); ``` ```bash theme={null} curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer 1e02632d-6feb-4a75-a157-documentation" \ -d '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "amountIn": ["1000000000000000000"], "slippage": "300", "tokenIn": ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], "tokenOut": ["0xBEeFFF209270748ddd194831b3fa287a5386f5bC"], "routingStrategy": "router" }' \ "https://api.enso.finance/api/v1/shortcuts/route" \ | jq ``` ### Simple LST Zapping Direct entry into or exit from liquid staking tokens. **Example**: Converting 1 stETH back to ETH * **Input**: 1 stETH (Lido Staked ETH) * **Output**: ETH (varies with current discount/premium) * **Slippage**: 1% ```ts SDK theme={null} const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token Addresses const stETH = "0xae7ab96520de3a18e5e111b5eaab095312d7fe84"; const ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; // Define amount const amountIn = parseUnits("1", 18); // 1 stETH const route = await ensoClient.getRouteData({ chainId, fromAddress, receiver: fromAddress, routingStrategy: "router", tokenIn: [stETH], tokenOut: [ETH], amountIn: [amountIn], slippage: "100" // 1% }); ``` ```bash theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/route' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "router", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xae7ab96520de3a18e5e111b5eaab095312d7fe84"], "tokenOut": ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], "amountIn": ["1000000000000000000"], "slippage": "100" }' | jq ``` *Note*: Limited to simple LST interactions without complex staking steps. Use Bundle API for multi-step LST staking flows. ## 2. Bundling DeFi Actions The Bundle API (POST `/v1/shortcuts/bundle`) excels at orchestrating complex sequences of operations.
### Multi-Position Entry Splitting funds across several positions simultaneously **Example**: Distributing 1 ETH into three LST tokens in one transaction * **Input**: 1 ETH * **Slippage**: 1% for each conversion * **Outputs**: 1. stETH (Lido Staked ETH) 2. rETH (Rocket Pool ETH) 3. cbETH (Coinbase Staked ETH) * **Process**: 1. Convert 1/3 ETH (0.333 ETH) to stETH 2. Convert 1/3 ETH (0.333 ETH) to rETH 3. Convert 1/3 ETH (0.334 ETH) to cbETH ```typescript SDK theme={null} import { parseUnits } from "ethers/lib/utils"; const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token Addresses const ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const stETH = "0xae7ab96520de3a18e5e111b5eaab095312d7fe84"; const rETH = "0xae78736cd615f374d3085123a210448e74fc6393"; const cbETH = "0xbe9895146f7af43049ca1c1ae358b0541ea49704"; // Define amounts const amountToStEth = parseUnits("0.333", 18); const amountToREth = parseUnits("0.333", 18); const amountToCbEth = parseUnits("0.334", 18); const bundle = await ensoClient.getBundleData( { chainId, fromAddress, routingStrategy: "delegate", }, [ { protocol: "enso", action: "route", args: { tokenIn: ETH, tokenOut: stETH, amountIn: amountToStEth, slippage: "100", }, }, { protocol: "enso", action: "route", args: { tokenIn: ETH, tokenOut: rETH, amountIn: amountToREth, slippage: "100", }, }, { protocol: "enso", action: "route", args: { tokenIn: ETH, tokenOut: cbETH, amountIn: amountToCbEth, slippage: "100", }, }, ], ); ``` ```bash theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "tokenOut": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", "amountIn": "333000000000000000", "slippage": "100" } }, { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "tokenOut": "0xae78736cd615f374d3085123a210448e74fc6393", "amountIn": "333000000000000000", "slippage": "100" } }, { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "tokenOut": "0xbe9895146f7af43049ca1c1ae358b0541ea49704", "amountIn": "334000000000000000", "slippage": "100" } } ]' | jq ```
### Single-Asset Zap into Uniswap V3 Concentrated Liquidity Provide liquidity to a two-asset Uniswap V3 pool using a single token as input. Enso automatically handles swapping for the second token and balancing the pair before depositing. **Example**: Use AAVE to provide concentrated liquidity to a WETH/AAVE pool on Uniswap v3 on Arbitrum. * **Input**: 10 AAVE * **Output token**: the `NonfungiblePositionManager` that mints and manages NFT-based receipts for provided liquidity. * **Final Result**: A Uniswap V3 NFT representing a concentrated liquidity position in the WETH/AAVE pool. * **Process**: 1. The `enso.split` action takes the input AAVE and swaps the optimal amount for WETH to create a balanced pair required by the Uniswap pool. 2. The `uniswap-v3.depositclmm` action takes the resulting WETH and AAVE from the previous step. 3. It deposits both tokens as liquidity into the specified pool within the defined tick range (`25320` to `25980`). ```ts SDK theme={null} const chainId = 42161; // Arbitrum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token and Protocol Addresses const tokenIn_AAVE = "0xba5ddd1f9d7f570dc94a51479a000e3bce967196"; const tokenOut_WETH = "0x82af49447d8a07e3bd95bd0d56f35241523fbab1"; const uniswapManager = "0xc36442b4a4522e871399cd717abdd847ab11fe88"; // Define amount const amountIn = parseUnits("10", 18); // 10 AAVE const bundle = await ensoClient.getBundleData( { chainId, fromAddress, routingStrategy: "router", }, [ { // Split AAVE into 2 equal parts // Converts the first half into WETH // needed for AAVE/WETH pool protocol: "enso", action: "split", args: { tokenIn: tokenIn_AAVE, tokenOut: [tokenOut_WETH, tokenIn_AAVE], amountIn: amountIn, }, }, { protocol: "uniswap-v3", action: "depositclmm", args: { tokenOut: uniswapManager, ticks: [25320, 25980], tokenIn: [tokenOut_WETH, tokenIn_AAVE], poolFee: "3000", amountIn: [ // use output from the split call { useOutputOfCallAt: 0, index: 0 }, { useOutputOfCallAt: 0, index: 1 }, ], }, }, ]); const approvalData = await client.getApprovalData({ amount: amountIn, chainId, fromAddress, tokenAddress: tokenIn_AAVE, }); // Approve Enso Router contract (bundle.tx.to) to operate with tokens await signEoa(approvalData.tx, approvalData.gas); // Sign and send transaction with simulated gas to out-of-gas errors await signEoa(bundle.tx, bundle.gas); ``` ```bash cURL theme={null} curl -X POST \ "https://api.enso.finance/api/v1/shortcuts/bundle?chainId=42161&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=router" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d "[ { "protocol": "enso", "action": "split", "args": { "tokenIn": "0xba5ddd1f9d7f570dc94a51479a000e3bce967196", "tokenOut": [ "0x82af49447d8a07e3bd95bd0d56f35241523fbab1", "0xba5ddd1f9d7f570dc94a51479a000e3bce967196" ], "amountIn": "10000000000000000000" } }, { "protocol": "uniswap-v3", "action": "depositclmm", "args": { "tokenOut": "0xc36442b4a4522e871399cd717abdd847ab11fe88", "ticks": [ 25320, 25980 ], "tokenIn": [ "0x82af49447d8a07e3bd95bd0d56f35241523fbab1", "0xba5ddd1f9d7f570dc94a51479a000e3bce967196" ], "poolFee": "3000", "amountIn": [ { "useOutputOfCallAt": 0, "index": 0 }, { "useOutputOfCallAt": 0, "index": 1 } ] } } ]" | jq ``` ### Multiple-Asset Zap to SushiSwap V3 LP To deposit into Sushiswap V3 `AUSD/USDC` poool, you need to use the `bundle` API. ```mermaid theme={null} flowchart LR A((USDC)) --> B{enso.split} subgraph split ["enso.split"] B -->|swap via
enso| E((AUSD)) B -->|keep as
USDC| F((USDC)) end E -->|depositclmm via
sushiswap-v3| G((LP NFT)) F -->|depositclmm via
sushiswap-v3| G ``` **Bundle Design**: * Input of 100 `USDC` must be split into 2 tokens: `AUSD` and `USDC`, using Enso's `split` action that converts 50% of USDC into AUSD, and keeps the rest untouched * Deposit using `depositclmm` action of `sushiswap-v3` protocol. * `tokenIn` are the pool's tokens (`USDC/AUSD`) * `amountIn` is an array of amounts obtained from the split into `USDC` and `AUSD` respectively, using dynamic quantity reference (`useOutputOfCallAt`). * The `tokenOut` value is the address of Sushiswap's position manager contract. * Provide correct fee and ticks. ```ts linenums="1" theme={null} export async function sushiswapV3() { const chainId = 747474; const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; const tokenIn_USDC = "0x203A662b0BD271A6ed5a60EdFbd04bFce608FD36"; const tokenOut_AUSD = "0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a"; const sushiswapManager = "0x2659C6085D26144117D904C46B48B6d180393d27"; const amountIn = parseUnits("100", 6); // 100 USDC const bundle = await client.getBundleData( { chainId, fromAddress, routingStrategy: "router", }, [ { // Split USDC into 2 parts for the LP position protocol: "enso", action: "split", args: { tokenIn: tokenIn_USDC, tokenOut: [tokenOut_AUSD, tokenIn_USDC], amountIn: amountIn.toString(), }, }, { protocol: "sushiswap-v3", action: "depositclmm", args: { tokenOut: sushiswapManager, ticks: [-114, -86], poolFee: "100", tokenIn: [tokenOut_AUSD, tokenIn_USDC], amountIn: [ { useOutputOfCallAt: 0, index: 0 }, // AUSD from split { useOutputOfCallAt: 0, index: 1 }, // USDC from split ], }, }, ] ); const approvalData = await client.getApprovalData({ amount: amountIn.toString(), chainId, fromAddress, tokenAddress: tokenIn_USDC, }); // Approve Enso Router contract to operate with USDC await sendEoa(approvalData.tx, approvalData.gas); // Execute the bundle transaction await sendEoa(bundle.tx, bundle.gas); return bundle; } ``` ### Staking Pipeline Chain multiple actions together to create a complete Curve LP staking workflow. **Example**: Creating a staked Curve 3pool position starting with 1 ETH * **Input**: 1 ETH * **Final Output**: 3pool LP tokens staked in Curve gauge * **Process**: 1. Swap 1 ETH to USDC 2. Deposit USDC into Curve 3pool to get 3pool LP tokens 3. Stake 3pool LP tokens in the Curve gauge ```typescript SDK theme={null} import { parseUnits } from "ethers/lib/utils"; const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token and Protocol Addresses const ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const USDC = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; const curve3poolLp = "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"; const curve3poolGauge = "0xbFcF63294aD7105dEa65aA58F8AE5BE2D9d0952A"; const curve3pool = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7"; // Define amount const amountIn = parseUnits("1", 18); // 1 ETH const bundle = await ensoClient.getBundleData( { chainId, fromAddress, routingStrategy: "delegate", }, [ { protocol: "enso", action: "route", args: { tokenIn: ETH, tokenOut: USDC, amountIn: amountIn, slippage: "300", }, }, { protocol: "curve", action: "deposit", args: { tokenIn: USDC, tokenOut: curve3poolLp, amountIn: { useOutputOfCallAt: 0 }, primaryAddress: curve3pool, }, }, { protocol: "curve-gauge", action: "deposit", args: { tokenIn: curve3poolLp, tokenOut: curve3poolGauge, amountIn: { useOutputOfCallAt: 1 }, primaryAddress: curve3poolGauge, }, }, ]); ``` ```bash theme={null} curl -X 'POST' \ "https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate" \ -H 'accept: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -H 'Content-Type: application/json' \ -d '[ { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "tokenOut": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "amountIn": '1000000000000000000', "slippage": "300" } }, { "protocol": "curve", "action": "deposit", "args": { "tokenIn": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "tokenOut": "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", "amountIn": { "useOutputOfCallAt": 0 }, "primaryAddress": "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7" } }, { "protocol": "curve-gauge", "action": "deposit", "args": { "tokenIn": "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", "tokenOut": "0xbFcF63294aD7105dEa65aA58F8AE5BE2D9d0952A", "amountIn": { "useOutputOfCallAt": 1 }, "primaryAddress": "0xbFcF63294aD7105dEa65aA58F8AE5BE2D9d0952A" } } ]' | jq ```
### Portfolio Rebalancing Adjusting position sizes across multiple protocols. **Example**: Rebalancing from 70% `ETH` + 30% `USDC` to 50% `ETH` + 50% `USDC` across Aave positions * **Input**: 0.6 WETH (for reallocation) * **Output**: 1. 0.4 WETH deposited to Aave (aWETH) 2. \~\$580 USDC (from 0.2 WETH) deposited to Aave (aUSDC) * **Process**: 1. Convert 0.2 WETH to USDC 2. Deposit 0.4 WETH into Aave (aWETH position) 3. Deposit the acquired USDC into Aave (aUSDC position) ```ts SDK theme={null} const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token and Protocol Addresses const WETH = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; const USDC = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; const aWETH = "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8"; const aUSDC = "0xbcca60bb61934080951369a648fb03df4f96263c"; const aaveV3Pool = "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2"; // Define amounts const amountToSwap = parseUnits("0.2", 18); const amountToDeposit = parseUnits("0.4", 18); const bundle = await ensoClient.getBundleData( { chainId, fromAddress, routingStrategy: "delegate", }, [ { protocol: "enso", action: "route", args: { tokenIn: WETH, tokenOut: USDC, amountIn: amountToSwap, slippage: "100", }, }, { protocol: "aave-v3", action: "deposit", args: { tokenIn: WETH, tokenOut: aWETH, amountIn: amountToDeposit, primaryAddress: aaveV3Pool, }, }, { protocol: "aave-v3", action: "deposit", args: { tokenIn: USDC, tokenOut: aUSDC, amountIn: { useOutputOfCallAt: 0 }, primaryAddress: aaveV3Pool, }, }, ]); ``` ```bash theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "tokenOut": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "amountIn": "200000000000000000", "slippage": "100" } }, { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "tokenOut": "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", "amountIn": "400000000000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "tokenOut": "0xbcca60bb61934080951369a648fb03df4f96263c", "amountIn": { "useOutputOfCallAt": 0 }, "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } } ]' | jq ```
### Position Migration Moving from one protocol to another **Example**: Migrating 1 aWETH from Aave to Compound's cETH * **Input**: 1 aWETH (Aave WETH) * **Output**: cETH (Compound ETH) * **Process**: 1. Withdraw 1 WETH from Aave by redeeming aWETH 2. Unwrap WETH to ETH 3. Deposit ETH into Compound to get cETH ```typescript SDK theme={null} import { parseUnits } from "ethers/lib/utils"; const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token and Protocol Addresses const aWETH = "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8"; const WETH = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; const ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const cETH = "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5"; const aaveV3Pool = "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2"; const compoundCEth = "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5"; // Define amount const amountIn = parseUnits("1", 18); // 1 aWETH const bundle = await ensoClient.getBundleData( { chainId, fromAddress, routingStrategy: "delegate", }, [ { protocol: "aave-v3", action: "redeem", args: { tokenIn: aWETH, tokenOut: WETH, amountIn: amountIn, primaryAddress: aaveV3Pool, }, }, { protocol: "wrapped-native", action: "redeem", args: { tokenIn: WETH, tokenOut: ETH, amountIn: { useOutputOfCallAt: 0 }, primaryAddress: WETH, }, }, { protocol: "compound-v2", action: "deposit", args: { tokenIn: ETH, tokenOut: cETH, amountIn: { useOutputOfCallAt: 1 }, primaryAddress: compoundCEth, }, }, ], ); ``` ```bash theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "aave-v3", "action": "redeem", "args": { "tokenIn": "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", "tokenOut": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "amountIn": "1000000000000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { "protocol": "wrapped-native", "action": "redeem", "args": { "tokenIn": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "tokenOut": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "amountIn": { "useOutputOfCallAt": 0 }, "primaryAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" } }, { "protocol": "compound-v2", "action": "deposit", "args": { "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "tokenOut": "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5", "amountIn": { "useOutputOfCallAt": 1 }, "primaryAddress": "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5" } } ]' | jq ```
### Leveraged Positions Creating leveraged positions through multiple actions **Example**: Creating a 2x ETH position using Aave * **Input**: 1 WETH initial collateral * **Final Result**: WETH worth of collateral in Aave * **Process**: 1. Deposit 1 WETH as collateral in Aave 2. Borrow \~1,000 USDC against the WETH collateral 3. Swap the borrowed 1,000 USDC back to \~0.35 WETH 4. Deposit the additional WETH back into Aave as more collateral ```ts SDK theme={null} const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token and Protocol Addresses const WETH = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; const aWETH = "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8"; const USDC = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; const aaveV3Pool = "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2"; // Define amounts const initialDeposit = parseUnits("1", 18); const borrowAmount = parseUnits("1000", 6); const bundle = await ensoClient.getBundleData( { chainId, fromAddress, routingStrategy: "delegate", }, [ { protocol: "aave-v3", action: "deposit", args: { tokenIn: WETH, tokenOut: aWETH, amountIn: initialDeposit, primaryAddress: aaveV3Pool, }, }, { protocol: "aave-v3", action: "borrow", args: { collateral: WETH, tokenOut: USDC, amountOut: borrowAmount, primaryAddress: aaveV3Pool, }, }, { protocol: "enso", action: "route", args: { tokenIn: USDC, tokenOut: WETH, amountIn: { useOutputOfCallAt: 1 }, slippage: "100", }, }, { protocol: "aave-v3", action: "deposit", args: { tokenIn: WETH, tokenOut: aWETH, amountIn: { useOutputOfCallAt: 2 }, primaryAddress: aaveV3Pool, }, }, ], ); ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "tokenOut": "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", "amountIn": "1000000000000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { "protocol": "aave-v3", "action": "borrow", "args": { "collateral": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "tokenOut": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "amountOut": "1000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "tokenOut": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "amountIn": { "useOutputOfCallAt": 1 }, "slippage": "100" } }, { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "tokenOut": "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", "amountIn": { "useOutputOfCallAt": 2 }, "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } } ]' | jq ```
### Zap into multiple LPs Multi-step entry into or exit from liquid staking tokens with additional operations. **Example**: Creating diversified LP and LST positions with 1 ETH * **Input**: 1 ETH split evenly * **Slippage**: 3% for each conversion * **Process**: 1. Convert 0.5 ETH to stETH/ETH Curve LP tokens 2. Convert 0.5 ETH to BAL/WETH Balancer LP tokens ```ts SDK theme={null} import { parseUnits } from "ethers/lib/utils"; const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token Addresses const ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const curve_stETH_ETH_Lp = "0x06325440D014e39736583c165C2963BA99fAf14E"; const balancer_BAL_WETH_Lp = "0x5c6Ee304399DBdB9C8Ef030aB642B10820DB8F56"; // Define amount const amountIn = parseUnits("0.5", 18); const bundle = await ensoClient.getBundleData( { chainId, fromAddress, routingStrategy: "delegate", }, [ { protocol: "enso", action: "route", args: { tokenIn: ETH, tokenOut: curve_stETH_ETH_Lp, amountIn: amountIn, slippage: "300", }, }, { protocol: "enso", action: "route", args: { tokenIn: ETH, tokenOut: balancer_BAL_WETH_Lp, amountIn: amountIn, slippage: "300", }, }, ]); ``` ```bash theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "tokenOut": "0x06325440D014e39736583c165C2963BA99fAf14E", "amountIn": "500000000000000000", "slippage": "300" } }, { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "tokenOut": "0x5c6Ee304399DBdB9C8Ef030aB642B10820DB8F56", "amountIn": "500000000000000000", "slippage": "300" } } ]' | jq ```
### Yield Compounding Flow Automate yield compounding by harvesting rewards, swapping, and redepositing in a single transaction. **Example**: Compounding Curve gauge rewards back into the stETH/ETH pool * **Input**: Existing position in stETH/ETH Curve gauge * **Slippage**: 3% * **Process**: 1. Harvest accumulated wstETH rewards from the Curve gauge 2. Convert wstETH rewards to stETH 3. Deposit stETH back into the stETH/ETH Curve pool ```ts SDK theme={null} // Token and Protocol Addresses const rewardToken_wstETH = "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0"; const depositToken_stETH = "0xae7ab96520de3a18e5e111b5eaab095312d7fe84"; const lpToken_curve_stETH_ETH = "0x06325440d014e39736583c165c2963ba99faf14e"; const curveGauge = "0x182B723a58739a9c974cFDB385ceaDb237453c28"; const curvePool = "0xDC24316b9AE028F1497c275EB9192a3Ea0f67022"; const bundle = await ensoClient.getBundleData( { chainId, fromAddress, receiver: fromAddress, routingStrategy: "delegate", }, [ { protocol: "curve-gauge", action: "harvest", args: { token: rewardToken_wstETH, primaryAddress: curveGauge, }, }, { protocol: "enso", action: "route", args: { tokenIn: rewardToken_wstETH, tokenOut: depositToken_stETH, amountIn: { useOutputOfCallAt: 0 }, slippage: "300", }, }, { protocol: "curve", action: "deposit", args: { tokenIn: depositToken_stETH, tokenOut: lpToken_curve_stETH_ETH, amountIn: { useOutputOfCallAt: 1 }, primaryAddress: curvePool, }, }, ], ); ``` ```bash theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate&receiver=0xd8da6bf26964af9d7eed9e03e53415d37aa96045' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "curve-gauge", "action": "harvest", "args": { "token": "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0", "primaryAddress": "0x182B723a58739a9c974cFDB385ceaDb237453c28" } }, { "protocol": "enso", "action": "route", "args": { "tokenIn": "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0", "tokenOut": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", "amountIn": { "useOutputOfCallAt": 0 }, "slippage": "300" } }, { "protocol": "curve", "action": "deposit", "args": { "tokenIn": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", "tokenOut": "0x06325440d014e39736583c165c2963ba99faf14e", "amountIn": { "useOutputOfCallAt": 1 }, "primaryAddress": "0xDC24316b9AE028F1497c275EB9192a3Ea0f67022" } } ] ' | jq ``` ### Liquid Staking Derivative Looping Create a leveraged position with liquid staking tokens through recursive borrowing and depositing in a lending protocol. **Example**: Implement a multi-loop leveraged position on Lido Staked ETH (wstETH) using Aave V3 as the lending platform. * **Input**: 10 wstETH * **Final Result**: \~18.32 wstETH deposited with \~8.32 wstETH borrowed (1.83x leverage) * **Process**: 1. Deposit 10 wstETH as collateral into Aave V3 2. Borrow 5.4 wstETH against your deposited collateral 3. Deposit the borrowed wstETH back as additional collateral 4. Borrow 2.916 wstETH against your increased collateral 5. Deposit this amount back again as additional collateral ```typescript SDK theme={null} import { parseUnits } from "ethers/lib/utils"; const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token and Protocol Addresses const wstETH = "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"; const aWstETH = "0x0B925eD163218f6662a35E0F0371Ac234F9E9371"; const aaveV3Pool = "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2"; // Define amounts const initialDeposit = parseUnits("10", 18); const firstBorrow = parseUnits("5.4", 18); const secondBorrow = parseUnits("2.916", 18); const bundle = await ensoClient.getBundleData( { chainId, fromAddress, routingStrategy: "delegate", }, [ { protocol: "aave-v3", action: "deposit", args: { tokenIn: wstETH, tokenOut: aWstETH, amountIn: initialDeposit, primaryAddress: aaveV3Pool, }, }, { protocol: "aave-v3", action: "borrow", args: { collateral: wstETH, tokenOut: wstETH, amountOut: firstBorrow, primaryAddress: aaveV3Pool, }, }, { protocol: "aave-v3", action: "deposit", args: { tokenIn: wstETH, tokenOut: aWstETH, amountIn: firstBorrow, primaryAddress: aaveV3Pool, }, }, { protocol: "aave-v3", action: "borrow", args: { collateral: wstETH, tokenOut: wstETH, amountOut: secondBorrow, primaryAddress: aaveV3Pool, }, }, { protocol: "aave-v3", action: "deposit", args: { tokenIn: wstETH, tokenOut: aWstETH, amountIn: secondBorrow, primaryAddress: aaveV3Pool, }, }, ], ); ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "tokenOut": "0x0B925eD163218f6662a35E0F0371Ac234F9E9371", "amountIn": "10000000000000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { "protocol": "aave-v3", "action": "borrow", "args": { "collateral": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "tokenOut": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "amountOut": "5400000000000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "tokenOut": "0x0B925eD163218f6662a35E0F0371Ac234F9E9371", "amountIn": "5400000000000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { "protocol": "aave-v3", "action": "borrow", "args": { "collateral": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "tokenOut": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "amountOut": "2916000000000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", "tokenOut": "0x0B925eD163218f6662a35E0F0371Ac234F9E9371", "amountIn": "2916000000000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } } ]' | jq ```
### Cross-Chain Route-Bridge Execute a route and bridge tokens to another chain in a single transaction using the route-bridge functionality. **Example**: Bridging 1 ETH from Ethereum to Optimism and converting to USDT * **Input**: 1 ETH on Ethereum * **Output**: USDT on Optimism * **Process**: 1. Route 1 ETH to USDT on Ethereum 2. Bridge the resulting USDT to Optimism 3. Receive USDT on Optimism **Important**: When using `destinationChainId`, you **must** include `refundReceiver` to handle any potential refunds from failed bridge operations. ```ts SDK theme={null} const chainId = 1; // Ethereum const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token Addresses const ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const USDT_optimism = "0x94b008aa00579c1307b0ef2c499ad98a8ce58e58"; // Define amount const amountIn = parseUnits("1", 18); // 1 ETH const bundle = await ensoClient.getBundleData( { chainId, fromAddress, routingStrategy: "delegate", }, [ { protocol: "enso", action: "route", args: { tokenIn: ETH, // ETH on Ethereum tokenOut: USDT_optimism, // USDT on Optimism amountIn: amountIn, destinationChainId: 10, // Optimism refundReceiver: fromAddress, // Required for route-bridge }, }, ], ); ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "tokenOut": "0x94b008aa00579c1307b0ef2c499ad98a8ce58e58", "amountIn": "1000000000000000000", "destinationChainId": 10, } } ]' | jq ```

Updated {date_0}

# Authentication Source: https://docs.enso.build/pages/build/get-started/authentication Obtain Enso API key to access the Enso API. export const date_0 = "2025-04-11" ## Obtain API Key 1. Create an API key using [Enso Dashboard](https://developers.enso.build). 2. Securely store your API key and make it available in your environment: ```bash authentication.sh theme={null} ENSO_API_KEY="$ENSO_API_KEY" echo $ENSO_API_KEY >> .env git ignore .env source .env ``` ## Test ```bash theme={null} curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ENSO_API_KEY" \ "http://api.enso.finance/api/v1/shortcuts/route?chainId=1&fromAddress=0x9008D19f58AAbD9eD0D60971565AA8510560ab41&tokenIn=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&tokenOut=0x5c6Ee304399DBdB9C8Ef030aB642B10820DB8F56&amountIn=326880000000000000000&tokenInAmountToTransfer=326880000000000000000" \ | jq ``` ## Rate Limiting API calls are limited to 10 RPS (60 requests per minute). It can be increased on demand. If you exceed the limit, you'll receive a `429 Too Many Requests` error.

Updated {date_0}

# Get Balances Source: https://docs.enso.build/pages/build/get-started/balances Get balances of tokens in a wallet address. ## Balances Information The `/balances` endpoint returns all wallet balances across protocols and networks Enso supports. **API Reference:** [GET `/v1/wallet/balances`](/api-reference/defi/wallet-balances) ```json theme={null} [ { "token": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "amount": "7568910913750864", "decimals": 18, "price": 2559.27, "name": "ETH", "symbol": "ETH", "logoUri": "https://static.debank.com/image/coin/logo_url/eth/6443cdccced33e204d90cb723c632917.png" }, { "token": "0x030ba81f1c18d280636f32af80b9aad02cf0854e", "amount": "2455429", "decimals": 18, "price": 2509.83, "name": "Aave interest bearing WETH", "symbol": "aWETH", "logoUri": "https://static.debank.com/image/eth_token/logo_url/0x030ba81f1c18d280636f32af80b9aad02cf0854e/b6910e236da889f08602435e79c08f98.png" } ] ``` ## Example Request ```ts EnsoSDK theme={null} import { EnsoClient } from '@ensofinance/sdk'; // Initialize the client with your API key const enso = new EnsoClient({ apiKey: 'YOUR_API_KEY' // Replace with your actual API key }); // Get user balances across all protocols on a specific chain async function getUserBalances(chainId: number, address: string) { try { const balances = await enso.getBalances({ chainId, eoaAddress: address, useEoa: true // Get balances for EOA; set to false for Enso Smart Wallet }); console.log(`Balances for ${address} on chain ${chainId}:`, balances); return balances; } catch (error) { console.error('Error fetching user balances:', error); throw error; } } // Get user balances on Ethereum getUserBalances(1, '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'); ``` ```bash cURL theme={null} curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ENSO_API_KEY" \ "https://api.enso.finance/api/v1/wallet/balances?chainId=1&eoaAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&useEoa=true" \ | jq ``` # Bundling Actions Source: https://docs.enso.build/pages/build/get-started/bundling-actions Bundle several DeFi actions into a single transaction using the `bundle` API. The Bundle API is Enso's **multi-action orchestration engine** that executes complex DeFi workflows atomically. **Would `route` do the job?**
The `route` API might be the simpler way to route your assets. Before using the bundle API, check if `route` would work using [happypath](https://happypath.enso.build).
While the Route API automatically finds optimal paths between positions, the Bundle API gives you precise control over each action in your sequence - perfect for custom strategies, multi-protocol operations, and advanced DeFi automation. **Bundle vs Route**: Choose Bundle when you need specific execution order, multi-protocol interactions, or actions beyond simple swaps and deposits. Use Route when you want Enso to handle the optimization automatically. **Atomic execution**: All actions in a bundle succeed together or revert entirely - no partial executions or stuck funds. ## Quick Start The Bundle API accepts an array of actions that execute sequentially. Each action can use outputs from previous actions, enabling complex workflows impossible with separate transactions. Bundle supports 15+ action types across 50+ protocols. Common actions include `swap`, `deposit`, `borrow`, `harvest`, and `bridge`. See our [Actions Reference](/pages/build/reference/actions) for the complete list. ```typescript theme={null} // Harvest rewards → Swap to base token → Redeposit [ { protocol: "curve-gauge", action: "harvest", args: { token: "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0", primaryAddress: "0x182B723a58739a9c974cFDB385ceaDb237453c28" } }, { protocol: "enso", action: "route", args: { tokenIn: "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0", tokenOut: "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", amountIn: { useOutputOfCallAt: 0 }, // Use harvested amount slippage: "300" } }, { protocol: "curve", action: "deposit", args: { tokenIn: "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", tokenOut: "0x06325440d014e39736583c165c2963ba99faf14e", amountIn: { useOutputOfCallAt: 1 }, // Use swapped amount primaryAddress: "0xDC24316b9AE028F1497c275EB9192a3Ea0f67022" } } ] ``` ```typescript theme={null} // Split 1 ETH across three liquid staking tokens [ { protocol: "enso", action: "route", args: { tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", tokenOut: "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", // stETH amountIn: "333000000000000000", slippage: "100" } }, { protocol: "enso", action: "route", args: { tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", tokenOut: "0xae78736cd615f374d3085123a210448e74fc6393", // rETH amountIn: "333000000000000000", slippage: "100" } }, { protocol: "enso", action: "route", args: { tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", tokenOut: "0xbe9895146f7af43049ca1c1ae358b0541ea49704", // cbETH amountIn: "334000000000000000", slippage: "100" } } ] ``` ```typescript theme={null} // Exit Aave → Enter Compound [ { protocol: "aave-v3", action: "redeem", args: { tokenIn: "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", // aWETH tokenOut: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH amountIn: "1000000000000000000", primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { protocol: "wrapped-native", action: "redeem", args: { tokenIn: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", tokenOut: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", amountIn: { useOutputOfCallAt: 0 }, primaryAddress: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" } }, { protocol: "compound-v2", action: "deposit", args: { tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", tokenOut: "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5", // cETH amountIn: { useOutputOfCallAt: 1 }, primaryAddress: "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5" } } ] ``` ```typescript theme={null} // Deposit → Borrow → Swap → Redeposit (2x leverage) [ { protocol: "aave-v3", action: "deposit", args: { tokenIn: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH tokenOut: "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", // aWETH amountIn: "1000000000000000000", // 1 WETH primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { protocol: "aave-v3", action: "borrow", args: { collateral: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", tokenOut: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC amountOut: "2000000000", // 2000 USDC primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { protocol: "enso", action: "route", args: { tokenIn: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", tokenOut: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", amountIn: { useOutputOfCallAt: 1 }, slippage: "100" } }, { protocol: "aave-v3", action: "deposit", args: { tokenIn: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", tokenOut: "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", amountIn: { useOutputOfCallAt: 2 }, primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } } ] ``` ## Core Concepts Each action requires: `protocol` (where to execute), `action` (what to do), and `args` (action-specific parameters). Actions execute in array order. Use `useOutputOfCallAt` to reference previous action outputs. This enables chaining without knowing amounts in advance - critical for harvesting, compounding, and multi-step strategies. All actions succeed or all revert. No partial executions, no stuck funds. Failed actions revert the entire bundle, protecting against incomplete workflows. One transaction instead of many. Bundle saves 20-40% on gas compared to separate transactions, plus reduced MEV exposure. Not all actions work for every protocol! To check which actions are supported per protocol, use the SDK's `getActionsBySlug` ([GET `/v1/actions/{protocol}`](/api-reference/integration/actions-for-protocol)) method. ## Request Structure Each action in the bundle array follows this structure: ```typescript theme={null} { protocol: string, // Protocol identifier (e.g., "aave-v3", "uniswap-v2") action: string, // Action type (e.g., "deposit", "swap", "borrow") args: { // Action-specific arguments tokenIn?: string, tokenOut?: string, amountIn?: string | { useOutputOfCallAt: number }, primaryAddress?: string, // ... other protocol-specific args } } ``` **Key parameters:** * **`primaryAddress`**: Protocol's main contract (pool, vault, router) * **`useOutputOfCallAt`**: Reference output from action at index N * **`receiver`**: Optional override for output recipient * **`slippage`**: Basis points for price protection (100 = 1%) ## Examples ### 0. Install & Authenticate You can interact with the API using Enso SDK or directly via REST API. ```bash npm theme={null} npm i @ensofinance/sdk ``` ```bash pnpm theme={null} pnpm i @ensofinance/sdk ``` ```bash yarn theme={null} yarn add @ensofinance/sdk ``` To use the API, authenticate using your [API key](/pages/build/get-started/authentication). ```typescript SDK theme={null} import { EnsoClient } from '@ensofinance/sdk'; const ensoClient = new EnsoClient({ apiKey: 'your-api-key-here' }); ``` ```bash Environment theme={null} export ENSO_API_KEY="your-api-key-here" ``` ### 1. Basic Bundle: Swap and Deposit Start with a simple two-action bundle that swaps ETH for USDC, then deposits into Aave. The first action (`route`) will invoke Enso's automatic routing engine and optimize ETH → USDC path, This simple example is completely achievable with [DeFi Swap and Routing](/pages/build/get-started/route). This is for illustrative purposes only. ```typescript SDK theme={null} const bundle = await ensoClient.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate" }, [ // Step 1: Swap ETH to USDC { protocol: "enso", action: "route", args: { tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH tokenOut: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC amountIn: "1000000000000000000", // 1 ETH slippage: "100" // 1% } }, // Step 2: Deposit USDC to Aave (fixed amount) { protocol: "aave-v3", action: "deposit", args: { tokenIn: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC tokenOut: "0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c", // aUSDC amountIn: "2000000000", // 2000 USDC primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } } ] ); // Execute the bundle await wallet.sendTransaction(bundle.tx); ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "tokenOut": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "amountIn": "1000000000000000000", "slippage": "100" } }, { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "tokenOut": "0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c", "amountIn": "2000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } } ]' | jq ``` **What's happening**: This bundle swaps 1 ETH for USDC, then deposits exactly 2000 USDC to Aave. Note the fixed amount in the second action - we'll make this dynamic next. ### 2. Dynamic Chaining: Harvest and Compound Use `useOutputOfCallAt` to chain actions dynamically. ```typescript SDK theme={null} const bundle = await ensoClient.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate" }, [ // Step 1: Split 1 ETH into 3 equal portions { protocol: "enso", action: "split", args: { tokenIn: ETH, tokenOut: [ETH, ETH, ETH], amountIn: "1000000000000000000", // 1 ETH receiver: userAddress, }, }, // Step 2: Route first portion to stETH { protocol: "enso", action: "route", args: { tokenIn: ETH, tokenOut: stETH, amountIn: { useOutputOfCallAt: [0, 0] }, // First output from split slippage: "100", receiver: userAddress, }, }, // Step 3: Route second portion to rETH { protocol: "enso", action: "route", args: { tokenIn: ETH, tokenOut: rETH, amountIn: { useOutputOfCallAt: [0, 1] }, // Second output from split slippage: "100", receiver: userAddress, }, }, // Step 4: Route third portion to cbETH { protocol: "enso", action: "route", args: { tokenIn: ETH, tokenOut: cbETH, amountIn: { useOutputOfCallAt: [0, 2] }, // Third output from split slippage: "100", receiver: userAddress, }, }, ] ); console.log('Compound tx ready:', bundle.tx); ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "curve-gauge", "action": "harvest", "args": { "token": "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0", "primaryAddress": "0x182B723a58739a9c974cFDB385ceaDb237453c28" } }, { "protocol": "enso", "action": "route", "args": { "tokenIn": "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0", "tokenOut": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", "amountIn": { "useOutputOfCallAt": 0 }, "slippage": "300" } }, { "protocol": "curve", "action": "deposit", "args": { "tokenIn": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", "tokenOut": "0x06325440d014e39736583c165c2963ba99faf14e", "amountIn": { "useOutputOfCallAt": 1 }, "primaryAddress": "0xDC24316b9AE028F1497c275EB9192a3Ea0f67022" } } ]' | jq ``` **Key concept**: `useOutputOfCallAt: 0` references the output from the first action (index 0). This enables compound strategies without knowing reward amounts in advance. ### 4. Leveraged Position Create a 2x leveraged position by borrowing against deposited collateral. ```typescript SDK theme={null} const bundle = await ensoClient.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate" }, [ // Deposit WETH as collateral { protocol: "aave-v3", action: "deposit", args: { tokenIn: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH tokenOut: "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", // aWETH amountIn: "1000000000000000000", // 1 WETH primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, // Borrow USDC against WETH { protocol: "aave-v3", action: "borrow", args: { collateral: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", tokenOut: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC amountOut: "2000000000", // 2000 USDC primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, // Swap borrowed USDC back to WETH { protocol: "enso", action: "route", args: { tokenIn: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", tokenOut: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", amountIn: { useOutputOfCallAt: 1 }, // All borrowed USDC slippage: "100" } }, // Deposit the additional WETH { protocol: "aave-v3", action: "deposit", args: { tokenIn: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", tokenOut: "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", amountIn: { useOutputOfCallAt: 2 }, // All swapped WETH primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } } ] ); console.log('2x leveraged WETH position created'); ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "tokenOut": "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", "amountIn": "1000000000000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { "protocol": "aave-v3", "action": "borrow", "args": { "collateral": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "tokenOut": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "amountOut": "2000000000", "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } }, { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "tokenOut": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "amountIn": { "useOutputOfCallAt": 1 }, "slippage": "100" } }, { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "tokenOut": "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", "amountIn": { "useOutputOfCallAt": 2 }, "primaryAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" } } ]' | jq ``` **Leverage mechanics**: Deposit → Borrow → Swap → Redeposit creates leveraged exposure. ### 5. Cross-chain Bundle with Callbacks Bridge assets and execute actions on the destination chain - all atomically. **What's happening**: The `callback` array executes atomically on the destination chain. If any callback action fails, the entire operation (including the bridge) reverts - true cross-chain atomicity! ```typescript SDK theme={null} export async function bridgeUsdcAndDepositToAave() { const bundle = await client.getBundleData( { chainId: ETHEREUM_CHAIN_ID, fromAddress: USER_ADDRESS, routingStrategy: "delegate", }, [ // Convert USDC to ETH for bridge fee { protocol: "enso", action: "route", args: { tokenIn: USDC_ETHEREUM, tokenOut: ETH_ADDRESS, amountIn: USDC_AMOUNT, slippage: "100", }, }, // Bridge ETH to Base with callback actions { protocol: "stargate", action: "bridge", args: { primaryAddress: STARGATE_PRIMARY_ADDRESS, destinationChainId: BASE_CHAIN_ID, tokenIn: ETH_ADDRESS, amountIn: { useOutputOfCallAt: 0 }, receiver: USER_ADDRESS, // These actions execute on Base after bridging! callback: [ { protocol: "enso", action: "balance", args: { token: ETH_ADDRESS, }, }, { protocol: "enso", action: "route", args: { tokenIn: ETH_ADDRESS, tokenOut: CBETH_BASE, // amountIn: "10000000000000", amountIn: { useOutputOfCallAt: 0 }, // Use bridged ETH slippage: "200", }, }, { protocol: "aave-v3", action: "deposit", args: { tokenIn: CBETH_BASE, tokenOut: ACBETH_BASE, amountIn: { useOutputOfCallAt: 1 }, // From the swap above primaryAddress: AAVE_V3_PRIMARY_ADDRESS, }, }, ], }, }, ] ); console.log("Cross-chain deposit ready:", bundle.tx); } // Addresses const ETHEREUM_CHAIN_ID = 1; const BASE_CHAIN_ID = 8453; // User addresses const USER_ADDRESS = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // Token addresses - Ethereum const USDC_ETHEREUM = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; const ETH_ADDRESS = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; // Token addresses - Base const CBETH_BASE = "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22"; const ACBETH_BASE = "0xcf3D55c10DB69f28fD1A75Bd73f3D8A2d9c595ad"; // Protocol addresses const STARGATE_PRIMARY_ADDRESS = "0x77b2043768d28e9c9ab44e1abfc95944bce57931"; const AAVE_V3_PRIMARY_ADDRESS = "0xA238Dd80C259a72e81d7e4664a9801593F98d1c5"; // Amounts const USDC_AMOUNT = "3000000000"; // 3000 USDC ``` ```bash cURL theme={null} curl -X POST \ 'https://api.enso.finance/api/v1/shortcuts/bundle?chainId=1&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&routingStrategy=delegate' \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -d '[ { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "tokenOut": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "amountIn": "3000000000", "slippage": "100" } }, { "protocol": "stargate", "action": "bridge", "args": { "primaryAddress": "0x77b2043768d28e9c9ab44e1abfc95944bce57931", "destinationChainId": 8453, "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "amountIn": { "useOutputOfCallAt": 0 }, "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "callback": [ { "protocol": "enso", "action": "route", "args": { "tokenIn": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "tokenOut": "0x2Ae3F1Ec7F328C4243D5eE", "amountIn": { "useOutputOfCallAt": 0 }, "slippage": "200" } }, { "protocol": "aave-v3", "action": "deposit", "args": { "tokenIn": "0x2Ae3F1Ec7F328C4243D5eE", "tokenOut": "0x078f358208685046a11C85e8ad32895DED33A249", "amountIn": { "useOutputOfCallAt": 0 }, "primaryAddress": "0xA238Dd80C259a72e81d7e4664a9801593F98d1c5" } } ] } } ]' | jq ``` ## Utility Actions Bundle API includes helper actions for safety and flow control: Get token balance mid-bundle: ```json theme={null} { "protocol": "enso", "action": "balance", "args": { "token": "0xa0b8...b48" } } ``` Apply slippage to any output: ```json theme={null} { "protocol": "enso", "action": "slippage", "args": { "amountOut": { "useOutputOfCallAt": 0 }, "bps": "100" } } ``` Enforce minimum amounts: ```json theme={null} { "protocol": "enso", "action": "minAmountOut", "args": { "amountOut": { "useOutputOfCallAt": 0 }, "minAmountOut": "1000000000" } } ``` Take protocol fees: ```json theme={null} { "protocol": "enso", "action": "fee", "args": { "token": "0xeee...eee", "amount": { "useOutputOfCallAt": 0 }, "bps": "250", "receiver": "0xfee...add" } } ``` ## Next Steps From here, you can explore other resources: * **[Actions Reference](/pages/build/reference/actions)**: Complete list of supported actions and protocols * **[Routing Strategies](/pages/build/reference/routing-strategies)**: Overview of `delegate` and `router` strategies for action execution\*\*.\*\* * **[Shortcuts Library](/pages/build/examples/shortcuts)**: 20+ production-ready bundle examples * **[Route API](/pages/build/get-started/route)**: When automatic routing is better than custom bundles # Crosschain Routing Source: https://docs.enso.build/pages/build/get-started/crosschain-routing Execute complex DeFi operations across multiple blockchains using bridge callbacks and post-bridge execution export const date_0 = "2025-09-30" Crosschain routing enables complex multichain workflows that execute DeFi operations across multiple blockchains atomically. Unlike simple token transfers, crosschain routing orchestrates sophisticated strategies that span several chains. Both `route` and `bundle` API operate in crosschain mode. For custom bundles, use the `bridge` action to facilitate cross-chain token transfers using Stargate. For example: bridge assets to chains where protocols exist, execute operations such as minting, then optionally bridge results back to your origin chain and deposit them in a yield-bearing position. ```mermaid theme={null} flowchart LR subgraph berachain ["🐻 Berachain"] USDC_BERA((USDC)) --> A1(( )) end A1 -.-> |balance
check| USDC_ETH((USDC)) subgraph ethereum ["🌐 Ethereum"] USDC_ETH((USDC)) -->|reservoir
deposit| rUSD_ETH((rUSD)) end rUSD_ETH -.-> |balance
check|rUSD_BERA((rUSD)) subgraph berachain ["🐻 Berachain"] rUSD_BERA((rUSD)) -->|euler-v2
deposit| erUSD((erUSD)) end ``` ## Quick Start Use the [GET `layerzero/pool`](/api-reference/integration/layerzero-pool) API to find the correct pool address and use it as the `primaryAddress` for `stargate.bridge` operation. Always start the post-bridging `callback` with `balance` action. ```ts theme={null} { protocol: "stargate", action: "bridge", args: { primaryAddress: rusdEthToBeraPools[0].pool, destinationChainId: ETHEREUM_ID, ... callback: [ // Mint e-rUSD using bridged USDC on Ethereum { protocol: "reservoir", action: "deposit", args: {...}, }, // Bridge newly minted e-rUSD back to Berachain { protocol: "stargate", action: "bridge", args: { destinationChainId: BERACHAIN_ID, ... // Callback executes on Berachain after e-rUSD arrives callback: [ // Deposit e-rUSD into Euler vault on Berachain { protocol: "euler-v2", action: "deposit", args: {...}, }, ], }, }, ], }, }, ``` [**Try this route →**](https://happypath.enso.build/?chainId=1\&destinationChainId=8453\&fromAddress=0xd8da6bf26964af9d7eed9e03e53415d37aa96045\&routingStrategy=delegate\&tokenIn=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\&tokenOut=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\&amountIn=1000000000) To simply bridge an asset, use the `route` API with automatic route optimization from input and output token/chain pairs. ```typescript SDK theme={null} // Basic USDC transfer: Ethereum → Base const route = await ensoClient.getRouteData({ fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", chainId: 1, // Ethereum destinationChainId: 8453, // Base tokenIn: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], // USDC Ethereum tokenOut: ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"], // USDC Base amountIn: ["1000000000"], // 1,000 USDC slippage: "300", // 3% routingStrategy: "delegate" }); await wallet.sendTransaction(route.tx); ``` ```bash cURL theme={null} curl --request POST \ --url https://api.enso.finance/api/v1/shortcuts/route \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer $ENSO_API_KEY" \ --data '{ "chainId": 1, "destinationChainId": 8453, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "delegate", "tokenIn": ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], "tokenOut": ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"], "amountIn": ["1000000000"], "slippage": "300" }' | jq ``` ## Core Concepts Crosschain routing uses Stargate and LayerZero for bridging assets. The `bridge` action's parameter `primaryAddress` must reference an appropriate pool contract, exposed by the `layerZero/pool` API. Parent bridge calls calculate gas fees required for all child bridge operations and include these costs in the initial transaction fee using LayerZero's native drop feature. Callback arrays of Enso Actions execute on the destination chain after bridge completion. All actions within a bundle execute atomically. ## When to use Route vs Bundle API? Use **Route API** for: * [simple crosschain swaps](#1-simple-cross-chain-swap) * [crosschain zap deposits](#2-crosschain-vault-zap) **Limitations**: Cannot handle custom post-bridge logic or multi-step protocols interactions Use **Bundle API** for: * [crosschain position minting](#3-cross-chain-position-minting) * [crosschain yield strategies](#4-crosschain-yield-strategy) * **Limitations**: Single callback sequence with up to 10 chained actions Use the [GET `layerzero/pool`](/api-reference/integration/layerzero-pool) API to find the correct pool address and use it as the `primaryAddress` for `stargate.bridge` operation. ## Examples ### 1. Simple Cross-Chain Swap Use Route API for basic cross-chain operations with automatic pathfinding. ```mermaid theme={null} flowchart LR subgraph ethereum ["🌐 Ethereum"] ETH((ETH)) --> A1(( )) end A1 -.->|stargate
bridge| B1 subgraph base ["🔵 Base"] B1(( )) -->|balance
check| USDC((USDC)) end ``` ```typescript SDK theme={null} // ETH on Ethereum → USDC on Base const route = await ensoClient.getRouteData({ fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", chainId: 1, // Ethereum destinationChainId: 8453, // Base tokenIn: ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], // ETH tokenOut: ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"], // USDC Base amountIn: ["1000000000000000000"], // 1 ETH slippage: "300", // 3% routingStrategy: "delegate" }); ``` ```bash cURL theme={null} curl --request POST \ --url https://api.enso.finance/api/v1/shortcuts/route \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer $ENSO_API_KEY" \ --data '{ "chainId": 1, "destinationChainId": 8453, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "delegate", "tokenIn": ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], "tokenOut": ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"], "amountIn": ["1000000000000000000"], "slippage": "300" }' | jq ``` ### 2. Crosschain Vault Zap In this example, we'll bridge ETH from Ethereum to zap it to a Ether.fi `weETH` vault on Base. [**Try this route →**](https://happypath.enso.build/?tokenIn=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\&outChainId=8453\&chainId=1\&tokenOut=0x04c0599ae5a44757c0af6f9ec3b93da8976c150a) ```mermaid theme={null} flowchart LR subgraph ethereum ["🌐 Ethereum"] ETH((ETH)) --> A1(( )) end A1 -.->|stargate
bridge| B1 subgraph base ["🔵 Base"] B1(( )) -->|balance
check| ETH_B((ETH)) ETH_B --> |ether.fi
deposit|WEETH((weETH)) end ``` ```typescript theme={null} const route = await ensoClient.getRouteData({ fromAddress: "0x...", chainId: 1, // Ethereum destinationChainId: 8453, // Base tokenIn: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], // USDC Ethereum tokenOut: ["0x04C0599Ae5A44757c0af6F9eC3b93da8976c150A"], // weETH vault on Base amountIn: ["1000000000"], // 1,000 USDC slippage: "500", // 5% (complex operation) routingStrategy: "delegate" }); // Bridge + vault entry in one transaction await wallet.sendTransaction(route.tx); ``` ### 3. Cross-Chain Position Minting Crosschain routing enables you to mint positions on different chains and bridge them back, while signing only once. In this example, we'll bridge USDC from Berachain to Ethereum, mint e-rUSD using Reservoir protocol, then bridge rUSD back to Berachain. **About Reservoir**: Reservoir is a stablecoin protocol that mints rUSD (a USD-pegged stablecoin) by accepting USDC as collateral on Ethereum mainnet. ```mermaid theme={null} flowchart LR subgraph berachain ["🐻 Berachain"] USDC_BERA((USDC)) --> A1(( )) end A1 -.-> B1 subgraph ethereum ["🌐 Ethereum"] B1(( )) -->|balance
check| USDC_ETH((USDC)) USDC_ETH -->|reservoir
deposit| A2(( )) --> rUSD_ETH((rUSD)) end rUSD_ETH -.-> C1 subgraph berachain ["🐻 Berachain"] C1(( )) -->|balance
check| rUSD_BERA((rUSD)) end ``` Use the [GET `layerzero/pool`](/api-reference/integration/layerzero-pool) API or `client.getLayerZeroPool()` from the SDK to find the correct pool address and use it as the `primaryAddress` for `stargate.bridge` operation. **What's happening**: This workflow demonstrates a complete round-trip bridge operation - taking USDC from Berachain, minting a stablecoin on Ethereum where the protocol exists, then bringing the newly minted e-rUSD back to the origin chain. **Understanding callbacks execution** Callbacks execute on the destination chain after the bridge completes, but they're not separate transactions. The bridge operation includes encoded instructions that execute atomically using Enso's crosschain execution engine. This means: * **Atomic Safety**: All callback actions execute as a single atomic transaction on the destination chain. If any action fails, the entire callback transaction reverts and bridged tokens are sent to the `refundReceiver` address. Funds never get stuck in an intermediate state. * **Gas Management**: The initial transaction on the source chain calculates and pays for all destination chain gas costs using LayerZero's native drop feature. You don't need to hold native tokens on every destination chain. * **Output Chaining**: Callbacks can reference outputs from previous callback actions using useOutputOfCallAt, enabling complex multi-step workflows that adapt to actual bridged amounts rather than fixed values. ```typescript mintOnBeraFromMainnet.ts highlight={21, 27, 48, 55, 79} lines theme={null} // Chain IDs const BERACHAIN_ID = 80094; const ETHEREUM_ID = 1; // Common addresses const WALLET_ADDRESS = "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11"; // User wallet // Token addresses const USDC_BERACHAIN = "0x549943e04f40284185054145c6E4e9568C1D3241"; const USDC_ETHEREUM = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; const RUSD_ETHEREUM = "0x09D4214C03D01F49544C0448DBE3A27f768F2b34"; // Protocol addresses const RESERVOIR_MINTING_CONTRACT = "0x4809010926aec940b550D34a46A52739f996D75D"; const client = new EnsoClient({ apiKey: process.env.ENSO_API_KEY || "your-api-key-here", }); const usdcBeraToEthPools = await client.getLayerZeroPool({ chainId: BERACHAIN_ID, token: USDC_BERACHAIN, destinationChainId: ETHEREUM_ID + "", }); const rusdEthToBeraPools = await client.getLayerZeroPool({ chainId: ETHEREUM_ID, token: RUSD_ETHEREUM, destinationChainId: BERACHAIN_ID + "", }); if (!(usdcBeraToEthPools.length && usdcBeraToEthPools.length)) { throw new Error("Required pools not available"); } const bundle = await client.getBundleData( { chainId: BERACHAIN_ID, fromAddress: WALLET_ADDRESS, spender: WALLET_ADDRESS, routingStrategy: "router", refundReceiver: WALLET_ADDRESS, }, [ { protocol: "stargate", action: "bridge", args: { primaryAddress: usdcBeraToEthPools[0].pool, destinationChainId: ETHEREUM_ID, tokenIn: USDC_BERACHAIN, amountIn: parseUnits("1000", 6).toString(), // 1000 USDC receiver: WALLET_ADDRESS, callback: [ // Step 1: Check USDC balance on Ethereum after bridge { protocol: "enso", action: "balance", args: { token: USDC_ETHEREUM, }, }, // Step 2: Mint e-rUSD using bridged USDC { protocol: "reservoir", action: "deposit", args: { primaryAddress: RESERVOIR_MINTING_CONTRACT, tokenIn: USDC_ETHEREUM, tokenOut: RUSD_ETHEREUM, amountIn: { useOutputOfCallAt: 0 }, // Use USDC from balance check receiver: WALLET_ADDRESS, }, }, // Step 3: Bridge newly minted e-rUSD back to Berachain { protocol: "stargate", action: "bridge", args: { primaryAddress: rusdEthToBeraPools[0].pool, destinationChainId: BERACHAIN_ID, tokenIn: RUSD_ETHEREUM, amountIn: { useOutputOfCallAt: 1 }, // Use e-rUSD from minting receiver: WALLET_ADDRESS, }, }, ], }, }, ] ); ``` ### 4. Crosschain Yield Strategy Nested callbacks enable multi-hop workflows, allowing operations that span multiple chains where different protocols exist. In this example, we'll do an Euler deposit of rUSD tokens minted on a Berachain by using Ethereum Mainnet assets. The user starts with USDC on Berachain and ends with yield-generating vault shares with a single signature. ```mermaid theme={null} flowchart LR subgraph berachain ["🐻 Berachain"] USDC_BERA((USDC)) --> A1(( )) end A1 -.-> |balance
check| USDC_ETH((USDC)) subgraph ethereum ["🌐 Ethereum"] USDC_ETH((USDC)) -->|reservoir
deposit| rUSD_ETH((rUSD)) end rUSD_ETH -.-> |balance
check|rUSD_BERA((rUSD)) subgraph berachain ["🐻 Berachain"] rUSD_BERA((rUSD)) -->|euler-v2
deposit| erUSD((erUSD)) end ``` ```typescript mintOnBeraDepositOnMainnet.ts highlight={50, 57, 81, 89, 23, 29} lines theme={null} const BERACHAIN_ID = 80094; const ETHEREUM_ID = 1; // Common addresses const WALLET_ADDRESS = "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11"; // User wallet // Token addresses const USDC_BERACHAIN = "0x549943e04f40284185054145c6E4e9568C1D3241"; const USDC_ETHEREUM = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; const RUSD_ETHEREUM = "0x09D4214C03D01F49544C0448DBE3A27f768F2b34"; const RUSD_BERACHAIN = "0x09D4214C03D01F49544C0448DBE3A27f768F2b34"; // Protocol addresses const RESERVOIR_MINTING_CONTRACT = "0x4809010926aec940b550D34a46A52739f996D75D"; const EULER_VAULT_E_RUSD_BERACHAIN = "0x109D6D1799f62216B4a7b0c6e245844AbD4DD281"; // Euler vault for e-rUSD on Berachain (need actual address) const client = new EnsoClient({ apiKey: process.env.ENSO_API_KEY!, }); const usdcBeraToEthPools = await client.getLayerZeroPool({ chainId: BERACHAIN_ID, token: USDC_BERACHAIN, destinationChainId: ETHEREUM_ID + "", }); const rusdEthToBeraPools = await client.getLayerZeroPool({ chainId: ETHEREUM_ID, token: RUSD_ETHEREUM, destinationChainId: BERACHAIN_ID + "", }); if (!(usdcBeraToEthPools.length && usdcBeraToEthPools.length)) { throw new Error("Required pools not available"); } const bundle = await client.getBundleData( { chainId: BERACHAIN_ID, fromAddress: WALLET_ADDRESS, spender: WALLET_ADDRESS, routingStrategy: "router", refundReceiver: WALLET_ADDRESS, }, [ { protocol: "stargate", action: "bridge", args: { primaryAddress: rusdEthToBeraPools[0].pool, destinationChainId: ETHEREUM_ID, tokenIn: USDC_BERACHAIN, amountIn: parseUnits("1000", 6).toString(), // 1000 USDC receiver: WALLET_ADDRESS, callback: [ // Step 1: Check USDC balance on Ethereum after bridge { protocol: "enso", action: "balance", args: { token: USDC_ETHEREUM, }, }, // Step 2: Mint e-rUSD using bridged USDC on Ethereum { protocol: "reservoir", action: "deposit", args: { primaryAddress: RESERVOIR_MINTING_CONTRACT, tokenIn: USDC_ETHEREUM, tokenOut: RUSD_ETHEREUM, amountIn: { useOutputOfCallAt: 0 }, // Use USDC from balance check receiver: WALLET_ADDRESS, }, }, // Step 3: Bridge newly minted e-rUSD back to Berachain { protocol: "stargate", action: "bridge", args: { primaryAddress: rusdEthToBeraPools[0].pool, destinationChainId: BERACHAIN_ID, tokenIn: RUSD_ETHEREUM, amountIn: { useOutputOfCallAt: 1 }, // Use e-rUSD from minting receiver: WALLET_ADDRESS, // Callback executes on Berachain after e-rUSD arrives callback: [ // Step 4: Check e-rUSD balance on Berachain { protocol: "enso", action: "balance", args: { token: RUSD_BERACHAIN, }, }, // Step 5: Deposit e-rUSD into Euler vault on Berachain { protocol: "euler-v2", action: "deposit", args: { primaryAddress: EULER_VAULT_E_RUSD_BERACHAIN, tokenIn: RUSD_BERACHAIN, tokenOut: EULER_VAULT_E_RUSD_BERACHAIN, // ERC4626 vault token amountIn: { useOutputOfCallAt: 0 }, // Use e-rUSD from balance check receiver: WALLET_ADDRESS, }, }, ], }, }, ], }, }, ] ); ``` ## Reference ### Bridge Action Parameters The \[`bridge` action] has the follwing parameters: | Parameter | Description | Required | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- | | `primaryAddress` | LayerZero pool contract address for the source chain | Yes | | `destinationChainId` | Target blockchain network ID | Yes | | `tokenIn` | Token address to bridge from source chain | Yes | | `amountIn` | Amount to bridge (with full decimals) or reference to previous action output | Yes | | `receiver` | Address to receive bridged tokens on destination chain | Yes | | `callback` | Array of actions to execute on destination chain after bridging | No | | `refundReceiver` | Address to receive bridged tokens if callback execution fails on destination chain. If not specified, `receiver` gets refunds. | No | ### Callback Requirements **Critical**: All callback sequences must begin with a balance check action to verify the bridged token amount on the destination chain. 1. **First action must be the `balance` action**: ```json theme={null} { protocol: "enso", action: "balance", args: { token: "bridged_token_address" } }` ``` 2. **Reference previous outputs**: Use the `ouseOutputOfCallAt` to chain actions together ```json theme={null} { useOutputOfCallAt: callIndex, index: outVarIndex } ``` 3. **Nested callbacks**: Bridge actions within callbacks enable multi-hop workflows ### Supported Chains and Tokens Use the [GET `layerzero/pool`](/api-reference/integration/layerzero-pool) API to find the correct pool address and use it as the `primaryAddress` for `stargate.bridge` operation.

Updated {date_0}

# Get Started Source: https://docs.enso.build/pages/build/get-started/overview Enso Shortcuts convert high-level specifications of crosschain DeFi operations into runnable calldata export const date_0 = "2025-09-12" Find optimal paths for entering/exiting DeFi positions or swapping ERC20 tokens with `route` API. Execute complex DeFi operations across multiple blockchains using bridge callbacks and post-bridge execution Bundle several DeFi actions into a single transaction using `bundle` API. Access DeFi protocols' and tokens' data through a set of Enso APIs. ## When to use: Route vs Bundle API?
Use **Route API** for: 1. Redeeming, swapping, direct position deposits 2. Automatically optimized swaps based on current market conditions (`enso.route`) 3. [Zapping into liquidity](/pages/build/get-started/route#2-zap-into-vault) from any token with automatic swaps 4. [Simple crosschain swaps](/pages/build/get-started/crosschain-routing#1-simple-cross-chain-swap) between two chains 5. [Crosschain zap deposits](/pages/build/get-started/crosschain-routing#2-crosschain-vault-zap) from any token to any vault on another chain with automatic swaps **Limitations**: * Cannot handle custom post-bridge logic or multi-step protocols interactions.
Use **Bundle API** for: 1. Borrowing, harvesting/claiming rewards, opening CLMM positions 2. Routing with predetermined positions 3. Creating multichain DeFi strategies 4. [Crosschain stablecoin minting](/pages/build/get-started/crosschain-routing#3-cross-chain-position-minting) 5. [Crosschain yield strategies](/pages/build/get-started/crosschain-routing#4-crosschain-yield-strategy) with minting tokens on different chains
**Limitations**: * Single callback sequence with up to 10 chained actions

Updated {date_0}

# Get Protocol Data Source: https://docs.enso.build/pages/build/get-started/protocol-data Access DeFi protocols and tokens data through Enso's API export const date_0 = "2025-08-07" With Enso API, you can retrieve detailed information about DeFi protocols, tokens, and user balances. These endpoints enable you to build data-rich applications with comprehensive DeFi protocol information. ## Protocol Information The Protocol API endpoints provide access to DeFi protocol data, standards, and volume metrics. ### Get Supported Protocols Retrieve a list of all protocols supported by Enso, including names, logos, and supported chains. **API Reference:** [GET `/v1/protocols`](/api-reference/integration/all-protocols) ```ts EnsoSDK theme={null} import { EnsoClient } from '@ensofinance/sdk'; // Initialize the client with your API key const enso = new EnsoClient({ apiKey: 'YOUR_API_KEY' // Replace with your actual API key }); // Get all supported protocols async function getAllProtocols() { try { const protocols = await enso.getProtocolData(); console.log('Supported protocols:', protocols); return protocols; } catch (error) { console.error('Error fetching protocols:', error); throw error; } } getAllProtocols(); ``` ```bash cURL theme={null} curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ENSO_API_KEY" \ "https://api.enso.finance/api/v1/protocols" \ | jq ``` ### Get Protocol Standards and Actions Access detailed information about protocols' supported actions and standards. This helps you understand which operations can be performed with specific protocols. **API Reference:** [GET `/v1/standards`](/api-reference/integration/standards) ```ts EnsoSDK theme={null} // Get all available standards (protocols and their actions) async function getProtocolStandards() { try { const response = await fetch('https://api.enso.finance/api/v1/standards', { headers: { 'Authorization': `Bearer ${enso.apiKey}`, 'Content-Type': 'application/json' } }); const standards = await response.json(); console.log('Protocol standards and actions:', standards); return standards; } catch (error) { console.error('Error fetching standards:', error); throw error; } } // Get specific protocol standard async function getProtocolStandardBySlug(slug) { try { const response = await fetch(`https://api.enso.finance/api/v1/integration/${slug}`, { headers: { 'Authorization': `Bearer ${enso.apiKey}`, 'Content-Type': 'application/json' } }); const standard = await response.json(); console.log(`Standard for ${slug}:`, standard); return standard; } catch (error) { console.error(`Error fetching standard for ${slug}:`, error); throw error; } } getProtocolStandards(); getProtocolStandardBySlug('aave-v3'); ``` ```bash cURL theme={null} # Get all standards curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ENSO_API_KEY" \ "https://api.enso.finance/api/v1/standards" \ | jq # Get specific protocol standard curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ENSO_API_KEY" \ "https://api.enso.finance/api/v1/integration/aave-v3" \ | jq ``` ### Get Protocol Volume Data Retrieve transaction volume on a given chain. **API Reference:** [GET `/volume/{chainId}`](/api-reference/defi/chain-and-transactions-volume) ```ts EnsoSDK theme={null} // Get protocol volume data for a specific chain async function getChainVolume(chainId: number) { try { const response = await fetch(`https://api.enso.finance/api/v1/volume/${chainId}`, { headers: { 'Authorization': `Bearer ${enso.apiKey}`, 'Content-Type': 'application/json' } }); const volumeData = await response.json(); console.log(`Volume data for chain ${chainId}:`, volumeData); return volumeData; } catch (error) { console.error(`Error fetching volume data for chain ${chainId}:`, error); throw error; } } // Get volume data for Ethereum getChainVolume(1); ``` ```bash cURL theme={null} curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ENSO_API_KEY" \ "https://api.enso.finance/api/v1/volume/1" \ | jq ``` ## Position Information The Token API delivers data about DeFi assets including pricing, composition, and yield metrics. Filter tokens by protocol, chain, underlying assets, APY, or TVL to discover specific DeFi opportunities. ### Filter Supported Tokens Query tokens based on various criteria like protocol, underlying assets, or token type. This helps users discover specific DeFi opportunities. **API Reference:** [GET `/v1/tokens`](/api-reference/tokens/tokens) ```ts EnsoSDK theme={null} import { EnsoClient } from '@ensofinance/sdk'; // Initialize the client with your API key const enso = new EnsoClient({ apiKey: 'YOUR_API_KEY' // Replace with your actual API key }); // Get Aave V3 DeFi tokens on Ethereum mainnet (chainId 1) with USDT as underlying async function getAaveV3UsdtTokensOnEthereum() { try { const tokenData = await enso.getTokenData({ chainId: 1, // Ethereum mainnet protocolSlug: 'aave-v3', type: 'defi', underlyingTokens: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT includeMetadata: true }); console.log('Aave V3 DeFi tokens with USDT as underlying on Ethereum:', tokenData.data); return tokenData.data; } catch (error) { console.error('Error fetching tokens:', error); throw error; } } getAaveV3UsdtTokensOnEthereum(); ``` ```bash cURL theme={null} curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ENSO_API_KEY" \ "https://api.enso.finance/api/v1/tokens?chainId=1&protocolSlug=aave-v3&type=defi&underlyingTokens=0xdAC17F958D2ee523a2206206994597C13D831ec7&includeMetadata=true" \ | jq ``` ### Get Protocol TVL and APY Data Access yield and total value locked (TVL) information for DeFi protocols. This data is crucial for comparing investment opportunities across the DeFi landscape. **API Reference:** [GET `/v1/tokens`](/api-reference/tokens/tokens) with APY filters ```ts EnsoSDK theme={null} import { EnsoClient } from '@ensofinance/sdk'; // Initialize the client with your API key const enso = new EnsoClient({ apiKey: 'YOUR_API_KEY' // Replace with your actual API key }); // Get tokens with APY over 5% for a specific protocol async function getHighYieldTokensForProtocol(protocolSlug: string, minApy: number = 5) { try { const tokenData = await enso.getTokenData({ chainId: 1, protocolSlug: protocolSlug, type: 'defi', apyFrom: minApy, includeMetadata: true }); console.log(`${protocolSlug} tokens with APY > ${minApy}%:`, tokenData.data); return tokenData.data; } catch (error) { console.error('Error fetching high-yield tokens:', error); throw error; } } getHighYieldTokensForProtocol('yearn'); ``` ```bash cURL theme={null} curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ENSO_API_KEY" \ "https://api.enso.finance/api/v1/tokens?chainId=1&protocolSlug=yearn-v2&type=defi&apyFrom=5&includeMetadata=true" \ | jq ``` ### Get Token Prices Retrieve current token prices with confidence scores, supporting decision-making around token swaps and valuations. **API Reference:** [GET `/prices/token-price`](/api-reference/tokens/token-price) ```ts EnsoSDK theme={null} import { EnsoClient } from '@ensofinance/sdk'; // Initialize the client with your API key const enso = new EnsoClient({ apiKey: 'YOUR_API_KEY' // Replace with your actual API key }); // Get price data for a specific token async function getTokenPrice(chainId: number, tokenAddress: string) { try { const priceData = await enso.getPriceData({ chainId, address: tokenAddress }); console.log(`Price data for ${tokenAddress} on chain ${chainId}:`, priceData); return priceData; } catch (error) { console.error('Error fetching token price:', error); throw error; } } // Get price for WETH on Ethereum getTokenPrice(1, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'); ``` ```bash cURL theme={null} curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ENSO_API_KEY" \ "https://api.enso.finance/api/v1/prices/1/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" \ | jq ``` I'll add the token information use cases with the specified layout and examples: ### Get Information for Several Tokens Retrieve detailed information about multiple tokens in a single request to support portfolio analysis or multi-token operations. **API Reference:** [GET `/v1/tokens`](/api-reference/tokens/tokens) ```ts EnsoSDK theme={null} // SDK Example const ensoClient = new EnsoClient({ apiKey: "your-api-key" }); const tokenData = await ensoClient.getTokenData({ chainId: 1, address: [ "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "0x6b175474e89094c44da98b954eedeac495271d0f" ], includeMetadata: true }); ``` ```bash cURL theme={null} curl -X GET \ 'https://api.enso.finance/api/v1/tokens?chainId=1&address=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&address=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&address=0x6b175474e89094c44da98b954eedeac495271d0f&includeMetadata=true' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -H 'accept: application/json' ``` ### Fetch All Tokens from a Specific Protocol Get a comprehensive list of all tokens associated with a particular protocol to understand available investment options. **API Reference:** [GET `/v1/tokens`](/api-reference/tokens/tokens) ```ts EnsoSDK theme={null} // SDK Example const ensoClient = new EnsoClient({ apiKey: "your-api-key" }); const aaveTokens = await ensoClient.getTokenData({ chainId: 1, protocolSlug: "aave-v3", includeMetadata: true }); ``` ```bash cURL theme={null} curl -X GET \ 'https://api.enso.finance/api/v1/tokens?chainId=1&protocolSlug=aave-v3&includeMetadata=true' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -H 'accept: application/json' ``` ### Filter by Token Type and Minimum TVL Find specific token types with a minimum TVL (Total Value Locked) threshold to focus on well-established and liquid DeFi positions. **API Reference:** [GET `/v1/tokens`](/api-reference/tokens/tokens) ```ts EnsoSDK theme={null} // SDK Example const ensoClient = new EnsoClient({ apiKey: "your-api-key" }); const defiTokens = await ensoClient.getTokenData({ chainId: 1, type: "defi", tvl: 1000000, // $1M minimum TVL includeMetadata: true }); ``` ```bash cURL theme={null} curl -X GET \ 'https://api.enso.finance/api/v1/tokens?chainId=1&type=defi&tvlFrom=1000000&includeMetadata=true' \ -H "Authorization: Bearer $ENSO_API_KEY" \ -H 'accept: application/json' ```

Updated {date_0}

# DeFi and Swap Routing Source: https://docs.enso.build/pages/build/get-started/route Find optimal paths for crosschain entering/exiting DeFi positions or swapping ERC20 tokens. export const date_0 = "2025-09-12" The Route API is Enso's **crosschain automated pathfinding engine** that calculates optimal multi-step paths between any two DeFi positions - `tokenIn` and `tokenOut`. Whether you're swapping tokens, entering yield vaults, or moving assets across chains, the Route API handles the complex routing logic automatically. **Would `route` do the job?**
The `route` API might be the simpler way to route your assets. Before using the bundle API, check if `route` would work using [happypath](https://happypath.enso.build).
**Routing vs Bundling**: The Route API excels at single-path operations where you want Enso to determine the optimal route automatically. For custom multi-step workflows where you need precise control over each action, use the [Bundle API](/api-reference/defi-shortcuts/bundle-a-list-of-actions) instead. **When to use routing**: Token swaps with optimal pricing, vault entries/exits, position migrations between protocols, crosschain transfers, and any scenario where you want automated route optimization rather than manually specifying each step. ## Quick Start The `route` API produces an gas-optimized, atomic transaction between the two given positions, combining `swap`, `deposit`, and `redeem` operations. Use the [Bundle API](/pages/build/get-started/bundling-actions) if you need other [actions Enso supports](/pages/build/reference/actions), such as `harvest`, `borrow`, `repay`. ## Sample requests ```typescript theme={null} const route = await ensoClient.getRouteData({ fromAddress: "0x...", chainId: 1, tokenIn: ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], // ETH tokenOut: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], // USDC amountIn: ["1000000000000000000"], // 1 ETH slippage: "50", // 0.5% routingStrategy: "delegate" }); await wallet.sendTransaction(route.tx); ``` ```typescript theme={null} const route = await ensoClient.getRouteData({ fromAddress: "0x...", chainId: 1, tokenIn: ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], // ETH tokenOut: ["0xa258c4606ca8206d8aa700ce2143d7db854d168c"], // yvWETH amountIn: ["1000000000000000000"], // 1 ETH slippage: "100", // 1% routingStrategy: "delegate" }); // ETH → WETH → Yearn vault automatically await wallet.sendTransaction(route.tx); ``` ```typescript theme={null} const route = await ensoClient.getRouteData({ fromAddress: "0x...", chainId: 1, // Ethereum destinationChainId: 8453, // Base tokenIn: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], // USDC Ethereum tokenOut: ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"], // USDC Base amountIn: ["1000000000"], // 1,000 USDC slippage: "300", // 3% (higher for crosschain) routingStrategy: "delegate" }); // Bridge USDC from Ethereum to Base await wallet.sendTransaction(route.tx); ``` ```typescript theme={null} const route = await ensoClient.getRouteData({ fromAddress: "0x...", chainId: 1, // Ethereum destinationChainId: 8453, // Base tokenIn: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], // USDC Ethereum tokenOut: ["0x04C0599Ae5A44757c0af6F9eC3b93da8976c150A"], // weETH vault on Base amountIn: ["1000000000"], // 1,000 USDC slippage: "500", // 5% (complex operation) routingStrategy: "delegate" }); // Bridge + vault entry in one transaction await wallet.sendTransaction(route.tx); ``` ## Core Concepts Specify any `tokenIn` and `tokenOut` - ERC20 tokens, LP tokens, vault shares, or yield positions. The Route API automatically finds the optimal path between any two DeFi positions across protocols and chains. Response contains a complete transaction object ready to sign (`tx`), `amountOut` (expected output), `gas` (estimated), and `route` (optimized path taken). Set slippage in basis points: `"50"` = 0.5%, `"300"` = 3%. Higher slippage for complex routes. **Cannot use both `slippage` and `minAmountOut`** - choose one protection method. Add `destinationChainId` for crosschain routes. API automatically selects optimal bridges and calculates fees. ## Response Structure The `route` response consists of the following fields: * **`tx`**: Complete transaction object ready for submission. Contains the correct `to` address, `data`, `value`, and `gas` fields. * **`amountOut`**: Simulated output amount - display this to users as expected returns. This is calculated through onchain simulation. * **`gas`**: Estimated gas usage from simulation. Use this value to prevent out-of-gas failures. * **`route`**: Array showing the optimization path Enso constructed. Shows the DEX(s) Enso selected for optimal pricing. Always use the complete `tx` object returned by the API, and use the `gas` value for your transaction. * The `to` address varies based on routing strategy, and other fields like `value` and `data` are precisely calculated for your specific route. * The `gas` value estimate comes from actual simulation, out-of-gas transaction failures. ## Examples The following examples progress from simple token swaps to complex crosschain vault interactions. Each example builds on concepts from previous ones, demonstrating how the Route API handles increasingly sophisticated DeFi operations automatically. ### 0. Install & Authenticate You can interact with the API using Enso SDK or directly via a REST API. You can explore Enso through [API Sandbox](/api-reference/). To install the SDK run the following command: ```bash theme={null} npm i @ensofinance/sdk pnpm i @ensofinance/sdk yarn add @ensofinance/sdk ``` To use the API, authenticate using the [API key](/pages/build/get-started/authentication). ### 1. Simple Token Swap Start with the most basic routing operation: swapping ETH for USDC on Ethereum mainnet. ```typescript SDK theme={null} import { EnsoClient } from '@ensofinance/sdk'; const ensoClient = new EnsoClient({ apiKey: 'your-api-key-here' }); const fromAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; const receiver = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; const spender = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; // ETH → USDC swap with 0.5% slippage const swapRoute = await ensoClient.getRouteData({ fromAddress, receiver, spender, chainId: 1, amountIn: ["1000000000000000000"], // 1 ETH tokenIn: ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], // ETH tokenOut: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], // USDC slippage: "50", // 0.5% routingStrategy: "delegate" }); console.log('Expected USDC output:', swapRoute.amountOut); console.log('Estimated gas:', swapRoute.gas); console.log('Swap route complexity:', swapRoute.route.length, 'steps'); // Use route.tx to execute the transaction const txHash = await wallet.sendTransaction(swapRoute.tx); ``` ```bash cURL theme={null} curl --request POST \ --url https://api.enso.finance/api/v1/shortcuts/route \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer $ENSO_API_KEY" \ --data '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "delegate", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], "tokenOut": ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], "amountIn": ["1000000000000000000"], "slippage": "50" }' | jq ``` ### 2. Zap into Vault Enter a Yearn vault directly from ETH, automatically handling any intermediate swaps and vault deposits. ```typescript SDK theme={null} // ETH → yvWETH (Yearn WETH vault) with 1% slippage const vaultEntry = await ensoClient.getRouteData({ fromAddress, receiver, spender, chainId: 1, amountIn: ["1000000000000000000"], // 1 ETH tokenIn: ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], // ETH tokenOut: ["0xa258c4606ca8206d8aa700ce2143d7db854d168c"], // yvWETH slippage: "100", // 1% routingStrategy: "delegate" }); console.log('yvWETH shares received:', vaultEntry.amountOut); console.log('Route complexity:', vaultEntry.route.length, 'steps'); // Route typically: ETH → WETH → deposit to Yearn vault ``` ```bash cURL theme={null} # ETH → yvWETH (Yearn WETH vault) with 1% slippage curl --request POST \ --url https://api.enso.finance/api/v1/shortcuts/route \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer $ENSO_API_KEY" \ --data '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "delegate", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], "tokenOut": ["0xa258c4606ca8206d8aa700ce2143d7db854d168c"], "amountIn": ["1000000000000000000"], "slippage": "100" }' | jq ``` **What's happening:** The router automatically wraps ETH to WETH, then deposits into the Yearn vault. The `amountOut` represents vault shares, not underlying tokens. ### 3. Vault Migration Move from one yield protocol to another - exit Yearn vault and enter Aave lending position. ```typescript SDK theme={null} // yvWETH → aWETH (migrate from Yearn to Aave) const migration = await ensoClient.getRouteData({ fromAddress, receiver, spender, chainId: 1, amountIn: ["1000000000000000000"], // 1 yvWETH tokenIn: ["0xa258c4606ca8206d8aa700ce2143d7db854d168c"], // yvWETH tokenOut: ["0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8"], // aWETH slippage: "100", // 1% routingStrategy: "delegate" }); console.log('aWETH tokens received:', migration.amountOut); console.log('Migration complexity:', migration.route.length, 'steps'); // Route: yvWETH → withdraw to WETH → deposit to Aave → receive aWETH ``` ```bash cURL theme={null} # Route: yvWETH → withdraw to WETH → deposit to Aave → receive aWETH curl --request POST \ --url https://api.enso.finance/api/v1/shortcuts/route \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer $ENSO_API_KEY" \ --data '{ "chainId": 1, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "delegate", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xa258c4606ca8206d8aa700ce2143d7db854d168c"], "tokenOut": ["0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8"], "amountIn": ["1000000000000000000"], "slippage": "100" }' | jq ``` **Complex routing:** This involves exiting one protocol (Yearn) and entering another (Aave). The route array will show multiple steps including withdrawal, potential swaps, and final deposit. ### 4. Crosschain Transfer Move assets between blockchains using Enso's integrated bridge routing. ```typescript SDK theme={null} // USDC from Ethereum → USDC.e on Plume Network const crossChain = await ensoClient.getRouteData({ fromAddress, receiver, spender, chainId: 1, // Ethereum destinationChainId: 98866, // Plume Network amountIn: ["1000000000"], // 1,000 USDC tokenIn: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], // USDC on Ethereum tokenOut: ["0x78adD880A697070c1e765Ac44D65323a0DcCE913"], // USDC.e on Plume slippage: "300", // 3% (higher for crosschain) routingStrategy: "delegate" }); console.log('USDC.e on Plume:', crossChain.amountOut); console.log('Bridge fee:', crossChain.feeAmount); console.log('Crosschain complexity:', crossChain.route.length, 'steps'); ``` ```bash cURL theme={null} # USDC from Ethereum → USDC.e on Plume Network curl --request POST \ --url https://api.enso.finance/api/v1/shortcuts/route \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer $ENSO_API_KEY" \ --data '{ "chainId": 1, "destinationChainId": 98866, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "delegate", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], "tokenOut": ["0x78adD880A697070c1e765Ac44D65323a0DcCE913"], "amountIn": ["1000000000"], "slippage": "300" }' | jq ``` **Crosschain considerations:** Higher slippage accounts for bridge fees and potential price differences. The `feeAmount` shows bridge costs, and `route` reveals pre- and post- bridging steps. ### 5. Crosschain Vault Zapping The most complex example: bridge assets and enter a vault on the destination chain in one transaction. ```typescript SDK theme={null} // USDC Ethereum → myPUSD vault on Plume (crosschain vault zap) const crossChainVault = await ensoClient.getRouteData({ fromAddress, receiver, spender, chainId: 1, // Ethereum destinationChainId: 98866, // Plume Network amountIn: ["2000000000"], // 2,000 USDC tokenIn: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], // USDC on Ethereum tokenOut: ["0xAf5aEAb2248415716569Be5d24FbE10b16590D6c"], // myPUSD vault on Plume slippage: "500", // 5% (complex crosschain + vault operation) routingStrategy: "delegate" }); console.log('myPUSD vault shares:', crossChainVault.amountOut); console.log('Total route steps:', crossChainVault.route.length); console.log('Estimated gas:', crossChainVault.gas); ``` ```bash cURL theme={null} # USDC Ethereum → myPUSD vault on Plume (crosschain vault zap) curl --request POST \ --url https://api.enso.finance/api/v1/shortcuts/route \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer $ENSO_API_KEY" \ --data '{ "chainId": 1, "destinationChainId": 98866, "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "routingStrategy": "delegate", "receiver": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "spender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "tokenIn": ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], "tokenOut": ["0xAf5aEAb2248415716569Be5d24FbE10b16590D6c"], "amountIn": ["2000000000"], "slippage": "500" }' | jq ``` **Maximum complexity:** This combines crosschain bridging with vault interaction. ## Related APIs & Next Steps ### When to Use Other APIs * **[Bundle API](/api-reference/defi-shortcuts/bundle-a-list-of-actions)**: When you need custom multi-step logic or want to orchestrate specific actions in sequence, or you need actions beyond `swap`, `deposit` and `redeem` the route API uses * **[Nontokenized Positions](/api-reference/defi-shortcuts/routing-to-a-non-tokenized-position)**: For lending positions that don't issue tokens (like Aave debt positions) * **[Approval Endpoint](/api-reference/defi-shortcuts/approve-enso-contract)**: Managing token permissions when using `"router"` strategy ### Supporting APIs * **[Tokens API](/api-reference/tokens/tokens)**: Discover available tokens and their addresses across chains * **[Prices API](/api-reference/tokens/token-price)**: Get current token valuations for your UI * **[Networks API](/api-reference/integration/networks)**: List supported chains and their details

Updated {date_0}

# Actions Source: https://docs.enso.build/pages/build/reference/actions Actions are interactions with DeFi protocols Enso supports. export const date_0 = "2025-09-23" Bundle API allows you to define blueprints of complex multi-step transactions composed out of Actions. This reference guide explains all available actions and their parameters. **Would `route` (`client.getRouteData`) do the job?**
The `route` API might be the simpler way to route your assets. Before using the bundle API, check if [`route` would suffice.](/pages/build/get-started/overview#when-to-use-route-vs-bundle-api)
To get the up-to date list of available actions and parameters, use [GET `/integration/actions`](/api-reference/integration/supported-actions).
To get a list of actions available for a specific protocol, use [GET `standards/{slug}/`](https://docs.enso.build/api-reference/integration/standard-per-protocol).
## Chaining Actions It's possible to chain actions: using the output of one action as the input for another. To reference outputs from previous actions use the `useOutputOfCallAt` syntax. For array-outputs such as `split`, you can specify the index within that action's output array ```typescript theme={null} { "amountIn": { "useOutputOfCallAt": 0 // Use the output amount from the action at index 0 "index": 1 // Optional: access outputOfCallAt[0][1] } } ``` Here's an example of a more complex chaining sequence that splits WETH into three different portions: ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate" }, [ { protocol: "enso", action: "route", args: { tokenIn: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC tokenOut: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH amountIn: "1000000000" // 1000 USDC } }, { protocol: "aave-v3", action: "deposit", args: { tokenIn: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH amountIn: { "useOutputOfCallAt": 1, "index": 0 }, // First portion primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2" // Aave V3 pool } }, { protocol: "curve", action: "deposit", args: { tokenIn: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH amountIn: { "useOutputOfCallAt": 1, "index": 1 }, // Second portion primaryAddress: "0xDC24316b9AE028F1497c275EB9192a3Ea0f67022" // Curve ETH/stETH pool } }, { protocol: "yearn", action: "deposit", args: { tokenIn: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH amountIn: { "useOutputOfCallAt": 1, "index": 2 }, // Third portion primaryAddress: "0xa258C4606Ca8206D8aA700cE2143D7db854D168c" // Yearn WETH vault } } ] ); ``` ## Core Actions ### `route` The route action determines the optimal path to swap one token for another across multiple DeFi protocols supported by Enso. This action gets expanded into a combination of `swap`, `deposit`, and `redeem` actions, similar to `/route` API. The `/bundle` API will return a `route` object that contains a list of all such actions. When using the `route` action, slippage is automatically calculated and applied. The action will revert if the received amount is below the expected output after applying slippage. For other actions, make sure to add one of [slippage protection actions](#slippage-protection) ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "enso", action: "route", args: { tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH address tokenOut: "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", // stETH address amountIn: "1000000000000000000", // Amount in wei (1 ETH) slippage: "300", // 3% slippage tolerance (in basis points) receiver: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", // Optional: Receiver address primaryAddress: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", // Optional: Primary contract address poolFee: "3000", // Optional: Pool fee in basis points (e.g., 3000 for 0.3%) }, }, ], ); ``` #### Route-Bridge Example When you need to route and bridge tokens to another chain, you can use the `destinationChainId` parameter. This converts the route into a cross-chain operation that handles both the swap and bridge in a single transaction. **Important**: When using `destinationChainId`, you **must** include `refundReceiver` to handle any potential refunds from failed bridge operations. The `refundReceiver` parameter should only be set when `destinationChainId` is provided. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", }, [ { protocol: "enso", action: "route", args: { tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH tokenOut: "0x94b008aa00579c1307b0ef2c499ad98a8ce58e58", // USDT amountIn: "1000000000000000000", // 1 ETH in wei destinationChainId: 10, // Optimism refundReceiver: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", // Required for route-bridge }, }, ], ); ``` | Parameter | Description | Required | | -------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------- | | `tokenIn` | Address of the token to send. For ETH, use `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` | Yes | | `tokenOut` | Address of the token to receive | Yes | | `amountIn` | Amount of `tokenIn` to send in wei (with full decimals) | Yes | | `slippage` | Slippage tolerance in basis points (100 = 1%) | No | | `receiver` | Address to receive the output tokens if not the caller | No | | `primaryAddress` | Optional address of the router or primary contract to use | No | | `poolFee` | Optional pool fee in basis points when using specific pools | No | | `destinationChainId` | Target blockchain network ID for cross-chain routing (route-bridge) | No | | `refundReceiver` | Address to receive refunds if bridge fails. Only used when `destinationChainId` is provided | Yes\* (when using `destinationChainId`) | ### `swap` Swaps one token for another using a specific pool or exchange protocol. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "uniswap-v2", action: "swap", args: { tokenIn: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH tokenOut: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC amountIn: "1000000000000000000", // 1 WETH (18 decimals) primaryAddress: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", // Uniswap V2 Router receiver: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", // Receiver slippage: "100", // Optional: 1% slippage (100 basis points) poolFee: "3000", // Optional: Pool fee in basis points (e.g., 3000 for 0.3%) }, }, ], ); ``` | Parameter | Description | Required | | ---------------- | ----------------------------------------------------------- | -------- | | `tokenIn` | Address of token to swap from | Yes | | `tokenOut` | Address of token to swap to | Yes | | `amountIn` | Amount of `tokenIn` to swap in wei (with full decimals) | Yes | | `primaryAddress` | Address of the router or pool contract | No | | `receiver` | Address to receive the output tokens | Yes | | `slippage` | Slippage tolerance in basis points (100 = 1%) | No | | `poolFee` | Optional pool fee in basis points when using specific pools | No | | `poolId` | The ID to identify the liquidity pool | No | ### `deposit` Deposits tokens into a protocol to receive a position token or add liquidity. Use the optional `positionId` to deposit into. ```js theme={null} { protocol: "morpho-markets-v1", action: "deposit", args: { amountIn: { useOutputOfCallAt: 0 }, tokenIn: TOKEN_IN_ADDRESS, receiver: WALLET_ADDRESS, primaryAddress: MORPHO, positionId: MORPHO_POSITION_ID, }, } ``` ```js theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "aave-v3", action: "deposit", args: { tokenIn: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH address tokenOut: "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", // aWETH address (optional) amountIn: "1000000000000000000", // Amount in wei (1 WETH) primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2", // Aave V3 pool receiver: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", // Optional: Receiver address }, }, ], ); ``` | Parameter | Description | Required | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------- | | `tokenIn` | Address of token to deposit. Can be a single address or an array for multiple tokens | Yes | | `tokenOut` | Address of token to receive. Can be a single address or an array for multiple tokens. Omit if position is not represented by a token. | No | | `amountIn` | Amount of `tokenIn` to deposit in wei (with full decimals). Can be a single value or an array for multiple tokens | Yes | | `primaryAddress` | Address of the protocol contract to interact with | Yes | | `receiver` | Address to receive the output tokens if not the caller | No | | `positionId` | Position ID to deposit into (e.g. Morpho Markets' positions) | No | ### `redeem` Redeems underlying assets from a protocol by exchanging shares or tokens. Use it to exit a position and retrieve the desired tokens. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ // Step 1: First deposit into the ERC4626 vault to get shares { protocol: "erc4626", action: "deposit", args: { tokenIn: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI (underlying asset) tokenOut: "0xdA816459F1AB5631232FE5e97a05BBBb94970c95", // yvDAI (vault shares) amountIn: "1000000000000000000", // 1 DAI primaryAddress: "0xdA816459F1AB5631232FE5e97a05BBBb94970c95", // Vault address }, }, // Step 2: Now redeem the shares we just received { protocol: "erc4626", action: "redeem", args: { tokenIn: "0xdA816459F1AB5631232FE5e97a05BBBb94970c95", // yvDAI shares tokenOut: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI (underlying asset) amountIn: { useOutputOfCallAt: 0 }, // Use the shares from the deposit primaryAddress: "0xdA816459F1AB5631232FE5e97a05BBBb94970c95", // Vault address receiver: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", // Optional: Receiver }, }, ], ); ``` | Parameter | Description | Required | | ---------------- | ----------------------------------------------------------------------------------- | -------- | | `tokenIn` | Address of shares/tokens to redeem | No | | `tokenOut` | Address of token(s) to receive upon redemption. Can be a single address or an array | Yes | | `amountIn` | Amount of shares/tokens to redeem in wei (with full decimals) | Yes | | `primaryAddress` | Address of the contract to interact with | Yes | | `receiver` | Address to receive the output tokens if not the caller | No | ## Bridging The `bridge` action lets you perform transactions spanning multiple chains. It relies on Stargate and LayerZero to coordinate interactions. ### `bridge` Facilitates cross-chain token transfers using various bridge protocols with optional callback actions on the destination chain. When used with callback actions (`callback` array), it can automatically execute a series of actions on the destination chain once tokens arrive. Each callback action is executed sequentially on the destination chain. **Important**: When using callbacks, the callback bundle MUST start with a balance action to check the bridged token balance on the destination chain. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11", spender: "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11", routingStrategy: "router", }, [ { protocol: "enso", action: "route", args: { tokenIn: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC on mainnet amountIn: "1000000000", // 1000 USDC tokenOut: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH }, }, { protocol: "enso", action: "fee", args: { token: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", amount: { useOutputOfCallAt: 0 }, bps: 25, receiver: "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11", // Fee receiver }, }, { protocol: "stargate", action: "bridge", args: { primaryAddress: "0x77b2043768d28e9c9ab44e1abfc95944bce57931", destinationChainId: 8453, tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", amountIn: { useOutputOfCallAt: 1 }, receiver: "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11", callback: [ { protocol: "enso", action: "balance", args: { token: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", }, }, { protocol: "enso", action: "split", args: { tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", tokenOut: [ "0x50c5725949a6f0c72e6c4a641f24049a917db0cb", "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", ], amountIn: { useOutputOfCallAt: 0 }, }, }, { protocol: "enso", action: "slippage", args: { amountOut: { useOutputOfCallAt: 1, index: 0 }, bps: 50, }, }, { protocol: "enso", action: "slippage", args: { amountOut: { useOutputOfCallAt: 1, index: 1 }, bps: 50, }, }, { protocol: "uniswap-v4", action: "depositclmm", args: { tokenOut: "0x7c5f5a4bbd8fd63184577525326123b519429bdc", ticks: [-276842, -275842], tokenIn: [ "0x50c5725949a6f0c72e6c4a641f24049a917db0cb", "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", ], poolFee: "100", amountIn: [ { useOutputOfCallAt: 1, index: 0 }, { useOutputOfCallAt: 1, index: 1 }, ], }, }, { protocol: "enso", action: "slippage", args: { amountOut: { useOutputOfCallAt: 4 }, bps: 200, }, }, ], }, }, ], ); ``` | Parameter | Description | Required | | -------------------- | ---------------------------------------------------------------------------------------------------- | -------- | | `primaryAddress` | Source bridge pool address | Yes | | `destinationChainId` | Target blockchain network ID | Yes | | `tokenIn` | Token address to bridge from source chain | Yes | | `amountIn` | Amount to bridge (with full decimals) or a reference to a previous action's output | Yes | | `receiver` | Address to receive bridged tokens on destination chain | Yes | | `callback` | Array of actions to execute on the destination chain after bridging (must start with balance action) | No | | `callbackValue` | Additional value passed to the callback (in addition to bridge token) | No | ## Slippage Protection Whereas the `route` action includes configurable slippage protection by default, but other actions require manual slippage configuration. Always include slippage protection via the `slippage` or `minAmountOut` actions to prevent price impact. ### `slippage` Applies slippage protection specified in basis points (`bps`) to ensure the received amount is within the acceptable range of the expected output. The action calculates the minimum acceptable amount based on the specified slippage tolerance (`amountOut * (10000 - bps) / 10000`). If the actual received amount falls below this threshold, the transaction will revert. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "enso", action: "slippage", args: { bps: "100", // 1% maximum slippage (100 basis points) amountOut: { useOutputOfCallAt: 0 }, // Reference previous action's output }, }, { protocol: "uniswap-v2", action: "swap", args: { tokenIn: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH tokenOut: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC amountIn: "1000000000000000000", // 1 WETH primaryAddress: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", // Uniswap V2 Router receiver: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", }, }, ], ); ``` | Parameter | Description | Required | | ----------- | ------------------------------------------------------------------------------------------ | -------- | | `amountOut` | Expected output amount - **must** be output of one of previous actions `useOutputOfCallAt` | Yes | | `bps` | Maximum acceptable slippage in basis points (1 bps = 0.01%, 100 bps = 1%) | Yes | ### `minAmountOut` Applies slippage protection specified in absolute amount (`minAmountOut`) to ensure the received amount is within the acceptable range of the expected output. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ // First action to get an output { protocol: "uniswap-v2", action: "swap", args: { tokenIn: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH tokenOut: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC amountIn: "1000000000000000000", // 1 WETH primaryAddress: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", // Uniswap V2 Router receiver: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", }, }, // Now apply minAmountOut check { protocol: "enso", action: "minamountout", args: { amountOut: { useOutputOfCallAt: 0 }, // Reference to first action's output minAmountOut: "1940000000", // Minimum amount (1.94 USDC) }, }, ], ); ``` | Parameter | Description | Required | | -------------- | ------------------------------------------------------------------------------------------ | -------- | | `amountOut` | Expected output amount - **must** be output of one of previous actions `useOutputOfCallAt` | Yes | | `minAmountOut` | Minimum acceptable amount of out token | Yes | ## Deposit & Redeem Actions ### `depositCLMM` Deposits tokens into a Concentrated Liquidity Market Maker pool (like Uniswap V3). ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11", spender: "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11", routingStrategy: "router", }, [ { protocol: "uniswap-v4", action: "depositclmm", args: { tokenOut: "0xbd216513d74c8cf14cf4747e6aaa6420ff64ee9e", ticks: [-887270, 887270], tokenIn: [ "0xdac17f958d2ee523a2206206994597c13d831ec7", // USDT "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", // WBTC ], poolFee: "500", amountIn: ["1000000000", "100000000"], // 1000 USDT (6 decimals), 1 WBTC (8 decimals) }, }, ], ); ``` | Parameter | Description | Required | | ------------- | ------------------------------------------------------------------------------------------------- | -------- | | `tokenIn` | Array of addresses of tokens to deposit (usually 2 tokens) | Yes | | `tokenOut` | Address of the position NFT to receive | Yes | | `amountIn` | Array of amounts to deposit in wei (with full decimals). Must match the length of `tokenIn` array | Yes | | `ticks` | Array containing lower and upper tick bounds defining the price range | Yes | | `poolFee` | Pool fee tier in basis points (e.g., 3000 for 0.3%) | Yes | | `receiver` | Address to receive the position NFT if not the caller | No | | `tickSpacing` | The minimum gap between valid price points for adding liquidity | No | | `hook` | The hook address for Uniswap V4 pools | No | ### `redeemCLMM` Redeems tokens from a Concentrated Liquidity Market Maker position (like Uniswap V3). ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "uniswap-v3", action: "redeemclmm", args: { tokenIn: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88", // UNI-V3-POS NFT tokenOut: [ "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC ], liquidity: "1000000000000", // Liquidity amount to withdraw tokenId: "123456", // The NFT token ID receiver: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", // Optional: Receiver }, }, ], ); ``` | Parameter | Description | Required | | ----------- | ---------------------------------------------------------- | -------- | | `tokenIn` | Address of the position NFT token | Yes | | `tokenOut` | Array of addresses of tokens to receive | Yes | | `liquidity` | Amount of liquidity to withdraw | Yes | | `tokenId` | ID of the position NFT | Yes | | `receiver` | Address to receive the underlying tokens if not the caller | No | ### `singleDeposit` Deposits a single token into a protocol. This is a specialized version of the `deposit` action for single token deposits. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "yearn", action: "singledeposit", args: { tokenIn: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI address tokenOut: "0xdA816459F1AB5631232FE5e97a05BBBb94970c95", // yvDAI address amountIn: "10000000000000000000", // 10 DAI (18 decimals) primaryAddress: "0xdA816459F1AB5631232FE5e97a05BBBb94970c95", // Yearn vault receiver: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", // Optional: Receiver }, }, ], ); ``` | Parameter | Description | Required | | ---------------- | ------------------------------------------------------------------ | -------- | | `tokenIn` | Address of the single token to deposit | Yes | | `tokenOut` | Address of the token to receive (usually a receipt or share token) | No | | `amountIn` | Amount of `tokenIn` to deposit in wei (with full decimals) | Yes | | `primaryAddress` | Address of the protocol contract to interact with | Yes | | `receiver` | Address to receive the output tokens if not the caller | No | ### `multiDeposit` Deposits multiple tokens into a protocol (like Curve or Balancer) in a single operation. ```ts theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "curve", action: "multideposit", args: { tokenIn: [ "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC "0xdAC17F958D2ee523a2206206994597C13D831ec7", // USDT ], tokenOut: "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490", // 3Crv LP token amountIn: [ "10000000000000000000", // 10 DAI (18 decimals) "10000000", // 10 USDC (6 decimals) "10000000", // 10 USDT (6 decimals) ], primaryAddress: "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", // Curve 3pool receiver: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", // Optional: Receiver }, }, ], ); console.log(JSON.stringify(bundle, null, 2)); ``` | Parameter | Description | Required | | ---------------- | ------------------------------------------------------------------------------------------------- | -------- | | `tokenIn` | Array of addresses of tokens to deposit | Yes | | `tokenOut` | Address of the LP token or receipt token to receive | No | | `amountIn` | Array of amounts to deposit in wei (with full decimals). Must match the length of `tokenIn` array | Yes | | `primaryAddress` | Address of the pool or protocol contract to interact with | Yes | | `receiver` | Address to receive the LP tokens if not the caller | No | ### `tokenizedSingleDeposit` **Deprecation Notice:** This action is deprecated in favor of using `singleDeposit` with the appropriate protocol. It will be removed in a future API version. Deposits a single token and receives a tokenized position. ```json theme={null} { "protocol": "compound-v3", "action": "tokenizedsingledeposit", "args": { "tokenIn": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC "tokenOut": "0xc3d688B66703497DAA19211EEdff47f25384cdc3", // cUSDCv3 "amountIn": "10000000", // 10 USDC (6 decimals) "primaryAddress": "0xc3d688B66703497DAA19211EEdff47f25384cdc3", // Compound market "receiver": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" // Optional: Receiver } } ``` | Parameter | Description | Required | | ---------------- | ---------------------------------------------------------- | -------- | | `tokenIn` | Address of token to deposit | Yes | | `tokenOut` | Address of tokenized position to receive | Yes | | `amountIn` | Amount of `tokenIn` to deposit in wei (with full decimals) | Yes | | `primaryAddress` | Address of the protocol contract to interact with | Yes | | `receiver` | Address to receive the position tokens if not the caller | No | ### `tokenizedMultiDeposit` **Deprecation Notice:** This action is deprecated in favor of using `multiDeposit` with the appropriate protocol. It will be removed in a future API version. Deposits multiple tokens and receives a tokenized position. ```json theme={null} { "protocol": "balancer-v2", "action": "tokenizedmultideposit", "args": { "tokenIn": [ "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", // WBTC "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" // WETH ], "tokenOut": "0x8353157092ED8Be69a9DF8F95af097bbF33Cb2aF", // BPT token "amountIn": [ "100000", // 0.01 WBTC (8 decimals) "10000000000000000" // 0.01 WETH (18 decimals) ], "primaryAddress": "0x8353157092ED8Be69a9DF8F95af097bbF33Cb2aF", // Balancer Pool "receiver": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" // Optional: Receiver } } ``` | Parameter | Description | Required | | ---------------- | ------------------------------------------------------------------------------------------------- | -------- | | `tokenIn` | Array of addresses of tokens to deposit | Yes | | `tokenOut` | Address of the tokenized position to receive | Yes | | `amountIn` | Array of amounts to deposit in wei (with full decimals). Must match the length of `tokenIn` array | Yes | | `primaryAddress` | Address of the protocol contract to interact with | Yes | | `receiver` | Address to receive the position token if not the caller | No | ### `multiOutSingleDeposit` Deposits a single token and receives multiple output tokens (typically used for certain AMM positions). ```ts theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "uniswap-v3", action: "multioutsingledeposit", args: { tokenIn: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH tokenOut: [ "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", // WBTC "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC ], amountIn: "1000000000000000000", // 1 WETH (18 decimals) primaryAddress: "0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640", // Uniswap pool receiver: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", // Optional: Receiver }, }, ], ); console.log(JSON.stringify(bundle, null, 2)); ``` | Parameter | Description | Required | | ---------------- | ---------------------------------------------------------- | -------- | | `tokenIn` | Address of the single token to deposit | Yes | | `tokenOut` | Array of addresses of tokens to receive | Yes | | `amountIn` | Amount of `tokenIn` to deposit in wei (with full decimals) | Yes | | `primaryAddress` | Address of the protocol contract to interact with | Yes | | `receiver` | Address to receive the output tokens if not the caller | No | ## Lending Actions ### `borrow` Borrows a token from a lending protocol using a deposited token as collateral. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "aave-v3", action: "deposit", args: { tokenIn: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH address tokenOut: "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", // aWETH address (optional) amountIn: "1000000000000000000", // Amount in wei (1 WETH) primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2", // Aave V3 pool receiver: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", // Optional: Receiver address }, }, { protocol: "aave-v3", action: "borrow", args: { collateral: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH address (collateral) tokenOut: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC address (to borrow) amountOut: "1000000000", // Amount to borrow in wei (1000 USDC with 6 decimals) primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2", // Aave V3 pool }, }, ], ); ``` | Parameter | Description | Required | | ---------------- | --------------------------------------------------------------------------------------- | -------- | | `collateral` | Address of the token used as collateral. Can be an array for multiple collateral tokens | Yes | | `tokenOut` | Address of the token to borrow | Yes | | `amountOut` | Amount to borrow in wei (with full decimals) | Yes | | `primaryAddress` | Address of the lending pool contract | Yes | ### `repay` Repays a loan on a lending protocol. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "aave-v3", action: "deposit", args: { tokenIn: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH address tokenOut: "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8", // aWETH address (optional) amountIn: "1000000000000000000", // Amount in wei (1 WETH) primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2", // Aave V3 pool receiver: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", // Optional: Receiver address }, }, { protocol: "aave-v3", action: "borrow", args: { collateral: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH address (collateral) tokenOut: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC address (to borrow) amountOut: "1000000000", // Amount to borrow in wei (1000 USDC with 6 decimals) primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2", // Aave V3 pool }, }, // Step 3: Now repay the borrowed USDT { protocol: "aave-v3", action: "repay", args: { tokenIn: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC amountIn: "1000000000", // 100 USDC primaryAddress: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2", }, }, ], ); ``` | Parameter | Description | Required | | ---------------- | ------------------------------------------- | -------- | | `tokenIn` | Address of token to repay | Yes | | `amountIn` | Amount to repay in wei (with full decimals) | Yes | | `primaryAddress` | Address of the lending pool contract | Yes | | `onBehalfOf` | Address to repay debt for | Yes | ### `repay` on Behalf of Another address Repay parameter `onBehalfOf` enables you to repay a loan on behalf of a given address: ```js theme={null} const bundleData = await client.getBundleData( { chainId: 1, // Mainnet fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045" as Address, routingStrategy: "delegate", }, [ // 3. Repay the ETH debt { protocol: "compound-v2", action: "repay", args: { tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH amountIn: "300000000000000000", primaryAddress: "0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5", // cETH contract onBehalfOf: "0x80fCBfbC698Aca3B3BCB83ceB13301a639A39832", }, }, ], ); console.log(bundleData); ``` ## Yield Farming Actions ### `harvest` Harvests rewards from yield-generating positions. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "curve-gauge", action: "harvest", args: { token: "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0", // Token address (LP token or gauge token) primaryAddress: "0x182B723a58739a9c974cFDB385ceaDb237453c28", // Curve gauge address }, }, ], ); ``` | Parameter | Description | Required | | ---------------- | ------------------------------------------------------------ | -------- | | `token` | Address of token to harvest rewards for | Yes | | `primaryAddress` | Address of the contract to interact with (e.g., gauge, farm) | Yes | ## Token Management Actions ### `approve` Approves a spender to use tokens. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "erc20", action: "approve", args: { token: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH address spender: "0xe592427a0aece92de3edee1f18e0157c05861564", // Spender address (e.g., Uniswap router) amount: "1000000000000000000000000", // Amount to approve in wei (1M WETH) }, }, ], ); ``` | Parameter | Description | Required | | --------- | --------------------------------------------- | -------- | | `token` | Address of the token to approve | Yes | | `spender` | Address of the spender (protocol or router) | Yes | | `amount` | Amount to approve in wei (with full decimals) | Yes | ### `transfer` Transfers tokens to a specified address. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "erc20", action: "transfer", args: { token: "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07", // OMG token address receiver: "0x80eba3855878739f4710233a8a19d89bdd2ffb8e", // Recipient address amount: "1000000000000000000", // Amount to transfer in wei (1 OMG) id: "1234", // Optional: ID for ERC721 or ERC1155 tokens }, }, ], ); ``` | Parameter | Description | Required | | ---------- | ---------------------------------------------- | -------- | | `token` | Address of the token to transfer | Yes | | `receiver` | Address of the recipient | Yes | | `amount` | Amount to transfer in wei (with full decimals) | Yes | | `id` | Token ID for ERC721 or ERC1155 tokens | No | ### `transferFrom` Transfers tokens from a specified address to another address. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "enso", action: "balance", args: { token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", }, }, { protocol: "erc20", action: "transferfrom", args: { token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // OMG token address sender: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", // Sender address receiver: "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11", // Recipient address amount: "1000000000000000000", // Amount to transfer in wei (1 OMG) }, }, ], ); ``` | Parameter | Description | Required | | ---------- | ---------------------------------------------- | -------- | | `token` | Address of the token to transfer | Yes | | `sender` | Address of the sender | Yes | | `receiver` | Address of the recipient | Yes | | `amount` | Amount to transfer in wei (with full decimals) | Yes | | `id` | Token ID for ERC721 or ERC1155 tokens | No | ### `permitTransferFrom` Approves and transfers a token that supports permit in a single step using a signature. A permit signature needs to be generated offchain and passed to the API. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "permit2", action: "permittransferfrom", args: { token: "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07", // Token address amount: "1000000000000000000", // Amount in wei (1 token) sender: "0xb67f3CE46bB9E1a1127796c27f38DbaB9f643ec0", // Sender address receiver: "0x35a2839b617F7da6534d636f22945f6Cb6137130", // Receiver address nonce: "1", // Nonce to prevent replay attacks deadline: "1710150268", // Timestamp deadline for signature validity signature: "0x...", // Permit signature }, }, ], ); ``` | Parameter | Description | Required | | ----------- | ----------------------------------------------------------------------------------- | -------- | | `token` | Address of the token to transfer. Can be an array for multiple tokens | Yes | | `amount` | Amount to transfer in wei (with full decimals). Can be an array for multiple tokens | Yes | | `sender` | Address of the sender | Yes | | `receiver` | Address of the recipient | Yes | | `nonce` | Nonce value to prevent signature replay | Yes | | `deadline` | Timestamp after which the signature is invalid | Yes | | `signature` | The EIP-2612 permit signature | Yes | ## Utility Actions ### `balance` Gets the balance of a token for the caller's address. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "enso", action: "balance", args: { token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC }, }, ], ); ``` | Parameter | Description | Required | | --------- | ------------------------------------- | -------- | | `token` | Address of the token to check balance | Yes | ### `split` Splits a token into multiple outputs with specified token addresses and amounts. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "enso", action: "balance", args: { token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC }, }, { protocol: "enso", action: "split", args: { tokenIn: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC tokenOut: [ "0x6b175474e89094c44da98b954eedeac495271d0f", // DAI "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH ], amountIn: { useOutputOfCallAt: 0 }, // Use the balance from the first action }, }, ], ); ``` | Parameter | Description | Required | | ---------- | ---------------------------------------------- | -------- | | `tokenIn` | Address of the token to split | Yes | | `tokenOut` | Array of token addresses for the split outputs | Yes | | `amountIn` | Amount to split in wei (with full decimals) | Yes | | `receiver` | Address to receive the split tokens | No | ### `merge` Merge multiple token inputs into a single output. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "enso", action: "merge", args: { tokenIn: [ "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC "0x6b175474e89094c44da98b954eedeac495271d0f", // DAI ], tokenOut: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // Combined WETH amountIn: [ "2000000000000000000000", // 2 USDC "3000000000000000000000", // 3 DAI ], receiver: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", }, }, ], ); ``` | Parameter | Description | Required | | ---------- | ------------------------------------------------------------ | -------- | | `tokenIn` | Array of input token addresses | Yes | | `tokenOut` | Address of the output token | Yes | | `amountIn` | Array of amounts to merge (must be in the same denomination) | Yes | | `receiver` | Address to receive the merged tokens | No | ### `call` Makes an arbitrary call to any contract, allowing for custom interactions. For example, making a [custom contract call](/pages/build/examples/custom-call-bundle) when the protocol demands additional arguments. This is useful for executing complex logic or interacting with contracts that are not directly supported by the Enso API. To perform arithemtics over return values from previous actions, you can use the PercentageMathHelpers contract: ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "enso", action: "call", args: { address: "0xD0aF6F692bFa10d6a535A3A321Dc8377F4EeEF12", // Contract address method: "percentMul", // Method name abi: "function percentMul(uint256,uint256) external", // ABI signature args: [ "1000000000000000000", // 1 ETH (first argument) "7000", // 70% (second argument) ], }, }, ], ); ``` Add these parameters to the `call` action documentation: | Parameter | Description | Required | | ---------- | ----------------------------------------------------------- | -------- | | `address` | Address of the contract to call | Yes | | `method` | Name of the method to call | Yes | | `abi` | ABI signature of the method | Yes | | `args` | Array of arguments to pass to the method | Yes | | `tokenIn` | Input token address (when tokens are involved in the call) | No | | `tokenOut` | Output token address (when tokens are involved in the call) | No | | `value` | ETH value to send with the transaction in wei | No | ### `fee` Calculates and deducts a fee from a specified amount, sending the fee to a designated receiver. This action is typically prepended to bridge operations to facilitate fee collection. The `fee` action calculates the fee as `amount * (bps/10000)` and sends this amount to the `receiver`. It returns `amount - fee`, which can be used in subsequent actions via `useOutputOfCallAt`. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "enso", action: "fee", args: { token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", amount: "1000000000000", bps: "500", receiver: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", }, }, ], ); ``` | Parameter | Description | Required | | ---------- | ---------------------------------------------------------------------------------------- | -------- | | `token` | Token address to apply the fee to | Yes | | `amount` | Amount to apply the fee to (with full decimals) or a return value from a previous action | Yes | | `bps` | Fee percentage in basis points (1 bps = 0.01%, 100 bps = 1%) | Yes | | `receiver` | Address to receive the fee | Yes | ### `ensofee` Calculates and deducts Enso's protocol fee from a specified amount. The `fee` action calculates the fee as `amount * (bps/10000)` and sends this amount to Enso. It returns `amount - fee`, which can be used in subsequent actions via `useOutputOfCallAt`. ```typescript theme={null} const bundle = await client.getBundleData( { chainId: 1, fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", routingStrategy: "delegate", }, [ { protocol: "enso", action: "ensofee", args: { token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC amount: "1000000000", // 1000 USDC bps: "25", // 0.25% fee (25 basis points) }, }, ], ); ``` | Parameter | Description | Required | | --------- | ---------------------------------------------------------------------------------------- | -------- | | `token` | Token address to apply the fee to | Yes | | `amount` | Amount to apply the fee to (with full decimals) or a return value from a previous action | Yes | | `bps` | Fee percentage in basis points (1 bps = 0.01%, 100 bps = 1%) | Yes | ## Protocol Support The Bundle API supports a wide range of protocols. Some common ones include: * `aave-v2`, `aave-v3`: Aave lending/borrowing * `balancer-v2`: Balancer liquidity pools * `curve`: Curve Finance stable swaps and gauges * `curve-gauge`: Curve gauges for staking * `erc20`: Standard token operations * `erc4626`: ERC4626 vaults * `enso`: General Enso operations including route and arbitrary calls * `permit2`: Uniswap's Permit2 operations * `uniswap-v2`, `uniswap-v3`: Uniswap pools and routers * `yearn`: Yearn Finance vaults * `compound-v2`, `compound-v3`: Compound lending/borrowing * `stargate`: Cross-chain bridging For a complete list of supported protocols, use the Projects API endpoint: [GET `/standards`](/api-reference/integration/standards).

Updated {date_0}

# Concepts Source: https://docs.enso.build/pages/build/reference/concepts Understand Enso's core concepts and how they work. export const date_0 = "2025-07-07" ## Projects A project in Enso represents an overarching blockchain platform or financial service with multiple protocol implementations. Projects serve as the top-level categorization in Enso's data model, grouping related protocols Example: The "Aave" project encompasses protocols "aave-v2" and "aave-v3". **API Reference:** * [GET `/projects`](/api-reference/integration/projects) - Returns all available projects * [GET `/projects/protocols`](/api-reference/integration/protocols-in-a-project) - Returns protocols available for a specific project ## Protocols A protocol is a specific implementation or version of a project deployed on one or more blockchain networks. Each protocol has a unique identifier (slug), defined functionality, and standardized interfaces. For example, "uniswap-v3" specifies the exact smart contract implementations, supported chains, and available actions for that particular version of Uniswap. **API Reference:** * [GET `/projects/protocols`](/api-reference/integration/protocols-in-a-project) - Returns all supported protocols and their metadata * [GET `/integration/{slug}`](/api-reference/integration/standard-per-protocol) - Returns details for a specific protocol by slug ## Standards A standard defines the interface specifications and methods for interacting with protocols. Standards document the common patterns across similar protocols, including required inputs, function signatures, and expected outputs. This standardization layer enables Enso to abstract implementation details and *provide consistent interfaces* across varied DeFi protocols. **API Reference:** * [GET `/standards`](/api-reference/integration/standards) - Returns all available standards and their methods * [GET `/actions`](/api-reference/integration/supported-actions) - Returns all standardized actions available for protocols ## Actions An action is a discrete operation performed on a protocol (e.g., "deposit", "withdraw", "swap", "borrow"). Actions specify the required input parameters and expected outputs for each operation type. Enso's action abstraction allows developers to *execute the same conceptual operation* across different protocols without handling protocol-specific implementation details. Actions can be bundled into atomic multi-step transactions. **API Reference:** * [GET `/actions`](/api-reference/integration/supported-actions) - Returns all available actions and their input parameters * [POST `/shortcuts/bundle`](/api-reference/defi-shortcuts/bundle-a-list-of-actions) - Allows bundling multiple actions into a single transaction ## Tokens Enso recognizes two primary token types: 1. **Base Token**: Standard cryptocurrency assets without DeFi positioning (e.g., ETH, WETH, USDC, DAI). These tokens serve as the building blocks for DeFi operations. 2. **DeFi Token**: Tokens representing positions in DeFi protocols (e.g., yvWETH for Yearn-deposited WETH, aDAI for Aave-deposited DAI). These tokens contain metadata about their protocol association, underlying assets, APY, and TVL metrics. **API Reference:** * [GET `/tokens/tokens`](/api-reference/tokens/tokens) - Returns all supported tokens with filtering options for type, protocol, etc. * [GET `/defi/prices`](/api-reference/tokens/token-price) - Returns price data for a specific token Both token types include core properties (address, chainId, decimals, symbol, name, logoUri), with DeFi tokens containing additional protocol-specific metadata.

Updated {date_0}

# Contracts and Deployments Source: https://docs.enso.build/pages/build/reference/deployments Enso contracts deployment addresses export const date_0 = "2025-10-22" The onchain interactions—executing the calldata Enso composes—happens via two smart contracts: * **EnsoRouter** that executes the submitted route with `router` strategy (`router-legacy` for V1). * **DelegateEnsoShortcuts** that executes the shortcut with `delegate` strategy (`delegate-legacy` for V1). Use the `response.tx.to` field from the [`/route`](/api-reference/defi-shortcuts/optimal-route-between-two-tokens) and [`/bundle`](/api-reference/defi-shortcuts/bundle-a-list-of-actions) endpoints instead of hardcoding Router and DelegateEnsoShortcuts addresses in your code. ## V2 Contracts Deployment addresses for EnsoRouter and Delegate V2 on supported networks.
Network Router V2 Delegate V2
Ethereum `1` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Optimism `10` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Binance `56` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Gnosis `100` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Unichain `130` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Polygon `137` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Sonic `146` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
ZkSync `324` `0x1BD8CefD703CF6b8fF886AD2E32653C32bc62b5C` `0x4c3Db0fFf66f98d84429Bf60E7622e206Fc4947c`
World `480` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Hyper `999` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Soneium `1868` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Base `8453` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Arbitrum `42161` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Avalanche `43114` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Ink `57073` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Linea `0xA146d46823f3F594B785200102Be5385CAfCE9B5` `0xEe41aB55411a957c43C469F74867fa4671F9f017`
Berachain `80094` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Plume `98866` `0x3067BDBa0e6628497d527bEF511c22DA8b32cA3F` `0x973e7203f1B7fbcc156b4BD8734fc66790e689C5`
Sepolia `11155111` `0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf` `0x7663fd40081dcCd47805c00e613B6beAc3B87F08`
Katana `747474` `0x3067BDBa0e6628497d527bEF511c22DA8b32cA3F` `0x973e7203f1B7fbcc156b4BD8734fc66790e689C5`
Plasma `9745` `0xCfBAa9Cfce952Ca4F4069874fF1Df8c05e37a3c7` `0xA2F4f9C6ec598CA8c633024f8851c79CA5F43e48`
## V1 Contracts Deployment addresses for EnsoRouter and Delegate V1 on supported networks.
Network Router V1 Delegate V1
Ethereum `1` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Optimism `10` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Binance `56` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Gnosis `100` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Unichain `130` - -
Polygon `137` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Sonic `146` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
ZkSync `324` `0xd12ecDD67300D5ef0A68576CfDF038bAB5b5054a` `0x43BD12326142568D5Cc33c7326A68Ca4e0be9292`
World `480` - -
Hyper `999` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Soneium `1868` - -
Base `8453` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Arbitrum `42161` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Avalanche `43114` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Ink `57073` - -
Linea `59144` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Berachain `80094` `0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E` `0x38147794ff247e5fc179edbae6c37fff88f68c52`
Sepolia `11155111` - -
Katana `747474` - -
Plume `98866` - -

Updated {date_0}

# FAQ Source: https://docs.enso.build/pages/build/reference/faq Find answers to common questions. export const date_0 = "2025-09-18" ## Integration ### What networks does Enso support? Enso supports multiple EVM-compatible networks. Check the [Supported Networks](/pages/build/reference/supported-networks) page for the latest list. *** ### What protocols does Enso support? Enso supports 140+ protocols across various categories. Use the [GET `/standards`](/api-reference/integration/standards) endpoint to get the latest list. Here's a complete list of supported protocols: * "bex" * "aave" * "radiant" * "zerolend" * "spark" * "angle" * "ankr" * "aura" * "avalon" * "balancer" * "burrbear" * "bancor" * "bedrock" * "beefy" * "beets" * "berachain-honey" * "compound-finance" * "venus" * "apeswap" * "flux-finance" * "iron-bank" * "moonwell" * "benqi" * "compound" * "convex" * "aura-lp" * "curve" * "dinero" * "erc20" * "erc4626" * "frax-finance" * "inverse-finance" * "gearbox" * "ethena" * "adapter-fi" * "mstable" * "idle" * "yieldnest" * "morpho" * "exactly" * "cian-protocol" * "reserve-protocol" * "d2-finance" * "mountain-protocol" * "gains-network" * "dolomite" * "concrete" * "acorn-wabtc" * "resolv" * "tokemak" * "liftdollar" * "rings" * "beraborrow" * "origami" * "the-honey-jar" * "dahlia" * "origin-protocol" * "infrared" * "yield-fi" * "etherfi" * "euler" * "fluid" * "frax" * "genesis-lrt" * "gmx" * "goldilocks" * "harvest-finance" * "inception-lrt" * "ipor" * "kelp" * "kelp-rseth-wrapped" * "kernel" * "kiln" * "kodiak" * "lido" * "locus" * "lorenzo" * "mantle" * "maverick" * "moby" * "molten" * "mozaic" * "pendle" * "permit2" * "pickle" * "polygon" * "pooltogether" * "primex" * "prisma" * "pumpbtc" * "renzo" * "reserve" * "reservoir" * "restake" * "rocketpool" * "origin" * "stakestone" * "satlayer" * "silo" * "sky" * "solv" * "sommelier" * "stability" * "stable-jack" * "stader" * "stakedao" * "stargate" * "steer" * "summer-fi" * "swell" * "symbiotic" * "shibaswap" * "verse" * "uniswap" * "unsheth" * "usual" * "vaultcraft" * "vector" * "veda" * "velodrome" * "aerodrome" * "vesper" * "wrapped-native" * "yearn" * "pancakeswap" * "sushiswap" * "pangolin" * "beradrome" * "camelot" * "trader-joe" * "pancakeswap-amm-v3" * "bakerdao" * "treehouse" * "shadow-exchange" * "swapx" * "vicuna" * "yeet" * "level *** ### Is it safe and secure to use Enso as a third party service? Enso prioritizes security in the following ways: * Smart contract code is [audited](https://github.com/EnsoBuild/enso-audits). * All transactions are simulated before execution, with actual values returned in the API response * End users can independently simulate transactions using Tenderly before on-chain execution *** ### What is the default rate limit for the API? Rate limits can be increased [on demand](https://t.me/enso_shortcuts). The default rate limit is 10 requests per second (RPS). When the limit is exceeded, you'll receive a `429 Too Many Requests` error. *** ### How do I request support for a new token or protocol? We are constantly expanding our support for new assets and protocols. If you'd like to request an integration, please reach out to our BD or DevRel team in [Telegram Dev Channel](https://t.me/enso_shortcuts) or our shared channel. ## API Basics ### What's the difference between `route` and `bundle` endpoints? **The `route` is optimally pre-populated `bundle`** The `route` API automatically creates a bundle of actions in order to find the optimal route for your desired outcome. The `bundle` API allows you to specify the exact actions and protocols you want to use in your transaction. * The [POST `/shortcuts/route`](/api-reference/defi-shortcuts/optimal-route-between-two-tokens) API endpoint is used when: * You want an optimal path from any token `tokenIn` to any token `tokenOut` * You don't care about the specific actions and intermediary tokens on the route * You're using tokenized positions (for non-tokenized positions, use the `nontokenized` endpoint) * The [POST `/shortcuts/bundle`](/api-reference/defi-shortcuts/bundle-a-list-of-actions) endpoint is used when: * You want to to bundle multiple actions into a single transaction * You want to use specific protocols for your route * You want to actions like `harvest` and `redeem` *** ### What's the difference between `route` and `nontokenized` endpoints? * The [POST `/shortcuts/route`](/api-reference/defi-shortcuts/optimal-route-between-two-tokens) API endpoint is used for tokenized positions where you receive a token representing your position (like aTokens in Aave). * The [GET `/shortcuts/route/nontokenized`](/api-reference/defi-shortcuts/routing-to-a-non-tokenized-position) endpoint is for non-tokenized positions, which are stored directly in a smart contract (usually a Smart Wallet). *** ### When do I need to use a Smart Wallet? Use the Smart Wallet (mandatory `delegate` routing strategy) with either `shortcuts/route`, `shortcuts/bundle` and `shortcuts/route/nontokenized` when: * You are using a Smart Wallet (like Argent or Gnosis Safe) * You want a `POST /shortcuts/bundle` including [`harvest`](/pages/build/reference/actions#harvest) or [`redeem`](/pages/build/reference/actions#redeem) actions * You want to use `GET /shortcuts/route/nontokenized` endpoint * You want to specify a [`spender` address](/api-reference/defi-shortcuts/optimal-route-between-two-tokens-1#body-spender) for `redeem` actions *** ### What is the difference between `router` and `delegate` routing strategies? Both routing strategies are used with `POST /shortcuts/route`, and `POST /shortcuts/bundle`, and `POST /shortcuts/route/nontokenized` endpoints: * `router`: Standard routing strategy for EOAs (Externally Owned Accounts). With this strategy, prior to executing your route, you must approve Enso Router to spend input tokens. You can do so by using [`approve` API](/api-reference/defi-shortcuts/approve-enso-contract). * `delegate`: Routing strategy for smart wallets, allowing for delegate calls. No approvals necessary prior to sending transaction. You also must use `delegate` for actions such as `borrow`, `harvest`, and `repay`. The routing strategy instructs the API on how to build the transaction calldata, and which of Enso's smart contracts to use for execution. The API response contains the calldata and the correct recipient in `tx.to` field, that points to [one of Enso's contracts](/pages/build/reference/deployments). Learn more about [routing strategies](/pages/build/reference/routing-strategies). *** ### How do I authenticate API requests? API requests require an authentication token in the Authorization header: ``` -H 'Authorization: Bearer YOUR_API_KEY' ``` *** ### How do I get and use the returned calldata? The API returns transaction calldata that should be sent to the [`EnsoShortcutRouter`](https://etherscan.io/address/0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E#code) contract. ## Routing Mechanics ### How does the routing work behind the scenes? Enso's router functions as a configurable multicall that can execute multiple actions in a single transaction on a specific chain. It optimizes the route based on current market conditions to find the best path for your transaction, whether it's a swap, zap, deposit and so on. *** ### Does Enso support cross-chain transactions? Both `route` and `bundle` API support crosschain routing. *** ### What contract does the calldata interact with? The calldata should be sent to the [`EnsoShortcutRouter`](https://etherscan.io/address/0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E#code) contract on the respective chain. *** ### How does Enso handle wallet types? Enso recognizes two different [routing strategies](/pages/build/reference/routing-strategies). * The standard `route` routing strategy is designed for EOAs (Externally Owned Accounts). To use a smart wallet, use `delegate` routing strategy. *** ### What happens if the user doesn't have sufficient funds? The API will return a route, but transaction execution will fail if sufficient funds aren't available. ## OneStable (crosschain routing) ### How do I do complex multichain routing For complex multichain routing, you can use nested bridge actions with callbacks, chaining operations across multiple chains in a single bundle. [**Crosschain Routing**](/pages/build/get-started/crosschain-routing) *** ### Are there any limitations on callback complexity? * **Maximum actions**: Bundles support up to 10 actions total (including those in callbacks) *** ### How do I ensure my funds are safe during cross-chain operations? Always set both `receiver` and `refundReceiver` addresses when using bridge callbacks. The `refundReceiver` gets the refund if callback actions fail on the destination chain. If `refundReceiver` is not set, tokens go to the `receiver` address on failure. *** ### How do I estimate the total gas cost across multiple chains, including callback execution? The bundle API returns the simulated gas it will use in the response. You can provide an additional `callbackGasLimit` parameter to control the maximum gas the transaction can spend on the destination chain to avoid excessive gas consumption. *** ### Can I query the status of a pending bridge transaction? You can use the LayerZero Scan API to track bridge transaction status by passing the transaction hash: ``` https://scan.layerzero-api.com/v1/messages/tx/{txHash} ``` This allows you to monitor the bridge status after submitting the transaction through the Enso SDK. *** ### What happens to my bridge callback actions if one fails midway? If the transaction on the destination chain fails/reverts, the bridged tokens are sent to the refundReceiver address (or receiver if no refundReceiver is specified).Retry *** ### How do I know if a token has a valid pool on both source and destination chains? The SDK provides the getLayerZeroPool() method to check if a pool exists for a token/chain combination. Additionally, when you make a bundle request, it will simulate the entire cross-chain transaction and fail if pools don't exist. ```typescript theme={null} const poolsInfo = await client.getLayerZeroPool({ chainId: 1, token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', destinationChainId: '8453', destinationToken: '0x...' }); console.log(poolsInfo[0]); ``` *** ### What happens if the destination pool doesn't have enough liquidity? ## Error Handling ### How can I test transactions before executing them? You can simulate transactions using Tenderly before executing them on-chain. ## Enso Contracts ### Are the Enso smart contracts upgradable? What are the security implications? Our core routing logic is handled by immutable, audited smart contracts to ensure maximum security. We use a delegate proxy pattern to enable simplified interaction when signing via Smart Wallets, controlled by the [`routingStrategy` API parameter](#what-is-the-difference-between-router-and-delegate-routing-strategies). All contract updates undergo rigorous internal testing and external audits before deployment. Learn more about [Enso contracts](/pages/build/reference/deployments). ## Integration Patterns ### How should I implement recurring transactions? Since routes are dynamic and market conditions change, the best approach for recurring transactions is to use an off-chain actor that calls the API periodically to get the latest optimal route. *** ### How can I integrate Enso with a custom smart contract? You can create a custom contract that calls the [`EnsoShortcutRouter`](https://etherscan.io/address/0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E#code) with the data returned from the API. *** ### Can I integrate Enso with a bot? Yes, Enso's API is suitable for bot integration, such as for dutch auction fills, liquidation bots, or automated trading strategies. *** ### What types of DeFi operations does Enso support? Enso supports a wide [range of DeFi operations](/pages/build/reference/actions) including swaps, deposits, lending, borrowing, staking into LSTs, and complex compositions of these actions. ## DeFi FAQ ### How is slippage handled in routes? Slippage is specified in basis points as a parameter in API calls (e.g., 300 = 3%). The response amount `tokenOut` accounts for any slippage, as the API simulates the transaction before returning the route. *** ### How do I know the price imapct of my route? When using `POST /shortcuts/route`, `POST /shortcuts/bundle`, or `POST /shortcuts/route/nontokenized`, the API returns the `priceImpact` field. This value is obtained from a transaction simulation, and indicates the expected price impact. *** ### Does `redeem` action withdraw additional pool rewards? The `redeem` action does not withdraw additional pool rewards. It only redeems the underlying asset from the pool. To withdraw rewards, use the `harvest` action. ## Common Errors and Solutions ### "Could not build shortcuts for route" Error This error in `/shortcuts/route` API indicates that Enso couldn't find a valid route between the specified tokens on the specified network. Possible solutions: * Verify token addresses are correct * Check if the token pair is supported on the specified chain * Verify the protocol integration is working * Check if your operation demands a `redeem` or `harvest` action, which must be used via the `bundle` endpoint, using the `delegate` routing strategy.

Updated {date_0}

# Licence & Legal Source: https://docs.enso.build/pages/build/reference/legal Understand the legal aspects of using Enso API. export const date_0 = "2025-06-30" # Legal Information for Enso API Builders ## Overview As an Enso API builder, it's important to understand the legal framework governing your use of our APIs. This page provides key information about legal considerations and links to our comprehensive legal documentation. ## API License Agreement Before integrating with the Enso API, please review our API License Agreement. This agreement outlines the terms and conditions for using our APIs, including: * License scope and limitations * Intellectual property rights * Usage restrictions * Data privacy considerations * Support provisions * Payment terms (if applicable) * Confidentiality requirements * Termination conditions ## Key Legal Considerations When building with the Enso API, keep these important legal points in mind: 1. **License Limitations**: The license granted is limited, non-exclusive, non-transferable, and may not be sublicensed. 2. **Usage Restrictions**: There are specific restrictions on how you can use the API, including prohibitions against reverse engineering and competing services. 3. **End User Agreements**: You must have appropriate agreements with your end users that protect Enso's rights. 4. **Ownership**: Enso maintains ownership of the API, platform, content, and related intellectual property. 5. **Data Privacy**: When using the API, certain information is shared with Enso and must be handled in accordance with data protection laws. ## Documentation Links For complete legal information, please review the following documentation: By accessing and using the API, you accept to be bound by the linked license agreement. You must read the Agreement carefully. * [API License Agreement](https://drive.google.com/file/d/1Z_szzLwwLqx9v6liyslKsos75I17obDS/view?usp=sharing) ## Questions or Concerns If you have any questions about the legal aspects of using the Enso API, please contact us at [partners@enso.finance](mailto:partners@enso.finance). *** **Note**: The information on this page is provided for guidance only. Always refer to the complete legal documents for definitive information about your rights and obligations when using the Enso API.

Updated {date_0}

# Routing Strategies Source: https://docs.enso.build/pages/build/reference/routing-strategies Understand `delegate` and `route` routing strategies for shortcuts APIs. export const date_0 = "2025-08-07" When using the Shortcuts endpoints (`/shortcuts/route` and `/shortcuts/bundle`), you must choose between two routing strategies: `router` and `delegate`. Based on the strategy you choose, the Enso API will route your transaction through the appropriate smart contract. **Use the `tx.to` response value** when sending on-chain a shortcut transaction you obtained. By avoiding hardcoded addresses, your shortcuts will always be routed to the correct contract, even if the address changes in the future. For specific addresses, check out [Deployments](/pages/build/reference/deployments) ## When to use `delegate` or `router`? You must use `delegate` when: * dealing with [non-tokenized positions](/pages/build/examples/route-nontokenized) where the state is stored in the protocol rather than represented by a token * you need the state to persist in the user's smart wallet. ## Smart Wallets with `delegate` Smart Wallet executes the bundle directly through delegate calls, by calling [`EnsoShortcutsDelegate` contract](./deployments), and the wallet itself doesn't hold any tokens during the execution. ```ts theme={null} // no approvals of input tokens needed const route = await client.getRouteData({ routingStrategy: "delegate", //... }); await signSmartWallet(route.tx, route.gas); ``` Use delegate for smart wallets Use `delegate` for smart wallets supporting `delegatecall`: * Enables both tokenized and non-tokenized interactions * The state stays in the smart wallet itself. * Complex, multi-step operations are more efficient and safer when executed through a smart wallet * Simple approval model * Limited to token-based operations ## EOAs with `router` With `router` strategy, the Enso Router contract will hold the intermediate tokens between actions. With this strategy, you must approve the Enso router contract to operate with your input tokens: ```ts theme={null} const approval1 = await client.getApprovalData({ tokenAddress: token1, amount: amt1, chainId, fromAddress, }); const approval2 = await client.getApprovalData({ tokenAddress: token2, amount: amt2, chainId, fromAddress, }); const route = await client.getRouteData({ routingStrategy: "router", //... }); await signEoa(approval1.tx, approval1.gas); await signEoa(approval2.tx, approval2.gas); await signEoa(route.tx, route.gas); ``` Use router for EOA Use `router` strategy for EOAs or simpler smart wallets: * Works with tokenized interactions only * Uses the universal router contract. * Supports tokenized and non-tokenized interactions * Enables complex DeFi strategies * Works with lending positions and other stateful interactions

Updated {date_0}

# Supported Networks Source: https://docs.enso.build/pages/build/reference/supported-networks Chains supported by Enso API. export const date_0 = "2025-07-31" Enso currently supports the following networks: * Ethereum (1) * Arbitrum (42161) * Avalanche (43114) * Base (8453) * Berachain (80094) * Binance (56) * Gnosis (100) * Hyper (999) * Ink (57073) * Linea (59144) * Optimism (10) * Plume (98866) * Polygon (137) * Sepolia (11155111) * Soneium (1868) * Sonic (146) * Unichain (130) * World (480) * Zksync (324) * Katana (747474) * Plasma (9745) You can use the [GET `/networks`](/api-reference/integration/networks) endpoint to get the list of supported networks programmatically. ```bash theme={null} curl -X 'GET' \ 'https://api.enso.finance/api/v1/networks' \ -H 'accept: application/json' \ -H "Authorization: Bearer $ENSO_API_KEY" \ | jq -r '.[] | "\(.name) (\(.id))"' | paste -sd '\n' - ```

Updated {date_0}

# Whitepaper Source: https://docs.enso.build/pages/build/reference/whitepaper Whitepaper TODO # Changelog Source: https://docs.enso.build/pages/changelog Latest updates on API changes, supported protocols, positions, and chains in Enso. # Changelog ### Enso Checkout Enso Checkout is the universal payment layer for Web3. It allows users to accept payments from anywhere: * Deposit from any chain into any protocol * Use CEX funds onchain (Binance, Bybit, OKX + more) * Fiat onramp: card + bank