> For the complete documentation index, see [llms.txt](https://docs.ipor.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ipor.io/build-on-fusion/alpha/sdk.md).

# SDK

Install, connect and execute with the Python SDK; the CLI, MCP server, agent skills, examples and module reference.

The official Python SDK for IPOR Fusion (`pip install ipor-fusion`; [PyPI](https://pypi.org/project/ipor-fusion/), [source](https://github.com/IPOR-Labs/ipor-fusion.py)). Use it to create vaults, construct contract calls, encode calldata and submit transactions through a configured signer — the only one of Fusion's public interfaces that can write, not just read (see MCP and the API for read-only surfaces).

For the full first-vault walkthrough, see Deploy your first Fusion vault. For revert selectors and the role table, see Common errors.

### Install

```bash
pip install ipor-fusion
```

### Connect and execute

```python
from ipor_fusion import Web3Context, PlasmaVault, AaveV3SupplyFuse
from web3 import Web3

# 1. Create a Web3 context with your provider and private key
ctx = Web3Context.from_url(
    url="https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY",
    private_key="0x...",
)

# 2. Wrap the PlasmaVault contract
vault = PlasmaVault(ctx, Web3.to_checksum_address("0xVAULT_ADDRESS"))

# 3. Build a fuse action (e.g. supply USDC to Aave V3)
fuse = AaveV3SupplyFuse(Web3.to_checksum_address("0xFUSE_ADDRESS"))
action = fuse.supply(
    asset=Web3.to_checksum_address("0xUSDC_ADDRESS"),
    amount=1_000_000,  # 1 USDC (6 decimals)
)

# 4. Execute on-chain (execute() returns a Call; .send() signs and submits it)
receipt = vault.execute([action]).send()
```

Fuse, factory and manager addresses per chain are published in [`ipor-abi`](https://github.com/IPOR-Labs/ipor-abi) (`mainnet/mainnet-<chain>-fusion/addresses.json`) — see also Addresses. A fuse must also be registered on the vault; `vault.get_fuses().call()` lists the registered ones. Amounts are raw on-chain integers (`Amount`, `Shares` in `ipor_fusion.types`); the SDK never scales by decimals.

### Read, send, or simulate

Every wrapper method returns a `Call` instead of executing immediately. The same `Call` powers all three modes — this is the SDK's read-only-vs-transaction-sending surface:

```python
from ipor_fusion import VaultSimulator

total = vault.total_assets().call()          # eth_call -> Amount, no key needed
receipt = vault.execute([action]).send()     # signed tx -> TxReceipt, needs a private key
payload = vault.execute([action]).calldata   # raw bytes for an external signer

# Simulate first via eth_simulateV1 (no local node); alpha is the account allowed to call execute()
sim = VaultSimulator(ctx.web3, vault=vault.address, alpha=Web3.to_checksum_address("0xALPHA"))
sim.observe("before", vault.total_assets())
sim.execute([action])
sim.observe("after", vault.total_assets())
result = sim.run()
if result.all_success:
    print(result.get("after") - result.get("before"))
```

`.send()` signs locally and requires a private key in the `Web3Context`; `.call()` and `.calldata` need none — sending through a keyless context raises `ValueError`.

### CLI: `fusion`

The SDK ships a `fusion` CLI for **inspecting** Plasma Vaults from the terminal — it does not deploy, configure or execute; that's the SDK's job above.

```bash
# Install with CLI extras (pipx keeps dependencies isolated)
pipx install 'ipor-fusion[cli]'

# Configure an RPC provider (auto-detects chain ID)
fusion config set-provider https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY

# Inspect a vault (auto-saves to config on first use)
fusion vault info 0xB8a451107A9f87FDe481D4D686247D6e43Ed715e --chain-id ethereum

# List saved vaults
fusion vault list

# Inspect a Morpho Blue market or MetaMorpho vault
fusion market morpho-blue 0xMARKET_ID --chain ethereum
fusion market meta-morpho 0xVAULT_ADDRESS --chain ethereum
```

### MCP: `fusion-mcp`

Two ways to reach Fusion from an MCP-compatible client — see MCP for the hosted server's full tool/resource/prompt reference.

* **Hosted, no install:** `https://mcp.ipor.io/mcp` — public, unauthenticated, read-only.
* **Local, from the SDK:** `pipx install 'ipor-fusion[mcp]'` ships a `fusion-mcp` server that exposes the same CLI over MCP, against your own RPC providers and local config, plus the resources `fusion://glossary`, `fusion://architecture`, `fusion://invariants` and `fusion://quickstart`, and the prompts `quickstart`, `deploy_vault`, `analyze_vault`, `trace_oracle_pricing` and `explain_fuse`.

```json
{
  "mcpServers": {
    "ipor-fusion": { "command": "fusion-mcp", "type": "stdio" }
  }
}
```

### Agent skills

[`skills/ipor-deploy-vault/SKILL.md`](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/skills/ipor-deploy-vault/SKILL.md) teaches a coding agent the full clone -> roles -> market -> access posture -> deposit -> execute walk, with the invariants and the revert selectors, before it writes vault code — the same text as `fusion://invariants` / `fusion://quickstart` and Common errors, one text with several delivery paths. One install per machine:

```bash
# Claude Code -- plugin with the skill and the hosted MCP server
/plugin marketplace add IPOR-Labs/ipor-fusion.py
/plugin install ipor-fusion@ipor-fusion

# Codex CLI, Gemini CLI, Cursor -- the skill; add the MCP server as shown above
npx skills add IPOR-Labs/ipor-fusion.py -g -a codex      # or gemini-cli, cursor
```

### Vault construction examples

Runnable, canonical examples for building and configuring a vault from scratch live in [`examples/`](https://github.com/IPOR-Labs/ipor-fusion.py/tree/main/examples). They preview and simulate through `eth_simulateV1` — nothing is ever signed or broadcast.

* [Simple Aave V3 supply vault](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/simple_aave_v3_supply_base.py) — start here for vault creation, role bootstrap, and configuring a single supported market.
* [Advanced Euler V2 credit-market vault](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/advanced_euler_v2_credit_market_base.py) — continue here for composing multiple functional fuses, typed Euler substrates and sub-accounts, and an ordered collateral -> borrow -> repay -> unwind lifecycle.

For a strategy bot that operates an existing vault end to end, see [`ipor-fusion-alpha-example`](https://github.com/IPOR-Labs/ipor-fusion-alpha-example).

### Architecture

The SDK uses a **fuse adapter pattern**: Fuses encode protocol-specific calls into `FuseAction` objects (pure calldata, no state); `PlasmaVault` batches and executes `FuseAction` sequences on-chain via `execute()` (atomically); `Web3Context` manages provider connections, signing and transaction dispatch; `Call` is the lazy result of every wrapper method.

```
Fuse.method()  -->  FuseAction  -->  PlasmaVault.execute([actions])  -->  Call  -->  .send() / simulate
```

#### Core modules (`ipor_fusion.core`)

| Module                                                   | Purpose                                                                              |
| -------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `Web3Context`                                            | Provider connection, signing, tx dispatch, gas estimation                            |
| `Call`                                                   | Pre-encoded contract call; `.call()`, `.send()`, `.calldata`, `.build_transaction()` |
| `PlasmaVault`                                            | ERC-4626 vault — execute, deposit, withdraw, fuse and market configuration           |
| `VaultSimulator`                                         | Batch `execute` + reads through `eth_simulateV1`, multi-block, no local node         |
| `FusionFactory`                                          | Deploy a new vault (`clone`, `clone_supervised`)                                     |
| `AccessManager`                                          | Role-based access control                                                            |
| `RewardsManager`                                         | Claim and vest rewards                                                               |
| `WithdrawManager`                                        | Time-windowed withdrawal requests                                                    |
| `FeeManager`                                             | Deposit, performance, and management fee configuration                               |
| `PriceOracleMiddleware` / `PriceOracleMiddlewareManager` | Asset price feeds and per-vault overrides                                            |
| `ERC20`                                                  | Token reads and approvals                                                            |

#### Supported protocols (`ipor_fusion.fuses`)

Aave V3, Morpho, Euler V2, Uniswap V3, Ramses V2, Compound V3, Gearbox V3, ERC-4626, Fluid Instadapp, Merkl, plus a Universal Token Swapper fuse. Full class list in the [README](https://github.com/IPOR-Labs/ipor-fusion.py#supported-protocols-ipor_fusionfuses).

#### Supported networks

Ethereum mainnet, Arbitrum One, Base.

### Development and contributing

Contributor and coding-agent instructions (commands, conventions, invariants, domain rules) live in [`AGENTS.md`](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/AGENTS.md) in the repository.
