Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(morpho-markets): full cycle, and individual flows #123

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions cdp-langchain/examples/morpho-python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# CDP Agentkit Langchain Extension Examples - Morpho Markets Agent

This example demonstrates an agent setup as a terminal style chatbot with access to the full set of CDP Agentkit actions for Morpho Markets interactions.

## Two Available Flow Options:

### 1. Morpho Market Flow (morpho_market_flow.py)
This script provides an automated, sequential flow that:
- Executes all Morpho operations in a predefined order
- Runs through the complete lifecycle of a position
- Ideal for testing or demonstrating the full Morpho lending/borrowing cycle
- No manual operation selection needed
- Operations execute in this fixed sequence:
1. Supply collateral (cbBTC)
2. Borrow (USDC)
3. Repay loan
4. Withdraw collateral

### 2. Specific Action Flow (specific_action_flow.py)
This script offers a more flexible, interactive approach:
- Allows manual selection of individual operations
- Users can choose which operation to execute and when
- Supports multiple execution paths based on user needs
- Available operations:
- Supply Collateral (cbBTC)
- Borrow (USDC)
- Repay
- Withdraw Collateral
- Ideal for testing specific operations or managing positions manually

## Available Morpho Actions
- `morpho_supply_collateral`
- `morpho_borrow`
- `morpho_repay`
- `morpho_withdraw_collateral`

## Requirements
- Python 3.10+
- Poetry for package management and tooling
- [Poetry Installation Instructions](https://python-poetry.org/docs/#installation)
- [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)
- Configured wallet data file

### Wallet Configuration
Before running the scripts, you might want to configure your wallet data in `morpho_base_mainnet_wallet_data.txt`:

Be careful as you expose your seed here, this should be used only for dev purpose.

```txt
{"wallet_id": "XXX", "seed": "XXX", "network_id": "base-mainnet", "default_address_id": "XXX"}
```

> ⚠️ **Important**: Never commit your actual wallet credentials to version control. Make sure to keep your wallet data secure.

### Checking Python Version

```bash
python --version
poetry --version
```

## Installation
```bash
poetry install
```

## Run the Agent

### Env
Ensure the following vars are set in .env-local:
- "OPENAI_API_KEY"

Rename .env-local to .env

### Running the Scripts

For complete market flow:
```bash
poetry run python morpho_market_flow.py
```

For specific action flow:
```bash
poetry run python specific_action_flow.py
```

## Market Parameters
The scripts use predefined market parameters for Morpho operations:

| Parameter | Description | Value |
|-------------------|----------------------|-----------------------------------------------------|
| **Loan Token** | USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
| **Collateral Token** | cbBTC | `0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf` |
| **Oracle** | MorphoChainlinkOracleV2 | `0x663BECd10daE6C4A3Dcd89F1d76c1174199639B9` |
| **IRM** | AdaptiveCurve | `0x46415998764C29aB2a25CbeA6254146D50D22687` |
| **LLTV** | 86% | `860000000000000000` |

The market is visible here, on the [Morpho App](https://app.morpho.org/market?id=0x9103c3b4e834476c9a62ea009ba2c884ee42e94e6e314a26f04d312434191836&network=base)

> ⚠️ **Important**:
A bit of interests might be accrued between the borrow and repay, thus the repay amount is slightly higher than the borrow amount after 1 block.
That can prevent a full withdraw operation.

> ⚠️ Also, be careful with your position. if your loan to value goes above the LLTV, your position will be at rsk and can suffer of liquidation, [more here](https://docs.morpho.org/morpho/concepts/liquidation).

## Important Final Notes
- The agent validates available tools before execution
- Each operation requires user confirmation
- Operations are executed sequentially with success verification
- Detailed error reporting for any failures
- Wallet data is persisted between sessions
133 changes: 133 additions & 0 deletions cdp-langchain/examples/morpho-python/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import os
from langchain_core.messages import HumanMessage
from cdp_langchain.agent_toolkits import CdpToolkit
from cdp_langchain.utils import CdpAgentkitWrapper
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.memory import MemorySaver

# Configure wallet persistence
wallet_data_file = "morpho_wallet_data.txt"


def initialize_agent():
"""Initialize the agent with CDP Agentkit and persistent wallet."""
# Initialize LLM
llm = ChatOpenAI(model="gpt-4o-mini")

# Load existing wallet data if available
wallet_data = None
if os.path.exists(wallet_data_file):
with open(wallet_data_file) as f:
wallet_data = f.read()

# Initialize CDP wrapper with existing wallet if available
values = {}
if wallet_data is not None:
values = {"cdp_wallet_data": wallet_data}

cdp = CdpAgentkitWrapper(**values)

# Persist the wallet data
wallet_data = cdp.export_wallet()
with open(wallet_data_file, "w") as f:
f.write(wallet_data)

# Create toolkit and get tools
toolkit = CdpToolkit.from_cdp_agentkit_wrapper(cdp)
tools = toolkit.get_tools()

# Add debug logging to see available tools
print("Available tools:", [tool.name for tool in tools])

# Add memory for conversation history
memory = MemorySaver()
config = {"configurable": {"thread_id": "CDP Morpho Integration Example"}}

return create_react_agent(
llm,
tools=tools,
checkpointer=memory,
state_modifier="""You are a helpful agent specialized in interacting with Morpho Protocol using CDP Agentkit.
For wrapping ETH to WETH, you must ONLY use the wrap_native action.
The WETH contract already exists at 0x4200000000000000000000000000000000000006 on Base Mainnet.

You can help users deposit and interact with Morpho vaults. If you need funds, you can request them from the faucet since we're on base-Mainnet network.""",
), config


def main():
"""Main execution function"""
agent_executor, config = initialize_agent()

# First, request funds from faucet
faucet_prompt = """
I need to deposit some WETH into Morpho, but first I need some funds.
Please request funds from the faucet since we're on base-mainnet network.
"""

print("Requesting funds from faucet...")
try:
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content=faucet_prompt)]}, config, stream_mode="values"
):
if "messages" in chunk:
chunk["messages"][-1].pretty_print()
else:
print("\nRAW CHUNK:", chunk)
print("-------------------")
except Exception as e:
print(f"Error during faucet request: {e}")

# Add wrapping ETH to WETH step
wrap_prompt = """
SYSTEM: You must use the wrap_native action available in the toolkit to wrap ETH to WETH.

ACTION REQUIRED: wrap_native
Parameters:
- weth_address: "0x4200000000000000000000000000000000000006"
- amount: 0.01 ETH

if we have enough funds, bypass this step.
"""

print("\nWrapping ETH to WETH...")
try:
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content=wrap_prompt)]}, config, stream_mode="values"
):
if "messages" in chunk:
chunk["messages"][-1].pretty_print()
else:
print("\nRAW CHUNK:", chunk)
print("-------------------")
except Exception as e:
print(f"Error during ETH wrapping: {e}")

# Update Morpho deposit interaction to use 0.01 WETH
morpho_prompt = """
Now that we have WETH, please deposit WETH into the Morpho Vault:
- Vault address: 0xb754c2a7FF8493CE1404E5ecFDE562e8f023DEF6
- WETH token address: 0x4200000000000000000000000000000000000006
- Amount: 0.01 WETH
- Use my wallet main address as the receiver address
"""

print("\nExecuting Morpho interaction...")
try:
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content=morpho_prompt)]}, config, stream_mode="values"
):
# Pretty print the messages for better readability
if "messages" in chunk:
chunk["messages"][-1].pretty_print()
else:
print("\nRAW CHUNK:", chunk)
print("-------------------")
except Exception as e:
print(f"Error during execution: {e}")


if __name__ == "__main__":
print("Starting Morpho Integration...")
main()
Loading