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.
routeCustomCallEOA.ts
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));

Updated