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

# Portfolio Rebalancer

> Rebalance user portfolios across DeFi venues in a single atomic transaction. Withdraw, swap, and deposit in one signature.

## Why This Matters

Users accumulate positions across multiple DeFi protocols over time. When rates change, they need to move funds - but doing it manually means multiple transactions, multiple signatures, and wasted gas. Most users never bother.

The Portfolio Rebalancer lets you build products that shift allocations across Aave, Morpho vaults, and Pendle markets in one atomic transaction. Users set their target allocation, sign once, and the API handles the rest.

## What It Does

Given a user's current positions and a set of target allocations, the rebalancer computes the optimal set of withdrawals, swaps, and deposits to reach the target state. All actions are bundled into one transaction using the [Bundle endpoint](/v2/Products/Bundling).

You call our API, we return a transaction payload. The user signs once, and their portfolio rebalances atomically.

**Important:** Users must first create an [Earn Account](/v2/Products/Accounts) before rebalancing.

## How It Works

1. **Fetch current positions** - Call the positions endpoint to see where the user's funds are deployed
2. **Compute the plan** - Determine what needs to move: withdrawals from over-allocated venues, swaps between tokens, deposits into under-allocated venues
3. **Bundle the actions** - Send the actions to [`POST /v2/earn/bundle`](/v2/api-reference/earn/execute-multiple-earn-actions) in order
4. **User signs once** - The API returns a single transaction (or EIP-712 data for gas sponsorship)
5. **Execution** - All actions execute atomically on-chain

### Action Order

The bundle executes actions in the order you provide. For a rebalance, the typical order is:

1. **Withdraw** from venues that are over-allocated
2. **Swap** tokens if the target venue uses a different asset
3. **Deposit** into venues that are under-allocated

***

## Example: Rebalance from Aave to a Morpho Vault

A user has 100 USDC in Aave earning 4.8% APY. They want to move half to a Morpho vault earning 6.2% APY. This requires three bundled actions: withdraw 50 USDC from Aave, then deposit 50 USDC into the vault.

<CodeGroup>
  ```typescript TypeScript theme={"system"}
  import { CompassAPI } from "@compass-labs/api-sdk";

  const compass = new CompassAPI({ apiKey: "YOUR_API_KEY" });

  const owner = "0xYourWalletAddress";
  const chain = "ethereum";

  // Step 1: Check current positions
  const positions = await compass.v2.earn.getPositions({ owner, chain });
  console.log("Current positions:", positions);

  // Step 2: Bundle withdraw + deposit to rebalance
  const bundle = await compass.v2.earn.bundle({
    owner,
    chain,
    gasSponsorship: true,
    actions: [
      // Withdraw 50 USDC from Aave
      {
        actionType: "V2_MANAGE",
        action: "WITHDRAW",
        amount: 50,
        venue: { type: "AAVE", token: "USDC" },
      },
      // Deposit 50 USDC into Morpho vault
      {
        actionType: "V2_MANAGE",
        action: "DEPOSIT",
        amount: 50,
        venue: {
          type: "VAULT",
          vaultAddress: "0xBEEF01735c132Ada46AA9aA9B6290ac27d14070e",
        },
      },
    ],
  });

  // Step 3: Sign the EIP-712 typed data with user's wallet
  const signature = await wallet.signTypedData(bundle.eip712);

  // Step 4: Submit the signed transaction for execution
  const result = await compass.v2.gasSponsoredTransaction.prepare({
    owner,
    chain,
    eip712: bundle.eip712,
    signature,
  });
  console.log("Rebalance tx hash:", result.txHash);
  ```

  ```python Python theme={"system"}
  from compass_api_sdk import CompassAPI

  compass = CompassAPI(api_key="YOUR_API_KEY")

  owner = "0xYourWalletAddress"
  chain = "ethereum"

  # Step 1: Check current positions
  positions = compass.v2.earn.get_positions(owner=owner, chain=chain)
  print("Current positions:", positions)

  # Step 2: Bundle withdraw + deposit to rebalance
  bundle = compass.v2.earn.bundle(
      owner=owner,
      chain=chain,
      gas_sponsorship=True,
      actions=[
          # Withdraw 50 USDC from Aave
          {
              "action_type": "V2_MANAGE",
              "action": "WITHDRAW",
              "amount": 50,
              "venue": {"type": "AAVE", "token": "USDC"},
          },
          # Deposit 50 USDC into Morpho vault
          {
              "action_type": "V2_MANAGE",
              "action": "DEPOSIT",
              "amount": 50,
              "venue": {
                  "type": "VAULT",
                  "vault_address": "0xBEEF01735c132Ada46AA9aA9B6290ac27d14070e",
              },
          },
      ],
  )

  # Step 3: Sign the EIP-712 typed data with user's wallet
  signature = wallet.sign_typed_data(bundle.eip712)

  # Step 4: Submit the signed transaction for execution
  result = compass.v2.gas_sponsored_transaction.prepare(
      owner=owner,
      chain=chain,
      eip712=bundle.eip712,
      signature=signature,
  )
  print("Rebalance tx hash:", result.tx_hash)
  ```
</CodeGroup>

## Example: Cross-Token Rebalance with Swap

A user has 200 USDC in an Aave market but wants to move 100 into a WETH vault. This requires a withdraw, swap, and deposit - all in one bundle.

<CodeGroup>
  ```typescript TypeScript theme={"system"}
  const bundle = await compass.v2.earn.bundle({
    owner,
    chain: "ethereum",
    gasSponsorship: true,
    actions: [
      // 1. Withdraw 100 USDC from Aave
      {
        actionType: "V2_MANAGE",
        action: "WITHDRAW",
        amount: 100,
        venue: { type: "AAVE", token: "USDC" },
      },
      // 2. Swap 100 USDC to WETH
      {
        actionType: "V2_SWAP",
        tokenIn: "USDC",
        tokenOut: "WETH",
        amountIn: 100,
        slippage: 0.5,
      },
      // 3. Deposit WETH into a vault
      {
        actionType: "V2_MANAGE",
        action: "DEPOSIT",
        amount: 0.03, // ~100 USDC worth of WETH
        venue: {
          type: "VAULT",
          vaultAddress: "0xYourWETHVaultAddress",
        },
      },
    ],
  });
  ```

  ```python Python theme={"system"}
  bundle = compass.v2.earn.bundle(
      owner=owner,
      chain="ethereum",
      gas_sponsorship=True,
      actions=[
          # 1. Withdraw 100 USDC from Aave
          {
              "action_type": "V2_MANAGE",
              "action": "WITHDRAW",
              "amount": 100,
              "venue": {"type": "AAVE", "token": "USDC"},
          },
          # 2. Swap 100 USDC to WETH
          {
              "action_type": "V2_SWAP",
              "token_in": "USDC",
              "token_out": "WETH",
              "amount_in": 100,
              "slippage": 0.5,
          },
          # 3. Deposit WETH into a vault
          {
              "action_type": "V2_MANAGE",
              "action": "DEPOSIT",
              "amount": 0.03,  # ~100 USDC worth of WETH
              "venue": {
                  "type": "VAULT",
                  "vault_address": "0xYourWETHVaultAddress",
              },
          },
      ],
  )
  ```
</CodeGroup>

## Portfolio Manager Widget

If you want a ready-made UI for rebalancing, use the **Portfolio Manager widget**. It handles position display, target allocation editing, preview, and execution out of the box.

<CardGroup cols={2}>
  <Card title="Try the Portfolio Manager" icon="sliders" href="https://studio.compasslabs.ai/portfolio_manager">
    Try the live widget in the Widget Builder Studio.
  </Card>

  <Card title="Widget Docs" icon="puzzle-piece" href="/v2/Products/Widgets">
    See installation and customization options.
  </Card>
</CardGroup>

```tsx theme={"system"}
import { RebalancingWidget } from "@compass-labs/widgets";

<RebalancingWidget
  title="Portfolio Manager"
  chain="ethereum"
  showChainSwitcher={true}
  showWalletStatus={true}
  onRebalance={(plan, txHash) => console.log("Rebalanced:", txHash)}
  onError={(err) => console.error("Error:", err)}
/>
```

| Prop                       | Type     | Default             | Description                                               |
| -------------------------- | -------- | ------------------- | --------------------------------------------------------- |
| `title`                    | string   | 'Portfolio Manager' | Title shown in the header                                 |
| `chain`                    | string   | undefined           | Lock to a specific chain. Hides chain selector when set.  |
| `showChainSwitcher`        | boolean  | true                | Show the chain selector dropdown                          |
| `showWalletStatus`         | boolean  | true                | Show the wallet connection status                         |
| `showTopUp`                | boolean  | true                | Show the Top Up button to transfer from wallet            |
| `defaultSlippage`          | number   | 0.5                 | Default slippage tolerance for swaps (%)                  |
| `minRebalanceThresholdUsd` | number   | 0.01                | Minimum USD value to include in rebalance                 |
| `venues`                   | object   | undefined           | Filter which venues are shown (aave, vaults, pendle)      |
| `height`                   | string   | '600px'             | Widget height                                             |
| `onRebalance`              | function | undefined           | Callback after successful rebalance with plan and tx hash |
| `onError`                  | function | undefined           | Callback on error                                         |

## Supported Venues

| Protocol              | Venue Type  | Description                                |
| --------------------- | ----------- | ------------------------------------------ |
| **Aave V3**           | `AAVE`      | Lending markets with variable supply rates |
| **Morpho / ERC-4626** | `VAULT`     | Curated vaults with optimized yield        |
| **Pendle**            | `PENDLE_PT` | Fixed-rate yield via principal tokens      |

## Use Cases

**Yield Optimization:** Monitor rates across protocols and automatically rebalance to maximize returns. When Morpho offers 6.2% but Aave drops to 4.8%, move funds in one transaction.

*Example: \$50,000 in Aave earning 4.8% (\$2,400/year). Rebalance to Morpho at 6.2% (\$3,100/year). Net gain: \$700/year in additional yield.*

**Risk Diversification:** Spread user funds across multiple protocols to reduce smart contract risk. Set target allocations like 40% Aave, 40% Morpho, 20% Pendle and rebalance when drift exceeds a threshold.

**Treasury Management:** Let businesses rebalance idle capital across venues based on changing rate environments. Build dashboards that show current vs. target allocation and offer one-click rebalancing.

## Next Steps

<CardGroup cols={3}>
  <Card title="Transaction Bundling" icon="layer-group" href="/v2/Products/Bundling">
    Learn how bundling works under the hood.
  </Card>

  <Card title="Earn" icon="chart-line" href="/v2/Products/Earn">
    Explore the vaults and Aave markets available for rebalancing.
  </Card>

  <Card title="Gas Sponsorship" icon="gas-pump" href="/v2/Products/gas-sponsorship">
    Sponsor gas so users rebalance without needing ETH.
  </Card>
</CardGroup>
