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

# Custom Contract Calls 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.

<Tabs>
  <Tab title="EOA signing">
    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));

    ```
  </Tab>

  <Tab title="Smart wallet signing">
    ### 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));

    ```
  </Tab>
</Tabs>

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