> ## Documentation Index
> Fetch the complete documentation index at: https://docs.enso.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Actions

> Actions are interactions with DeFi protocols Enso supports.

export const date_0 = "2026-03-12"

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.

<Tip>
  **Would `route` (`client.getRouteData`) do the job?** <br />
  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)
</Tip>

<Info>
  To get the up-to date list of available actions and parameters, use [GET
  `/integration/actions`](/api-reference/integration/supported-actions).
  <br /> 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).
</Info>

## 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.

<Tip>
  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)
</Tip>

```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.

```typescript theme={null}
const bundle = await client.getBundleData(
  {
    chainId: 1,
    fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
  },
  [
    {
      protocol: "enso",
      action: "route",
      args: {
        tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH
        tokenOut: "0x94b008aa00579c1307b0ef2c499ad98a8ce58e58", // USDT on Optimism
        amountIn: "1000000000000000000", // 1 ETH in wei
        destinationChainId: 10, // Optimism
        receiver: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", // Optional: receiver
      },
    },
  ],
);
```

| 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       |

### `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.

<Tabs>
  <Tab title="Morpho">
    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,
      },
    }
    ```
  </Tab>

  <Tab title="Aave">
    ```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
          },
        },
      ],
    );
    ```
  </Tab>
</Tabs>

| 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.

<Note>
  **Important**: When using callbacks, the callback bundle MUST start with a
  balance action to check the bridged token balance on the destination chain.
</Note>

```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.

<Warning>
  Always include slippage protection via the `slippage` or `minAmountOut`
  actions to prevent price impact.
</Warning>

### `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`

<Warning>
  **Deprecation Notice:** This action is deprecated in favor of using
  `singleDeposit` with the appropriate protocol. It will be removed in a future
  API version.
</Warning>

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`

<Warning>
  **Deprecation Notice:** This action is deprecated in favor of using
  `multiDeposit` with the appropriate protocol. It will be removed in a future
  API version.
</Warning>

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

### `flashloan`

Borrows tokens from a lending protocol without upfront collateral, executes callback actions atomically, and repays the debt within the same transaction.

<Info>
  Flashloans have dedicated documentation. See the [Flashloans
  Reference](/pages/build/reference/flashloans) for supported protocols, chain
  availability, parameters, and examples.
</Info>

### `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      |

<Info>
  The balance action supports advanced parameters for checking external account
  balances and building routes with estimated amounts. See the [Advanced Balance
  Reference](/pages/build/reference/balance) for details, risk considerations,
  and examples.
</Info>

### `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      |

## Math Actions

Math actions perform on-chain arithmetic operations over values from previous actions. These are useful for computing amounts dynamically within a bundle — for example, dividing a routed amount to distribute across multiple recipients.

All math actions use protocol `math` and take two operands: `amountA` and `amountB`. Each operand can be a static value or a reference to a previous action's output via `useOutputOfCallAt`.

### `add`

Returns `amountA + amountB`.

### `sub`

Returns `amountA - amountB`.

### `mul`

Returns `amountA * amountB`.

### `div`

Returns `amountA / amountB` (integer division).

### `min`

Returns the smaller of `amountA` and `amountB`.

### `max`

Returns the larger of `amountA` and `amountB`.

**Example: Route then divide output by 2 and transfer halves to two addresses**

```typescript theme={null}
const bundle = await client.getBundleData(
  {
    chainId: 1,
    fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
    routingStrategy: "delegate",
    receiver: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
  },
  [
    {
      protocol: "enso",
      action: "route",
      args: {
        tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
        tokenOut: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        amountIn: "1000000000000000000",
        slippage: "300",
      },
    },
    {
      protocol: "math",
      action: "div",
      args: {
        amountA: { useOutputOfCallAt: 0 },
        amountB: "2",
      },
    },
    {
      protocol: "erc20",
      action: "transfer",
      args: {
        token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        amount: { useOutputOfCallAt: 1 },
        receiver: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
      },
    },
    {
      protocol: "erc20",
      action: "transfer",
      args: {
        token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        amount: { useOutputOfCallAt: 1 },
        receiver: "0x93621DCA56fE26Cdee86e4F6B18E116e9758Ff11",
      },
    },
  ],
);
```

| Parameter | Description                                                                          | Required |
| --------- | ------------------------------------------------------------------------------------ | -------- |
| `amountA` | First operand — a static uint256 value or a reference to a previous action's output  | Yes      |
| `amountB` | Second operand — a static uint256 value or a reference to a previous action's output | Yes      |

## Helpers Actions

Helpers actions provide on-chain comparison and conditional logic, enabling bundles to branch based on runtime values. These are useful for building guard conditions, assertions, and conditional flows.

All helpers actions use protocol `helpers`.

### Comparison Actions

Compare two uint256 values and return a boolean result. The result can be referenced by subsequent actions.

#### `isequal`

Returns `true` if `amountA == amountB`.

#### `islessthan`

Returns `true` if `amountA < amountB`.

#### `isequalorlessthan`

Returns `true` if `amountA <= amountB`.

#### `isgreaterthan`

Returns `true` if `amountA > amountB`.

#### `isequalorgreaterthan`

Returns `true` if `amountA >= amountB`.

| Parameter | Description                                                                          | Required |
| --------- | ------------------------------------------------------------------------------------ | -------- |
| `amountA` | First operand — a static uint256 value or a reference to a previous action's output  | Yes      |
| `amountB` | Second operand — a static uint256 value or a reference to a previous action's output | Yes      |

### `check`

Asserts that a boolean condition is `true`. If the condition is `false`, the entire transaction reverts. Use this to enforce invariants — for example, ensuring an output amount meets a minimum threshold.

| Parameter   | Description                                                    | Required |
| ----------- | -------------------------------------------------------------- | -------- |
| `condition` | A boolean value or a reference to a comparison action's output | Yes      |

### `not`

Negates a boolean condition. Returns `true` if the input is `false`, and vice versa.

| Parameter   | Description                                                    | Required |
| ----------- | -------------------------------------------------------------- | -------- |
| `condition` | A boolean value or a reference to a comparison action's output | Yes      |

### `toggle`

Selects between two values based on a condition. Returns `amountA` if the condition is `true`, otherwise returns `amountB`. This is the on-chain equivalent of a ternary expression (`condition ? amountA : amountB`).

| Parameter   | Description                                                    | Required |
| ----------- | -------------------------------------------------------------- | -------- |
| `condition` | A boolean value or a reference to a comparison action's output | Yes      |
| `amountA`   | The value to return if the condition is `true`                 | Yes      |
| `amountB`   | The value to return if the condition is `false`                | Yes      |

**Example: Check that a routed amount is above a minimum before proceeding**

```typescript theme={null}
const bundle = await client.getBundleData(
  {
    chainId: 1,
    fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
    routingStrategy: "delegate",
  },
  [
    {
      protocol: "enso",
      action: "route",
      args: {
        tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
        tokenOut: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        amountIn: "1000000000000000000",
        slippage: "300",
      },
    },
    {
      protocol: "helpers",
      action: "isequalorgreaterthan",
      args: {
        amountA: { useOutputOfCallAt: 0 },
        amountB: "1000000000", // minimum 1000 USDC
      },
    },
    {
      protocol: "helpers",
      action: "check",
      args: {
        condition: { useOutputOfCallAt: 1 },
      },
    },
  ],
);
```

## 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, split, merge, balance, and arbitrary calls
* `math`: On-chain arithmetic operations (`add`, `sub`, `mul`, `div`, `min`, `max`)
* `helpers`: On-chain comparisons and conditional logic (`isequal`, `islessthan`, `isgreaterthan`, `check`, `not`, `toggle`)
* `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).

<div className="text-right text-xs gray-200 font-semibold w-full" style={{marginTop: '0'}}>
  <p style={{
        color: "#b2b2b2"  
    }}>Updated {date_0}</p>
</div>
