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

# Advanced Balance

> Check balances of external accounts and build routes against estimated amounts using the Bundle API.

export const date_0 = "2026-03-23"

The `balance` action supports advanced parameters for pulling tokens from external accounts and building routes against estimated token amounts. These parameters extend the [basic balance action](/pages/build/reference/actions#balance), which simply returns the on-chain balance of the caller's wallet.

<Warning>
  This is an advanced feature intended for integrators who need to pull tokens
  from external accounts or pre-build routes before balances are available.
  Using `account` and `estimate` incorrectly can lead to **loss of funds**. Read
  the [risk considerations](#risk-considerations) below before integrating.
</Warning>

## How It Works

```mermaid theme={null}
sequenceDiagram
    participant User
    participant Enso API
    participant RPC Node
    participant Wallet

    User->>Enso API: POST /bundle with balance action (account)
    alt Without estimate
        Enso API->>RPC Node: Check token balance of account
        RPC Node-->>Enso API: Balance value
        Enso API->>Enso API: Build route with the balance
    else With estimate
        Enso API->>Enso API: Build route with the estimate
    end
    Enso API-->>User: Transaction data
    User->>Wallet: Submit bundle transaction
```

1. You submit a `/bundle` request with a `balance` action that includes `account` (and optionally `estimate`)
2. The API performs an off-chain RPC call to check the account's token balance
3. If no `estimate` is provided and the balance is zero, the request returns an error
4. For **router** strategy: the token and amount are added to `tokensIn`/`amountsIn`
5. For **delegate** / **ensowallet** strategies: a `transferFrom` call is automatically inserted to pull tokens from the external account into the wallet
6. The API generates approval transactions that the `account` must sign for the spender contract before the bundle can execute

## Parameters

| Parameter  | Type         | Description                                                                                               | Required |
| ---------- | ------------ | --------------------------------------------------------------------------------------------------------- | -------- |
| `token`    | `AddressArg` | Address of the token to check balance                                                                     | Yes      |
| `estimate` | `NumberArg`  | Estimated balance amount in wei. Allows route building without an existing balance on the account.        | No       |
| `account`  | `AddressArg` | Address of an external account to check balance of. Defaults to the caller's wallet address when omitted. | No       |

<Note>
  When only `token` is provided (no `account` or `estimate`), the action behaves
  exactly as the basic balance check — returning the on-chain balance of the
  caller's wallet. See the [basic
  usage](/pages/build/reference/actions#balance).
</Note>

## Behavior by Routing Strategy

The advanced balance action behaves differently depending on the routing strategy and whether `estimate` is provided:

### Router

* **With `account` only (no `estimate`):** The `account` must approve the **router contract**.
* **With `account` and `estimate`:** The `account` must approve the **EnsoShortcuts contract**. The required approval transaction is returned in the bundle response.

<Warning>
  **Dangerous: EnsoShortcuts contract approval.** When using `estimate` with the
  `router` strategy, the `account` must approve the EnsoShortcuts contract. If
  approval is not reset back to 0, anyone will be able to pull funds from the
  wallet. **You should revoke this approval within the same transaction** to
  minimize the window of exposure. Leaving the approval active after the
  transaction is a security risk.
</Warning>

### Delegate / EnsoWallet

| Strategy        | Behavior when `account` is provided                                                                                                          |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `delegate`      | Automatically inserts a `transferFrom` call to pull tokens from the account into the wallet. The account must approve the delegate contract. |
| `ensowallet-v2` | Same as `delegate` — inserts a `transferFrom` call. The account must approve the EnsoWallet contract.                                        |

<Tip>
  See [Routing Strategies](/pages/build/reference/routing-strategies) for
  details on choosing a strategy.
</Tip>

## Balance Estimates

When `estimate` is provided alongside `account`, routes are built using the estimated amount rather than requiring the full on-chain balance:

* The API uses the estimate for quoting and route optimization, enabling you to build transactions before the account has the full balance available

<Warning>
  Routes built with `estimate` are only as accurate as the estimate itself. If
  the actual balance at execution time differs significantly from the estimate,
  the transaction may fail or produce suboptimal results.
</Warning>

## Risk Considerations

* **EnsoShortcuts contract approval** - When using `estimate` with the `router` strategy, the `account` must approve the EnsoShortcuts contract, which is the main execution contract where tokens will get pulled into. **Always revoke this approval in the same transaction.** The required approval is returned in the bundle response - pair it with a revoke action to avoid leaving a persistent approval.
* **Estimate as max amount** - The `estimate` value should be treated as the **maximum amount** that will be pulled from the account. Swap aggregators used during routing may capture positive slippage, meaning the actual amount consumed can be up to the full estimate even if a smaller amount would have sufficed for the desired output. Set the estimate carefully to limit exposure.
* **Estimate accuracy** - Using `estimate` means routes are optimized against projected amounts. Significant divergence between the estimate and the actual balance at execution time can cause transaction failure or poor execution prices.
* **External account security** - This feature pulls tokens from an external account via `transferFrom`. Always verify the `account` address and its approval status before executing.

## Examples

### Balance with Account and Route

This example checks the USDC balance of an external account with an estimate, then routes the USDC to USDT.

<CodeGroup>
  ```typescript TypeScript SDK theme={null}
  const bundle = await client.getBundleData(
    {
      chainId: 1,
      fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
      routingStrategy: "router",
    },
    [
      {
        protocol: "enso",
        action: "balance",
        args: {
          token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
          account: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
          estimate: "1000000000", // 1000 USDC
        },
      },
      {
        protocol: "enso",
        action: "route",
        args: {
          tokenIn: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
          tokenOut: "0xdAC17F958D2ee523a2206206994597C13D831ec7", // USDT
          amountIn: { useOutputOfCallAt: 0 },
          slippage: "300",
        },
      },
    ],
  );
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.enso.build/api/v1/shortcuts/bundle" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{
      "chainId": 1,
      "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
      "routingStrategy": "router",
      "bundle": [
        {
          "protocol": "enso",
          "action": "balance",
          "args": {
            "token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
            "account": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
            "estimate": "1000000000"
          }
        },
        {
          "protocol": "enso",
          "action": "route",
          "args": {
            "tokenIn": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
            "tokenOut": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
            "amountIn": { "useOutputOfCallAt": 0 },
            "slippage": "300"
          }
        }
      ]
    }'
  ```
</CodeGroup>

**What's happening step by step:**

1. **Balance** — Check the USDC balance of the external account, using `1000 USDC` as the estimate for route building
2. **Route** — Route the USDC to USDT using `useOutputOfCallAt: 0` to reference the balance from step 1

### Balance with Account, TransferFrom, and Route

This example checks the balance, explicitly transfers tokens from the external account, then routes.

<CodeGroup>
  ```typescript TypeScript SDK theme={null}
  const bundle = await client.getBundleData(
    {
      chainId: 1,
      fromAddress: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
      routingStrategy: "router",
    },
    [
      {
        protocol: "enso",
        action: "balance",
        args: {
          token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
          account: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
          estimate: "1000000000", // 1000 USDC
        },
      },
      {
        protocol: "erc20",
        action: "transferfrom",
        args: {
          token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
          sender: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
          receiver: "0x4Fe93ebC4Ce6Ae4f81601cC7Ce7139023919E003", // EnsoShortcuts
          amount: { useOutputOfCallAt: 0 },
        },
      },
      {
        protocol: "enso",
        action: "route",
        args: {
          tokenIn: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
          tokenOut: "0xdAC17F958D2ee523a2206206994597C13D831ec7", // USDT
          amountIn: { useOutputOfCallAt: 0 },
          slippage: "300",
        },
      },
    ],
  );
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.enso.build/api/v1/shortcuts/bundle" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{
      "chainId": 1,
      "fromAddress": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
      "routingStrategy": "router",
      "bundle": [
        {
          "protocol": "enso",
          "action": "balance",
          "args": {
            "token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
            "account": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
            "estimate": "1000000000"
          }
        },
        {
          "protocol": "erc20",
          "action": "transferfrom",
          "args": {
            "token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
            "sender": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
            "receiver": "0x4Fe93ebC4Ce6Ae4f81601cC7Ce7139023919E003",
            "amount": { "useOutputOfCallAt": 0 }
          }
        },
        {
          "protocol": "enso",
          "action": "route",
          "args": {
            "tokenIn": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
            "tokenOut": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
            "amountIn": { "useOutputOfCallAt": 0 },
            "slippage": "300"
          }
        }
      ]
    }'
  ```
</CodeGroup>

**What's happening step by step:**

1. **Balance** — Check the USDC balance of the external account with a `1000 USDC` estimate
2. **TransferFrom** — Explicitly transfer USDC from the external account to the router, using `useOutputOfCallAt: 0` to reference the balance
3. **Route** — Route the USDC to USDT

<Tip>
  When the balance action detects a following `transferFrom` for the same token
  and account, it optimizes the flow automatically. Use `useOutputOfCallAt` to
  dynamically chain action outputs. See [Chaining
  Actions](/pages/build/reference/actions#chaining-actions) for details.
</Tip>

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