From b78ce9612bf32c7bd69a9c7306ad7c4278ed4ade Mon Sep 17 00:00:00 2001 From: John Peterson Date: Tue, 14 Jan 2025 18:07:08 -0500 Subject: [PATCH] feat(PSDK-854): Morpho Vault Deposit/Withdraw Actions --- cdp-agentkit-core/CHANGELOG.md | 5 + .../cdp_agentkit_core/actions/__init__.py | 4 + .../actions/morpho/__init__.py | 0 .../actions/morpho/constants.py | 102 +++++++++++ .../actions/morpho/deposit.py | 88 +++++++++ .../cdp_agentkit_core/actions/morpho/utils.py | 35 ++++ .../actions/morpho/withdraw.py | 67 +++++++ .../tests/actions/morpho/test_deposit.py | 167 ++++++++++++++++++ .../tests/actions/morpho/test_withdraw.py | 92 ++++++++++ .../tests/factories/asset_factory.py | 17 ++ .../examples/chatbot/morpho_wallet_data.txt | 1 + 11 files changed, 578 insertions(+) create mode 100644 cdp-agentkit-core/cdp_agentkit_core/actions/morpho/__init__.py create mode 100644 cdp-agentkit-core/cdp_agentkit_core/actions/morpho/constants.py create mode 100644 cdp-agentkit-core/cdp_agentkit_core/actions/morpho/deposit.py create mode 100644 cdp-agentkit-core/cdp_agentkit_core/actions/morpho/utils.py create mode 100644 cdp-agentkit-core/cdp_agentkit_core/actions/morpho/withdraw.py create mode 100644 cdp-agentkit-core/tests/actions/morpho/test_deposit.py create mode 100644 cdp-agentkit-core/tests/actions/morpho/test_withdraw.py create mode 100644 cdp-agentkit-core/tests/factories/asset_factory.py create mode 100644 cdp-langchain/examples/chatbot/morpho_wallet_data.txt diff --git a/cdp-agentkit-core/CHANGELOG.md b/cdp-agentkit-core/CHANGELOG.md index fdbca675..7e1faf53 100644 --- a/cdp-agentkit-core/CHANGELOG.md +++ b/cdp-agentkit-core/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Added + +- Added `morpho_deposit` action to deposit to Morpho Vault. +- Added `morpho_withdrawal` action to withdraw from Morpho Vault. + ## [0.0.8] - 2025-01-13 ### Added diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/__init__.py b/cdp-agentkit-core/cdp_agentkit_core/actions/__init__.py index b07f1d84..83a6772f 100644 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/__init__.py +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/__init__.py @@ -4,6 +4,8 @@ from cdp_agentkit_core.actions.get_balance import GetBalanceAction from cdp_agentkit_core.actions.get_wallet_details import GetWalletDetailsAction from cdp_agentkit_core.actions.mint_nft import MintNftAction +from cdp_agentkit_core.actions.morpho.deposit import MorphoDepositAction +from cdp_agentkit_core.actions.morpho.withdraw import MorphoWithdrawAction from cdp_agentkit_core.actions.register_basename import RegisterBasenameAction from cdp_agentkit_core.actions.request_faucet_funds import RequestFaucetFundsAction from cdp_agentkit_core.actions.trade import TradeAction @@ -42,4 +44,6 @@ def get_all_cdp_actions() -> list[type[CdpAction]]: "WowCreateTokenAction", "WowSellTokenAction", "WrapEthAction", + "MorphoDepositAction", + "MorphoWithdrawAction", ] diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/__init__.py b/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/constants.py b/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/constants.py new file mode 100644 index 00000000..76f9ce02 --- /dev/null +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/constants.py @@ -0,0 +1,102 @@ +MORPHO_BASE_ADDRESS = "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb" + +ERC20_ABI = [ + { + "constant": False, + "inputs": [ + {"internalType": "address", "name": "spender", "type": "address"}, + {"internalType": "uint256", "name": "value", "type": "uint256"}, + ], + "name": "approve", + "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], + "payable": False, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "constant": True, + "inputs": [ + {"internalType": "address", "name": "owner", "type": "address"}, + {"internalType": "address", "name": "spender", "type": "address"}, + ], + "name": "allowance", + "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], + "payable": False, + "stateMutability": "view", + "type": "function", + }, + { + "constant": True, + "inputs": [{"internalType": "address", "name": "account", "type": "address"}], + "name": "balanceOf", + "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], + "payable": False, + "stateMutability": "view", + "type": "function", + }, + { + "constant": False, + "inputs": [ + {"internalType": "address", "name": "recipient", "type": "address"}, + {"internalType": "uint256", "name": "amount", "type": "uint256"}, + ], + "name": "transfer", + "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], + "payable": False, + "stateMutability": "nonpayable", + "type": "function", + }, + { + "anonymous": False, + "inputs": [ + {"indexed": True, "internalType": "address", "name": "owner", "type": "address"}, + {"indexed": True, "internalType": "address", "name": "spender", "type": "address"}, + {"indexed": False, "internalType": "uint256", "name": "value", "type": "uint256"}, + ], + "name": "Approval", + "type": "event", + }, + { + "anonymous": False, + "inputs": [ + {"indexed": True, "internalType": "address", "name": "from", "type": "address"}, + {"indexed": True, "internalType": "address", "name": "to", "type": "address"}, + {"indexed": False, "internalType": "uint256", "name": "value", "type": "uint256"}, + ], + "name": "Transfer", + "type": "event", + }, + { + "constant": True, + "inputs": [], + "name": "decimals", + "outputs": [{"internalType": "uint8", "name": "", "type": "uint8"}], + "payable": False, + "stateMutability": "view", + "type": "function", + }, +] + +METAMORPHO_ABI = [ + { + "inputs": [ + {"internalType": "uint256", "name": "assets", "type": "uint256"}, + {"internalType": "address", "name": "receiver", "type": "address"}, + ], + "name": "deposit", + "outputs": [{"internalType": "uint256", "name": "shares", "type": "uint256"}], + "stateMutability": "nonpayable", + "type": "function", + }, + { + "inputs": [ + {"internalType": "uint256", "name": "assets", "type": "uint256"}, + {"internalType": "address", "name": "receiver", "type": "address"}, + {"internalType": "address", "name": "owner", "type": "address"}, + ], + "name": "withdraw", + "outputs": [{"internalType": "uint256", "name": "shares", "type": "uint256"}], + "stateMutability": "nonpayable", + "type": "function", + }, +] diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/deposit.py b/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/deposit.py new file mode 100644 index 00000000..7b983cfd --- /dev/null +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/deposit.py @@ -0,0 +1,88 @@ +from collections.abc import Callable +from decimal import Decimal + +from cdp import Asset, Wallet +from pydantic import BaseModel + +from cdp_agentkit_core.actions import CdpAction +from cdp_agentkit_core.actions.morpho.constants import METAMORPHO_ABI +from cdp_agentkit_core.actions.morpho.utils import approve + + +class MorphoDepositInput(BaseModel): + """Input schema for Morpho Vault deposit action.""" + + vault_address: str + assets: str + receiver: str + token_address: str + + +DEPOSIT_PROMPT = """ +This tool allows depositing assets into a Morpho Vault. It takes: + +- vault_address: The address of the Morpho Vault to deposit to +- assets: The amount of assets to deposit in native units + Examples for WETH: + - 1 WETH + - 0.1 WETH + - 0.01 WETH +- receiver: The address to receive the shares +- token_address: The address of the token to approve +""" + + +def deposit_to_morpho( + wallet: Wallet, + vault_address: str, + assets: str, + receiver: str, + token_address: str, +) -> str: + """Deposit assets into a Morpho Vault. + + Args: + wallet (Wallet): The wallet to execute the deposit from + vault_address (str): The address of the Morpho Vault + assets (str): The amount of assets to deposit in native units (e.g., 0.01 WETH) + receiver (str): The address to receive the shares + token_address (str): The address of the token to approve + + Returns: + str: A success message with transaction hash or error message + + """ + if float(assets) <= 0: + return "Error: Assets amount must be greater than 0" + + try: + token_asset = Asset.fetch(wallet.network_id, token_address) + + atomic_assets = str(int(token_asset.to_atomic_amount(Decimal(assets)))) + + approval_result = approve(wallet, token_address, vault_address, atomic_assets) + if approval_result.startswith("Error"): + return f"Error approving Morpho Vault as spender: {approval_result}" + + deposit_args = {"assets": atomic_assets, "receiver": receiver} + + invocation = wallet.invoke_contract( + contract_address=vault_address, + method="deposit", + abi=METAMORPHO_ABI, + args=deposit_args, + ).wait() + + return f"Deposited {assets} to Morpho Vault {vault_address} with transaction hash: {invocation.transaction_hash} and transaction link: {invocation.transaction_link}" + + except Exception as e: + return f"Error depositing to Morpho Vault: {e!s}" + + +class MorphoDepositAction(CdpAction): + """Morpho Vault deposit action.""" + + name: str = "morpho_deposit" + description: str = DEPOSIT_PROMPT + args_schema: type[BaseModel] = MorphoDepositInput + func: Callable[..., str] = deposit_to_morpho diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/utils.py b/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/utils.py new file mode 100644 index 00000000..bcaf9be7 --- /dev/null +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/utils.py @@ -0,0 +1,35 @@ +from cdp import Wallet + +from cdp_agentkit_core.actions.morpho.constants import ERC20_ABI + + +def approve(wallet: Wallet, token_address: str, spender: str, amount: int) -> str: + """Approve a spender to spend a specified amount of tokens. + + Args: + wallet (Wallet): The wallet to execute the approval from + token_address (str): The address of the token contract + spender (str): The address of the spender + amount (int): The amount of tokens to approve + + Returns: + str: A success message with transaction hash or error message + + """ + try: + amount_str = str(amount) + + invocation = wallet.invoke_contract( + contract_address=token_address, + method="approve", + abi=ERC20_ABI, + args={ + "spender": spender, + "value": amount_str, + }, + ).wait() + + return f"Approved {amount} tokens for {spender} with transaction hash: {invocation.transaction_hash} and transaction link: {invocation.transaction_link}" + + except Exception as e: + return f"Error approving tokens: {e!s}" diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/withdraw.py b/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/withdraw.py new file mode 100644 index 00000000..08be2cd1 --- /dev/null +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/morpho/withdraw.py @@ -0,0 +1,67 @@ +from collections.abc import Callable + +from cdp import Wallet +from pydantic import BaseModel + +from cdp_agentkit_core.actions import CdpAction +from cdp_agentkit_core.actions.morpho.constants import METAMORPHO_ABI + + +class MorphoWithdrawInput(BaseModel): + """Input schema for Morpho Vault withdraw action.""" + + vault_address: str + assets: str + receiver: str + + +WITHDRAW_PROMPT = """ +This tool allows withdrawing assets from a Morpho Vault. It takes: + +- vault_address: The address of the Morpho Vault to withdraw from +- assets: The amount of assets to withdraw in atomic units +- receiver: The address to receive the shares +""" + + +def withdraw_from_morpho(wallet: Wallet, vault_address: str, assets: str, receiver: str) -> str: + """Withdraw assets from a Morpho Vault. + + Args: + wallet (Wallet): The wallet to execute the deposit from + vault_address (str): The address of the Morpho Vault + assets (str): The amount of assets to withdraw in atomic units + receiver (str): The address to receive the shares + + Returns: + str: A success message with transaction hash or error message + + """ + if int(assets) <= 0: + return "Error: Assets amount must be greater than 0" + + try: + invocation = wallet.invoke_contract( + contract_address=vault_address, + method="withdraw", + abi=METAMORPHO_ABI, + args={ + "assets": assets, + "receiver": receiver, + "owner": receiver, + }, + ).wait() + + return f"Withdrawn {assets} from Morpho Vault {vault_address} with transaction hash: {invocation.transaction_hash} and transaction link: {invocation.transaction_link}" + + except Exception as e: + return f"Error withdrawing from Morpho Vault: {e!s}" + + +class MorphoWithdrawAction(CdpAction): + """Morpho Vault withdraw action.""" + + name: str = "morpho_withdraw" + description: str = WITHDRAW_PROMPT + args_schema: type[BaseModel] = MorphoWithdrawInput + func: Callable[..., str] = withdraw_from_morpho diff --git a/cdp-agentkit-core/tests/actions/morpho/test_deposit.py b/cdp-agentkit-core/tests/actions/morpho/test_deposit.py new file mode 100644 index 00000000..57f8270f --- /dev/null +++ b/cdp-agentkit-core/tests/actions/morpho/test_deposit.py @@ -0,0 +1,167 @@ +from decimal import Decimal +from unittest.mock import patch + +import pytest + +from cdp_agentkit_core.actions.morpho.constants import METAMORPHO_ABI +from cdp_agentkit_core.actions.morpho.deposit import ( + MorphoDepositInput, + deposit_to_morpho, +) + +MOCK_VAULT_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e" +MOCK_ASSETS_WETH = "1000000000000000000" +MOCK_NETWORK_ID = "base-sepolia" +MOCK_WALLET_ADDRESS = "0x1234567890123456789012345678901234567890" +MOCK_TOKEN_ADDRESS = "0x4200000000000000000000000000000000000006" +MOCK_DECIMALS = 18 +MOCK_ASSETS = "1" +MOCK_ASSETS_WEI = "1000000000000000000" + + +def test_deposit_input_model_valid(): + """Test that MorphoDepositInput accepts valid parameters.""" + input_model = MorphoDepositInput( + vault_address=MOCK_VAULT_ADDRESS, + assets=MOCK_ASSETS_WETH, + receiver=MOCK_WALLET_ADDRESS, + token_address=MOCK_TOKEN_ADDRESS, + ) + + assert input_model.vault_address == MOCK_VAULT_ADDRESS + assert input_model.assets == MOCK_ASSETS_WETH + assert input_model.receiver == MOCK_WALLET_ADDRESS + assert input_model.token_address == MOCK_TOKEN_ADDRESS + + +def test_deposit_input_model_missing_params(): + """Test that MorphoDepositInput raises error when params are missing.""" + with pytest.raises(ValueError): + MorphoDepositInput() + + +def test_deposit_success(wallet_factory, contract_invocation_factory, asset_factory): + """Test successful deposit with valid parameters.""" + mock_wallet = wallet_factory() + mock_contract_instance = contract_invocation_factory() + mock_wallet.default_address.address_id = MOCK_WALLET_ADDRESS + mock_wallet.network_id = MOCK_NETWORK_ID + mock_asset = asset_factory(decimals=MOCK_DECIMALS) + + with ( + patch( + "cdp_agentkit_core.actions.morpho.deposit.approve", return_value="Approval successful" + ) as mock_approve, + patch( + "cdp_agentkit_core.actions.morpho.deposit.Asset.fetch", return_value=mock_asset + ) as mock_get_asset, + patch.object( + mock_asset, "to_atomic_amount", return_value=MOCK_ASSETS_WEI + ) as mock_to_atomic_amount, + patch.object( + mock_wallet, "invoke_contract", return_value=mock_contract_instance + ) as mock_invoke, + patch.object( + mock_contract_instance, "wait", return_value=mock_contract_instance + ) as mock_contract_wait, + ): + action_response = deposit_to_morpho( + mock_wallet, + MOCK_VAULT_ADDRESS, + MOCK_ASSETS, + MOCK_WALLET_ADDRESS, + MOCK_TOKEN_ADDRESS, + ) + + expected_response = f"Deposited {MOCK_ASSETS} to Morpho Vault {MOCK_VAULT_ADDRESS} with transaction hash: {mock_contract_instance.transaction_hash} and transaction link: {mock_contract_instance.transaction_link}" + assert action_response == expected_response + + mock_approve.assert_called_once_with( + mock_wallet, MOCK_TOKEN_ADDRESS, MOCK_VAULT_ADDRESS, MOCK_ASSETS_WEI + ) + + mock_get_asset.assert_called_once_with(MOCK_NETWORK_ID, MOCK_TOKEN_ADDRESS) + + mock_to_atomic_amount.assert_called_once_with(Decimal(MOCK_ASSETS)) + + mock_invoke.assert_called_once_with( + contract_address=MOCK_VAULT_ADDRESS, + method="deposit", + abi=METAMORPHO_ABI, + args={"assets": MOCK_ASSETS_WEI, "receiver": MOCK_WALLET_ADDRESS}, + ) + mock_contract_wait.assert_called_once_with() + + +def test_deposit_api_error(wallet_factory, asset_factory): + """Test deposit when API error occurs.""" + mock_wallet = wallet_factory() + mock_wallet.default_address.address_id = MOCK_WALLET_ADDRESS + mock_wallet.network_id = MOCK_NETWORK_ID + mock_asset = asset_factory(decimals=MOCK_DECIMALS) + + with ( + patch( + "cdp_agentkit_core.actions.morpho.deposit.approve", return_value="Approval successful" + ), + patch( + "cdp_agentkit_core.actions.morpho.deposit.Asset.fetch", return_value=mock_asset + ) as mock_get_asset, + patch.object( + mock_asset, "to_atomic_amount", return_value=MOCK_ASSETS_WEI + ) as mock_to_atomic_amount, + patch.object(mock_wallet, "invoke_contract", side_effect=Exception("API error")), + ): + action_response = deposit_to_morpho( + mock_wallet, + MOCK_VAULT_ADDRESS, + MOCK_ASSETS, # Using non-wei value + MOCK_WALLET_ADDRESS, + MOCK_TOKEN_ADDRESS, + ) + + expected_response = "Error depositing to Morpho Vault: API error" + assert action_response == expected_response + + mock_get_asset.assert_called_once_with(MOCK_NETWORK_ID, MOCK_TOKEN_ADDRESS) + + mock_to_atomic_amount.assert_called_once_with(Decimal(MOCK_ASSETS)) + + +def test_deposit_approval_failure(wallet_factory, asset_factory): + """Test deposit when approval fails.""" + mock_wallet = wallet_factory() + mock_wallet.default_address.address_id = MOCK_WALLET_ADDRESS + mock_wallet.network_id = MOCK_NETWORK_ID + mock_asset = asset_factory(decimals=MOCK_DECIMALS) + + with ( + patch( + "cdp_agentkit_core.actions.morpho.deposit.approve", + return_value="Error: Approval failed", + ) as mock_approve, + patch( + "cdp_agentkit_core.actions.morpho.deposit.Asset.fetch", return_value=mock_asset + ) as mock_get_asset, + patch.object( + mock_asset, "to_atomic_amount", return_value=MOCK_ASSETS_WEI + ) as mock_to_atomic_amount, + ): + action_response = deposit_to_morpho( + mock_wallet, + MOCK_VAULT_ADDRESS, + MOCK_ASSETS, # Using non-wei value + MOCK_WALLET_ADDRESS, + MOCK_TOKEN_ADDRESS, + ) + + expected_response = "Error approving Morpho Vault as spender: Error: Approval failed" + assert action_response == expected_response + + mock_approve.assert_called_once_with( + mock_wallet, MOCK_TOKEN_ADDRESS, MOCK_VAULT_ADDRESS, MOCK_ASSETS_WEI + ) + + mock_get_asset.assert_called_once_with(MOCK_NETWORK_ID, MOCK_TOKEN_ADDRESS) + + mock_to_atomic_amount.assert_called_once_with(Decimal(MOCK_ASSETS)) diff --git a/cdp-agentkit-core/tests/actions/morpho/test_withdraw.py b/cdp-agentkit-core/tests/actions/morpho/test_withdraw.py new file mode 100644 index 00000000..aa090e43 --- /dev/null +++ b/cdp-agentkit-core/tests/actions/morpho/test_withdraw.py @@ -0,0 +1,92 @@ +from unittest.mock import patch + +import pytest + +from cdp_agentkit_core.actions.morpho.constants import METAMORPHO_ABI +from cdp_agentkit_core.actions.morpho.withdraw import ( + MorphoWithdrawInput, + withdraw_from_morpho, +) + +MOCK_VAULT_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e" +MOCK_ASSETS_WETH = "1000000000000000000" +MOCK_NETWORK_ID = "base-sepolia" +MOCK_WALLET_ADDRESS = "0x1234567890123456789012345678901234567890" + + +def test_deposit_input_model_valid(): + """Test that MorphoWithdrawInput accepts valid parameters.""" + input_model = MorphoWithdrawInput( + vault_address=MOCK_VAULT_ADDRESS, + assets=MOCK_ASSETS_WETH, + receiver=MOCK_WALLET_ADDRESS, + ) + + assert input_model.vault_address == MOCK_VAULT_ADDRESS + assert input_model.assets == MOCK_ASSETS_WETH + assert input_model.receiver == MOCK_WALLET_ADDRESS + + +def test_withdraw_input_model_missing_params(): + """Test that MorphoWithdrawInput raises error when params are missing.""" + with pytest.raises(ValueError): + MorphoWithdrawInput() + + +def test_withdraw_success(wallet_factory, contract_invocation_factory): + """Test successful withdraw with valid parameters.""" + mock_wallet = wallet_factory() + mock_contract_instance = contract_invocation_factory() + mock_wallet.default_address.address_id = MOCK_WALLET_ADDRESS + mock_wallet.network_id = MOCK_NETWORK_ID + + with ( + patch.object( + mock_wallet, "invoke_contract", return_value=mock_contract_instance + ) as mock_invoke, + patch.object( + mock_contract_instance, "wait", return_value=mock_contract_instance + ) as mock_contract_wait, + ): + action_response = withdraw_from_morpho( + mock_wallet, + MOCK_VAULT_ADDRESS, + MOCK_ASSETS_WETH, + MOCK_WALLET_ADDRESS, + ) + + expected_response = f"Withdrawn {MOCK_ASSETS_WETH} from Morpho Vault {MOCK_VAULT_ADDRESS} with transaction hash: {mock_contract_instance.transaction_hash} and transaction link: {mock_contract_instance.transaction_link}" + assert action_response == expected_response + + mock_invoke.assert_called_once_with( + contract_address=MOCK_VAULT_ADDRESS, + method="withdraw", + abi=METAMORPHO_ABI, + args={ + "assets": MOCK_ASSETS_WETH, + "receiver": MOCK_WALLET_ADDRESS, + "owner": MOCK_WALLET_ADDRESS, + }, + ) + mock_contract_wait.assert_called_once_with() + + +def test_withdraw_api_error(wallet_factory): + """Test withdraw when API error occurs.""" + mock_wallet = wallet_factory() + mock_wallet.default_address.address_id = MOCK_WALLET_ADDRESS + mock_wallet.network_id = MOCK_NETWORK_ID + + with patch.object( + mock_wallet, "invoke_contract", side_effect=Exception("API error") + ) as mock_invoke: + action_response = withdraw_from_morpho( + mock_wallet, + MOCK_VAULT_ADDRESS, + MOCK_ASSETS_WETH, + MOCK_WALLET_ADDRESS, + ) + + expected_response = "Error withdrawing from Morpho Vault: API error" + assert action_response == expected_response + mock_invoke.assert_called_once() diff --git a/cdp-agentkit-core/tests/factories/asset_factory.py b/cdp-agentkit-core/tests/factories/asset_factory.py new file mode 100644 index 00000000..39a7ebd7 --- /dev/null +++ b/cdp-agentkit-core/tests/factories/asset_factory.py @@ -0,0 +1,17 @@ +from unittest.mock import Mock + +import pytest +from cdp.asset import Asset + + +@pytest.fixture +def asset_factory(): + """Create and return a factory for creating Asset fixtures.""" + + def _create_asset(network_id="base-sepolia", asset_id="usdc", decimals=6): + asset_mock = Mock(spec=Asset) + asset_mock.decimals = decimals + + return asset_mock + + return _create_asset diff --git a/cdp-langchain/examples/chatbot/morpho_wallet_data.txt b/cdp-langchain/examples/chatbot/morpho_wallet_data.txt new file mode 100644 index 00000000..d280b559 --- /dev/null +++ b/cdp-langchain/examples/chatbot/morpho_wallet_data.txt @@ -0,0 +1 @@ +{"wallet_id": "5a74a1a2-c2ee-4162-b6b8-ec9f5af332fa", "seed": "a3e61f8e7d431e627e22384b2896b1b035c50dbb72b410b34fc1b4f83f4316b63c353fbcd81960a60b3363dd4cbc1dc1cfec4c70c87f03ce9422fd124e278c75", "default_address_id": "0x27A1dE5F0f84c9fE6aAFAa912A712EBB7D04ce05"} \ No newline at end of file