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

# simulateBestPositions

Preview the best yield split for an amount before anyone signs anything. Give it an amount, a token, and a chain (or several), and it comes back with the pools it would route into, the blended APY, and ready-to-run transaction calldata for each position.

<Tip title="No wallet required">
  This is a pure simulation: read-only, no signing, no gas. It only needs your API key, so it's a great fit for calculators, previews, and "what would I earn" dashboards. Call it as often as you like as the user tweaks their inputs.
</Tip>

## Signature

```typescript theme={null}
simulateBestPositions(params: SimulateBestPositionsParams): Promise<SimulateBestPositionsResponse>
```

## Parameters

`params` is a single object:

| Field | Type | Required | Description |
| - | - | :-: | - |
| `amount` | `number` | ✅ | Amount to deploy, in human units (e.g. `3000` for 3,000 USDC), not wei. |
| `token` | `string` | ✅ | `"USDC"`, `"WETH"`, `"EURC"`, `"USDT"`, `"PYUSD"`, or `"NVDAc"`. See [Supported Assets](/docs/sdk/supported-assets). |
| `networks` | `number \| number[]` | ✅ | A chain ID, or an array of them, e.g. `8453` or `[8453, 42161]`. |
| `strategy` | `Strategy` | ✅ | `"conservative"`, `"aggressive"`, or `"yieldmaxxing"`. See [Supported Assets](/docs/sdk/supported-assets). |
| `minSplit` | `number` | ❌ | Minimum number of pools to spread the amount across. |
| `protocols` | `string[]` | ❌ | Restrict candidates to these protocols, e.g. `["aave", "morpho"]`. |
| `pools` | `string[]` | ❌ | Restrict candidates to these exact pool names. |
| `userPositions` | `UserPosition[]` | ❌ | Positions the user already holds, so the simulation can account for them (see below). |

```typescript theme={null}
interface UserPosition {
  protocol: string;
  pool: string;
  tvl: number; // the user's position size in this pool, not the pool's total TVL
}
```

## Returns

Chain-keyed simulated positions, plus calldata to actually enter each one.

## Return Type

```typescript theme={null}
interface SimulateBestPositionsResponse {
  success: boolean;
  data: Record<string, SimulatedPosition[]>; // keyed by chain ID
  messages: Record<string, string>;          // per-chain notes, e.g. why a chain came back empty
}

interface SimulatedPosition {
  protocol: string;
  pool: string;
  simulated_apy: number;             // base APY, no rewards
  combined_apy: number;              // Headline APY including rewards. Use this one.
  amount: number;                    // how much goes into this pool, human units
  amount_raw: string;                // the same amount, in the token's raw decimal units
  tvl: number;                       // pool's total TVL
  liquidity: number;                 // pool's available liquidity
  averageCombinedApy30Days: number;  // 30-day average, useful to confirm the APY isn't a spike
  url: string;                       // link to the pool
  calldata: SimulateCalldataItem[];
}

interface SimulateCalldataItem {
  contract_address: string;
  function_name: string;   // e.g. "approve", "deposit"
  parameters: string[];
  value: string;           // ETH value, usually "0"
  description: string;     // human-readable, e.g. "Approve 3000 USDC for Morpho"
}
```

<Warning title="Replace the receiver before sending">
  The `deposit` calldata contains a `"<RECEIVER>"` placeholder among its `parameters`. Swap it for the real receiving address (usually the user's Safe / smart wallet) before you send the transaction.
</Warning>

## Good to know

A few behaviors worth knowing before you build against this, confirmed by calling the live API directly:

* **`userPositions` is additive, not just contextual.** If the user already has $1,500 in a pool and you simulate depositing $3,000 more, the returned position is sized for the **combined** $4,500, not $3,000. Pass it in whenever you know where the user already is.
* **`minSplit` divides the amount evenly** across that many pools. `minSplit: 3` on $5,000 returns three ~$1,666.67 positions, each with its own `calldata`.
* **A chain can come back empty on purpose.** If every candidate pool for a chain gets excluded (unstable APY, doesn't clear the strategy's risk bar, etc.), that chain's entry in `data` is `[]` and `messages[chainId]` explains why.
* **An unmatched `pools` filter isn't a dead end.** The call still returns `success: true` with an empty array for that chain, and `messages[chainId]` lists the pools that actually exist for that token/chain/strategy. This is handy for a "did you mean…" experience.
* Works for any supported chain/token combination, with no special-casing needed for less common pairs.

## Examples

### Simplest call

```typescript theme={null}
const result = await sdk.simulateBestPositions({
  amount: 3000,
  token: "USDC",
  networks: 8453,
  strategy: "conservative",
});

console.log(result.data["8453"]);
// [{ protocol: "Morpho", pool: "Gauntlet USDC Prime", combined_apy: 4.15, ... }]
```

### Multiple chains, with a minimum split

```typescript theme={null}
const result = await sdk.simulateBestPositions({
  amount: 5000,
  token: "USDC",
  networks: [8453, 42161],
  strategy: "conservative",
  minSplit: 3,
});

const positions = Object.values(result.data).flat();
console.log(positions.map((p) => `${p.protocol}/${p.pool}: $${p.amount}`));
```

### Accounting for an existing position

```typescript theme={null}
await sdk.simulateBestPositions({
  amount: 3000,
  token: "USDC",
  networks: 8453,
  strategy: "conservative",
  userPositions: [
    { protocol: "aave", pool: "USDC", tvl: 1500 }, // the user's current position size
  ],
});
// Simulated against a $4,500 total, not $3,000.
```

### Blended APY across a split

```typescript theme={null}
const positions = Object.values(result.data).flat();
const total = positions.reduce((sum, p) => sum + p.amount, 0);
const blendedApy =
  positions.reduce((sum, p) => sum + p.amount * p.combined_apy, 0) / total;
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.