diff --git a/README.md b/README.md index efe122639..4715430b1 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ The Coinbase Developer Platform (CDP) Agentkit simplifies bringing your AI Agent - Getting wallet details and balances - Transferring and trading tokens - Registering Basenames - - Deploying ERC20 tokens and creating uniswap_v3 pools for trading + - Deploying ERC20 tokens - Deploying ERC721 tokens and minting NFTs ## Examples diff --git a/cdp-agentkit-core/CHANGELOG.md b/cdp-agentkit-core/CHANGELOG.md index b83efe36c..b39d18747 100644 --- a/cdp-agentkit-core/CHANGELOG.md +++ b/cdp-agentkit-core/CHANGELOG.md @@ -4,8 +4,6 @@ ### Added -- Added `uniswap_v3_create_pool` action. -- Added `uniswap_v3_get_pool`, `uniswap_v3_get_pool_observe`, `uniswap_v3_get_pool_slot0`, and `uniswap_v3_get_pool_liquidity` actions. - Added `wow_create_token` action. ## [0.0.1] - 2024-11-04 diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/__init__.py b/cdp-agentkit-core/cdp_agentkit_core/actions/__init__.py index f0cdea993..e2ae304a2 100644 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/__init__.py +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/__init__.py @@ -8,11 +8,6 @@ from cdp_agentkit_core.actions.request_faucet_funds import RequestFaucetFundsAction from cdp_agentkit_core.actions.trade import TradeAction from cdp_agentkit_core.actions.transfer import TransferAction -from cdp_agentkit_core.actions.uniswap_v3.create_pool import UniswapV3CreatePoolAction -from cdp_agentkit_core.actions.uniswap_v3.get_pool import UniswapV3GetPoolAction -from cdp_agentkit_core.actions.uniswap_v3.get_pool_liquidity import UniswapV3GetPoolLiquidityAction -from cdp_agentkit_core.actions.uniswap_v3.get_pool_observe import UniswapV3GetPoolObserveAction -from cdp_agentkit_core.actions.uniswap_v3.get_pool_slot0 import UniswapV3GetPoolSlot0Action from cdp_agentkit_core.actions.wow.create_token import WowCreateTokenAction @@ -39,11 +34,6 @@ def get_all_cdp_actions() -> list[type[CdpAction]]: "RequestFaucetFundsAction", "TradeAction", "TransferAction", - "UniswapV3CreatePoolAction", - "UniswapV3GetPoolAction", - "UniswapV3GetPoolSlot0Action", - "UniswapV3GetPoolObserveAction", - "UniswapV3GetPoolLiquidityAction", "WowCreateTokenAction", "CDP_ACTIONS", ] diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/deploy_nft.py b/cdp-agentkit-core/cdp_agentkit_core/actions/deploy_nft.py index 7a7e088fa..1ebfafb1e 100644 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/deploy_nft.py +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/deploy_nft.py @@ -39,7 +39,10 @@ def deploy_nft(wallet: Wallet, name: str, symbol: str, base_uri: str) -> str: str: A message containing the NFT token deployment details. """ - nft_contract = wallet.deploy_nft(name=name, symbol=symbol, base_uri=base_uri).wait() + try: + nft_contract = wallet.deploy_nft(name=name, symbol=symbol, base_uri=base_uri).wait() + except Exception as e: + return f"Error deploying NFT {e!s}" return f"Deployed NFT Collection {name} to address {nft_contract.contract_address} on network {wallet.network_id}.\nTransaction hash for the deployment: {nft_contract.transaction.transaction_hash}\nTransaction link for the deployment: {nft_contract.transaction.transaction_link}" diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/deploy_token.py b/cdp-agentkit-core/cdp_agentkit_core/actions/deploy_token.py index 5f150afe8..82f91277d 100644 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/deploy_token.py +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/deploy_token.py @@ -33,9 +33,12 @@ def deploy_token(wallet: Wallet, name: str, symbol: str, total_supply: str) -> s str: A message containing the deployed token contract address and details """ - token_contract = wallet.deploy_token(name=name, symbol=symbol, total_supply=total_supply) + try: + token_contract = wallet.deploy_token(name=name, symbol=symbol, total_supply=total_supply) - token_contract.wait() + token_contract.wait() + except Exception as e: + return f"Error deploying token {e!s}" return f"Deployed ERC20 token contract {name} ({symbol}) with total supply of {total_supply} tokens at address {token_contract.contract_address}. Transaction link: {token_contract.transaction.transaction_link}" diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/get_balance.py b/cdp-agentkit-core/cdp_agentkit_core/actions/get_balance.py index f77a0d940..f1b22c2c8 100644 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/get_balance.py +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/get_balance.py @@ -31,9 +31,13 @@ def get_balance(wallet: Wallet, asset_id: str) -> str: """ # for each address in the wallet, get the balance for the asset balances = {} - for address in wallet.addresses: - balance = address.balance(asset_id) - balances[address.address_id] = balance + + try: + for address in wallet.addresses: + balance = address.balance(asset_id) + balances[address.address_id] = balance + except Exception as e: + return f"Error getting balance for all addresses in the wallet {e!s}" # Format each balance entry on a new line balance_lines = [f" {addr}: {balance}" for addr, balance in balances.items()] diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/mint_nft.py b/cdp-agentkit-core/cdp_agentkit_core/actions/mint_nft.py index 97e9c351e..5d5656fd8 100644 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/mint_nft.py +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/mint_nft.py @@ -36,9 +36,12 @@ def mint_nft(wallet: Wallet, contract_address: str, destination: str) -> str: """ mint_args = {"to": destination, "quantity": "1"} - mint_invocation = wallet.invoke_contract( - contract_address=contract_address, method="mint", args=mint_args - ).wait() + try: + mint_invocation = wallet.invoke_contract( + contract_address=contract_address, method="mint", args=mint_args + ).wait() + except Exception as e: + return f"Error minting NFT {e!s}" return f"Minted NFT from contract {contract_address} to address {destination} on network {wallet.network_id}.\nTransaction hash for the mint: {mint_invocation.transaction.transaction_hash}\nTransaction link for the mint: {mint_invocation.transaction.transaction_link}" diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/request_faucet_funds.py b/cdp-agentkit-core/cdp_agentkit_core/actions/request_faucet_funds.py index ffc6617a2..495e24974 100644 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/request_faucet_funds.py +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/request_faucet_funds.py @@ -29,11 +29,14 @@ def request_faucet_funds(wallet: Wallet, asset_id: str | None = None) -> str: str: Confirmation message with transaction details """ - # Request funds from the faucet. - faucet_tx = wallet.faucet(asset_id=asset_id if asset_id else None) - - # Wait for the faucet transaction to be confirmed. - faucet_tx.wait() + try: + # Request funds from the faucet. + faucet_tx = wallet.faucet(asset_id=asset_id if asset_id else None) + + # Wait for the faucet transaction to be confirmed. + faucet_tx.wait() + except Exception as e: + return f"Error requesting faucet funds {e!s}" return f"Received {asset_id} from the faucet. Transaction: {faucet_tx.transaction_link}" diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/trade.py b/cdp-agentkit-core/cdp_agentkit_core/actions/trade.py index db6a26034..959271b50 100644 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/trade.py +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/trade.py @@ -38,9 +38,12 @@ def trade(wallet: Wallet, amount: str, from_asset_id: str, to_asset_id: str) -> str: A message containing the trade details. """ - trade_result = wallet.trade( - amount=amount, from_asset_id=from_asset_id, to_asset_id=to_asset_id - ).wait() + try: + trade_result = wallet.trade( + amount=amount, from_asset_id=from_asset_id, to_asset_id=to_asset_id + ).wait() + except Exception as e: + return f"Error trading assets {e!s}" return f"Traded {amount} of {from_asset_id} for {trade_result.to_amount} of {to_asset_id}.\nTransaction hash for the trade: {trade_result.transaction.transaction_hash}\nTransaction link for the trade: {trade_result.transaction.transaction_link}" diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/transfer.py b/cdp-agentkit-core/cdp_agentkit_core/actions/transfer.py index aea065a7c..07e0f9887 100644 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/transfer.py +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/transfer.py @@ -45,9 +45,12 @@ def transfer( str: A message containing the transfer details. """ - transfer_result = wallet.transfer( - amount=amount, asset_id=asset_id, destination=destination, gasless=gasless - ).wait() + try: + transfer_result = wallet.transfer( + amount=amount, asset_id=asset_id, destination=destination, gasless=gasless + ).wait() + except Exception as e: + return f"Error transferring the asset {e!s}" return f"Transferred {amount} of {asset_id} to {destination}.\nTransaction hash for the transfer: {transfer_result.transaction_hash}\nTransaction link for the transfer: {transfer_result.transaction_link}" diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/constants.py b/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/constants.py deleted file mode 100644 index 14ceb3d02..000000000 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/constants.py +++ /dev/null @@ -1,548 +0,0 @@ -UNISWAP_V3_FACTORY_ABI = [ - {"inputs": [], "stateMutability": "nonpayable", "type": "constructor"}, - { - "anonymous": False, - "inputs": [ - {"indexed": True, "internalType": "uint24", "name": "fee", "type": "uint24"}, - {"indexed": True, "internalType": "int24", "name": "tickSpacing", "type": "int24"}, - ], - "name": "FeeAmountEnabled", - "type": "event", - }, - { - "anonymous": False, - "inputs": [ - {"indexed": True, "internalType": "address", "name": "oldOwner", "type": "address"}, - {"indexed": True, "internalType": "address", "name": "newOwner", "type": "address"}, - ], - "name": "OwnerChanged", - "type": "event", - }, - { - "anonymous": False, - "inputs": [ - {"indexed": True, "internalType": "address", "name": "token0", "type": "address"}, - {"indexed": True, "internalType": "address", "name": "token1", "type": "address"}, - {"indexed": True, "internalType": "uint24", "name": "fee", "type": "uint24"}, - {"indexed": False, "internalType": "int24", "name": "tickSpacing", "type": "int24"}, - {"indexed": False, "internalType": "address", "name": "pool", "type": "address"}, - ], - "name": "PoolCreated", - "type": "event", - }, - { - "inputs": [ - {"internalType": "address", "name": "tokenA", "type": "address"}, - {"internalType": "address", "name": "tokenB", "type": "address"}, - {"internalType": "uint24", "name": "fee", "type": "uint24"}, - ], - "name": "createPool", - "outputs": [{"internalType": "address", "name": "pool", "type": "address"}], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [ - {"internalType": "uint24", "name": "fee", "type": "uint24"}, - {"internalType": "int24", "name": "tickSpacing", "type": "int24"}, - ], - "name": "enableFeeAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [{"internalType": "uint24", "name": "", "type": "uint24"}], - "name": "feeAmountTickSpacing", - "outputs": [{"internalType": "int24", "name": "", "type": "int24"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [ - {"internalType": "address", "name": "tokenA", "type": "address"}, - {"internalType": "address", "name": "tokenB", "type": "address"}, - {"internalType": "uint24", "name": "fee", "type": "uint24"}, - ], - "name": "getPool", - "outputs": [{"internalType": "address", "name": "", "type": "address"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [], - "name": "owner", - "outputs": [{"internalType": "address", "name": "", "type": "address"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [], - "name": "parameters", - "outputs": [ - {"internalType": "address", "name": "factory", "type": "address"}, - {"internalType": "address", "name": "token0", "type": "address"}, - {"internalType": "address", "name": "token1", "type": "address"}, - {"internalType": "uint24", "name": "fee", "type": "uint24"}, - {"internalType": "int24", "name": "tickSpacing", "type": "int24"}, - ], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [{"internalType": "address", "name": "_owner", "type": "address"}], - "name": "setOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function", - }, -] - -UNISWAP_V3_POOL_ABI = [ - {"inputs": [], "stateMutability": "nonpayable", "type": "constructor"}, - { - "anonymous": False, - "inputs": [ - {"indexed": True, "internalType": "address", "name": "owner", "type": "address"}, - {"indexed": True, "internalType": "int24", "name": "tickLower", "type": "int24"}, - {"indexed": True, "internalType": "int24", "name": "tickUpper", "type": "int24"}, - {"indexed": False, "internalType": "uint128", "name": "amount", "type": "uint128"}, - {"indexed": False, "internalType": "uint256", "name": "amount0", "type": "uint256"}, - {"indexed": False, "internalType": "uint256", "name": "amount1", "type": "uint256"}, - ], - "name": "Burn", - "type": "event", - }, - { - "anonymous": False, - "inputs": [ - {"indexed": True, "internalType": "address", "name": "owner", "type": "address"}, - {"indexed": False, "internalType": "address", "name": "recipient", "type": "address"}, - {"indexed": True, "internalType": "int24", "name": "tickLower", "type": "int24"}, - {"indexed": True, "internalType": "int24", "name": "tickUpper", "type": "int24"}, - {"indexed": False, "internalType": "uint128", "name": "amount0", "type": "uint128"}, - {"indexed": False, "internalType": "uint128", "name": "amount1", "type": "uint128"}, - ], - "name": "Collect", - "type": "event", - }, - { - "anonymous": False, - "inputs": [ - {"indexed": True, "internalType": "address", "name": "sender", "type": "address"}, - {"indexed": True, "internalType": "address", "name": "recipient", "type": "address"}, - {"indexed": False, "internalType": "uint128", "name": "amount0", "type": "uint128"}, - {"indexed": False, "internalType": "uint128", "name": "amount1", "type": "uint128"}, - ], - "name": "CollectProtocol", - "type": "event", - }, - { - "anonymous": False, - "inputs": [ - {"indexed": True, "internalType": "address", "name": "sender", "type": "address"}, - {"indexed": True, "internalType": "address", "name": "recipient", "type": "address"}, - {"indexed": False, "internalType": "uint256", "name": "amount0", "type": "uint256"}, - {"indexed": False, "internalType": "uint256", "name": "amount1", "type": "uint256"}, - {"indexed": False, "internalType": "uint256", "name": "paid0", "type": "uint256"}, - {"indexed": False, "internalType": "uint256", "name": "paid1", "type": "uint256"}, - ], - "name": "Flash", - "type": "event", - }, - { - "anonymous": False, - "inputs": [ - { - "indexed": False, - "internalType": "uint16", - "name": "observationCardinalityNextOld", - "type": "uint16", - }, - { - "indexed": False, - "internalType": "uint16", - "name": "observationCardinalityNextNew", - "type": "uint16", - }, - ], - "name": "IncreaseObservationCardinalityNext", - "type": "event", - }, - { - "anonymous": False, - "inputs": [ - { - "indexed": False, - "internalType": "uint160", - "name": "sqrtPriceX96", - "type": "uint160", - }, - {"indexed": False, "internalType": "int24", "name": "tick", "type": "int24"}, - ], - "name": "Initialize", - "type": "event", - }, - { - "anonymous": False, - "inputs": [ - {"indexed": False, "internalType": "address", "name": "sender", "type": "address"}, - {"indexed": True, "internalType": "address", "name": "owner", "type": "address"}, - {"indexed": True, "internalType": "int24", "name": "tickLower", "type": "int24"}, - {"indexed": True, "internalType": "int24", "name": "tickUpper", "type": "int24"}, - {"indexed": False, "internalType": "uint128", "name": "amount", "type": "uint128"}, - {"indexed": False, "internalType": "uint256", "name": "amount0", "type": "uint256"}, - {"indexed": False, "internalType": "uint256", "name": "amount1", "type": "uint256"}, - ], - "name": "Mint", - "type": "event", - }, - { - "anonymous": False, - "inputs": [ - {"indexed": False, "internalType": "uint8", "name": "feeProtocol0Old", "type": "uint8"}, - {"indexed": False, "internalType": "uint8", "name": "feeProtocol1Old", "type": "uint8"}, - {"indexed": False, "internalType": "uint8", "name": "feeProtocol0New", "type": "uint8"}, - {"indexed": False, "internalType": "uint8", "name": "feeProtocol1New", "type": "uint8"}, - ], - "name": "SetFeeProtocol", - "type": "event", - }, - { - "anonymous": False, - "inputs": [ - {"indexed": True, "internalType": "address", "name": "sender", "type": "address"}, - {"indexed": True, "internalType": "address", "name": "recipient", "type": "address"}, - {"indexed": False, "internalType": "int256", "name": "amount0", "type": "int256"}, - {"indexed": False, "internalType": "int256", "name": "amount1", "type": "int256"}, - { - "indexed": False, - "internalType": "uint160", - "name": "sqrtPriceX96", - "type": "uint160", - }, - {"indexed": False, "internalType": "uint128", "name": "liquidity", "type": "uint128"}, - {"indexed": False, "internalType": "int24", "name": "tick", "type": "int24"}, - ], - "name": "Swap", - "type": "event", - }, - { - "inputs": [ - {"internalType": "int24", "name": "tickLower", "type": "int24"}, - {"internalType": "int24", "name": "tickUpper", "type": "int24"}, - {"internalType": "uint128", "name": "amount", "type": "uint128"}, - ], - "name": "burn", - "outputs": [ - {"internalType": "uint256", "name": "amount0", "type": "uint256"}, - {"internalType": "uint256", "name": "amount1", "type": "uint256"}, - ], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [ - {"internalType": "address", "name": "recipient", "type": "address"}, - {"internalType": "int24", "name": "tickLower", "type": "int24"}, - {"internalType": "int24", "name": "tickUpper", "type": "int24"}, - {"internalType": "uint128", "name": "amount0Requested", "type": "uint128"}, - {"internalType": "uint128", "name": "amount1Requested", "type": "uint128"}, - ], - "name": "collect", - "outputs": [ - {"internalType": "uint128", "name": "amount0", "type": "uint128"}, - {"internalType": "uint128", "name": "amount1", "type": "uint128"}, - ], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [ - {"internalType": "address", "name": "recipient", "type": "address"}, - {"internalType": "uint128", "name": "amount0Requested", "type": "uint128"}, - {"internalType": "uint128", "name": "amount1Requested", "type": "uint128"}, - ], - "name": "collectProtocol", - "outputs": [ - {"internalType": "uint128", "name": "amount0", "type": "uint128"}, - {"internalType": "uint128", "name": "amount1", "type": "uint128"}, - ], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [], - "name": "factory", - "outputs": [{"internalType": "address", "name": "", "type": "address"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [], - "name": "fee", - "outputs": [{"internalType": "uint24", "name": "", "type": "uint24"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [], - "name": "feeGrowthGlobal0X128", - "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [], - "name": "feeGrowthGlobal1X128", - "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [ - {"internalType": "address", "name": "recipient", "type": "address"}, - {"internalType": "uint256", "name": "amount0", "type": "uint256"}, - {"internalType": "uint256", "name": "amount1", "type": "uint256"}, - {"internalType": "bytes", "name": "data", "type": "bytes"}, - ], - "name": "flash", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [ - {"internalType": "uint16", "name": "observationCardinalityNext", "type": "uint16"} - ], - "name": "increaseObservationCardinalityNext", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [{"internalType": "uint160", "name": "sqrtPriceX96", "type": "uint160"}], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [], - "name": "liquidity", - "outputs": [{"internalType": "uint128", "name": "", "type": "uint128"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [], - "name": "maxLiquidityPerTick", - "outputs": [{"internalType": "uint128", "name": "", "type": "uint128"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [ - {"internalType": "address", "name": "recipient", "type": "address"}, - {"internalType": "int24", "name": "tickLower", "type": "int24"}, - {"internalType": "int24", "name": "tickUpper", "type": "int24"}, - {"internalType": "uint128", "name": "amount", "type": "uint128"}, - {"internalType": "bytes", "name": "data", "type": "bytes"}, - ], - "name": "mint", - "outputs": [ - {"internalType": "uint256", "name": "amount0", "type": "uint256"}, - {"internalType": "uint256", "name": "amount1", "type": "uint256"}, - ], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], - "name": "observations", - "outputs": [ - {"internalType": "uint32", "name": "blockTimestamp", "type": "uint32"}, - {"internalType": "int56", "name": "tickCumulative", "type": "int56"}, - { - "internalType": "uint160", - "name": "secondsPerLiquidityCumulativeX128", - "type": "uint160", - }, - {"internalType": "bool", "name": "initialized", "type": "bool"}, - ], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [{"internalType": "uint32[]", "name": "secondsAgos", "type": "uint32[]"}], - "name": "observe", - "outputs": [ - {"internalType": "int56[]", "name": "tickCumulatives", "type": "int56[]"}, - { - "internalType": "uint160[]", - "name": "secondsPerLiquidityCumulativeX128s", - "type": "uint160[]", - }, - ], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [{"internalType": "bytes32", "name": "", "type": "bytes32"}], - "name": "positions", - "outputs": [ - {"internalType": "uint128", "name": "liquidity", "type": "uint128"}, - {"internalType": "uint256", "name": "feeGrowthInside0LastX128", "type": "uint256"}, - {"internalType": "uint256", "name": "feeGrowthInside1LastX128", "type": "uint256"}, - {"internalType": "uint128", "name": "tokensOwed0", "type": "uint128"}, - {"internalType": "uint128", "name": "tokensOwed1", "type": "uint128"}, - ], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [], - "name": "protocolFees", - "outputs": [ - {"internalType": "uint128", "name": "token0", "type": "uint128"}, - {"internalType": "uint128", "name": "token1", "type": "uint128"}, - ], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [ - {"internalType": "uint8", "name": "feeProtocol0", "type": "uint8"}, - {"internalType": "uint8", "name": "feeProtocol1", "type": "uint8"}, - ], - "name": "setFeeProtocol", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [], - "name": "slot0", - "outputs": [ - {"internalType": "uint160", "name": "sqrtPriceX96", "type": "uint160"}, - {"internalType": "int24", "name": "tick", "type": "int24"}, - {"internalType": "uint16", "name": "observationIndex", "type": "uint16"}, - {"internalType": "uint16", "name": "observationCardinality", "type": "uint16"}, - {"internalType": "uint16", "name": "observationCardinalityNext", "type": "uint16"}, - {"internalType": "uint8", "name": "feeProtocol", "type": "uint8"}, - {"internalType": "bool", "name": "unlocked", "type": "bool"}, - ], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [ - {"internalType": "int24", "name": "tickLower", "type": "int24"}, - {"internalType": "int24", "name": "tickUpper", "type": "int24"}, - ], - "name": "snapshotCumulativesInside", - "outputs": [ - {"internalType": "int56", "name": "tickCumulativeInside", "type": "int56"}, - {"internalType": "uint160", "name": "secondsPerLiquidityInsideX128", "type": "uint160"}, - {"internalType": "uint32", "name": "secondsInside", "type": "uint32"}, - ], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [ - {"internalType": "address", "name": "recipient", "type": "address"}, - {"internalType": "bool", "name": "zeroForOne", "type": "bool"}, - {"internalType": "int256", "name": "amountSpecified", "type": "int256"}, - {"internalType": "uint160", "name": "sqrtPriceLimitX96", "type": "uint160"}, - {"internalType": "bytes", "name": "data", "type": "bytes"}, - ], - "name": "swap", - "outputs": [ - {"internalType": "int256", "name": "amount0", "type": "int256"}, - {"internalType": "int256", "name": "amount1", "type": "int256"}, - ], - "stateMutability": "nonpayable", - "type": "function", - }, - { - "inputs": [{"internalType": "int16", "name": "", "type": "int16"}], - "name": "tickBitmap", - "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [], - "name": "tickSpacing", - "outputs": [{"internalType": "int24", "name": "", "type": "int24"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [{"internalType": "int24", "name": "", "type": "int24"}], - "name": "ticks", - "outputs": [ - {"internalType": "uint128", "name": "liquidityGross", "type": "uint128"}, - {"internalType": "int128", "name": "liquidityNet", "type": "int128"}, - {"internalType": "uint256", "name": "feeGrowthOutside0X128", "type": "uint256"}, - {"internalType": "uint256", "name": "feeGrowthOutside1X128", "type": "uint256"}, - {"internalType": "int56", "name": "tickCumulativeOutside", "type": "int56"}, - { - "internalType": "uint160", - "name": "secondsPerLiquidityOutsideX128", - "type": "uint160", - }, - {"internalType": "uint32", "name": "secondsOutside", "type": "uint32"}, - {"internalType": "bool", "name": "initialized", "type": "bool"}, - ], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [], - "name": "token0", - "outputs": [{"internalType": "address", "name": "", "type": "address"}], - "stateMutability": "view", - "type": "function", - }, - { - "inputs": [], - "name": "token1", - "outputs": [{"internalType": "address", "name": "", "type": "address"}], - "stateMutability": "view", - "type": "function", - }, -] - - -UNISWAP_V3_FACTORY_CONTRACT_ADDRESSES = { - "base-sepolia": "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24", - "base-mainnet": "0x33128a8fC17869897dcE68Ed026d694621f6FDfD", - "ethereum-mainnet": "0x1F98431c8aD98523631AE4a59f267346ea31F984", - "arbitrum-mainnet": "0x1F98431c8aD98523631AE4a59f267346ea31F984", - "polygon-mainnet": "0x1F98431c8aD98523631AE4a59f267346ea31F984", -} - - -def get_contract_address(network: str) -> str: - """Get the Uniswap V3 Factory contract address for the specified network. - - Args: - network (str): The network ID to get the contract address for. - Valid networks are: base-sepolia, base-mainnet, ethereum-mainnet, - arbitrum-mainnet, polygon-mainnet. - - Returns: - str: The contract address for the specified network. - - Raises: - ValueError: If the specified network is not supported. - - """ - network = network.lower() - if network not in UNISWAP_V3_FACTORY_CONTRACT_ADDRESSES: - raise ValueError( - f"Invalid network: {network}. Valid networks are: {', '.join(UNISWAP_V3_FACTORY_CONTRACT_ADDRESSES.keys())}" - ) - return UNISWAP_V3_FACTORY_CONTRACT_ADDRESSES[network] diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/create_pool.py b/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/create_pool.py deleted file mode 100644 index beb6539e3..000000000 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/create_pool.py +++ /dev/null @@ -1,67 +0,0 @@ -from collections.abc import Callable - -from cdp import Wallet -from pydantic import BaseModel, Field - -from cdp_agentkit_core.actions import CdpAction -from cdp_agentkit_core.actions.uniswap_v3.constants import ( - UNISWAP_V3_FACTORY_ABI, - get_contract_address, -) - -UNISWAP_V3_CREATE_POOL_PROMPT = """ -This tool will create a Uniswap v3 pool for trading 2 tokens, one of which can be the native gas token. For native gas token, use the address 0x4200000000000000000000000000000000000006, and for ERC20 token, use its contract address. This tool takes the address of the first token, address of the second token, and the fee to charge for trades as inputs. The fee is denominated in hundredths of a bip (i.e. 1e-6) and must be passed a string. Acceptable fee values are 100, 500, 3000, and 10000. Supported networks are Base Sepolia, Base Mainnet, Ethereum Mainnet, Polygon Mainnet, and Arbitrum Mainnet.""" - - -class UniswapV3CreatePoolInput(BaseModel): - """Input argument schema for create pool action.""" - - token_a: str = Field( - ..., - description="The address of the first token to trade, e.g. 0x4200000000000000000000000000000000000006 for native gas token", - ) - token_b: str = Field( - ..., - description="The address of the second token to trade, e.g. 0x1234567890123456789012345678901234567890 for ERC20 token", - ) - fee: str = Field( - ..., - description="The fee to charge for trades, denominated in hundredths of a bip (i.e. 1e-6). Acceptable fee values are 100, 500, 3000, and 10000.", - ) - - -def uniswap_v3_create_pool(wallet: Wallet, token_a: str, token_b: str, fee: str) -> str: - """Create a Uniswap v3 pool for trading 2 tokens, one of which can be the native gas token. - - Args: - wallet (Wallet): The wallet to create the pool from. - token_a (str): The address of the first token to trade, e.g. 0x4200000000000000000000000000000000000006 for native gas token - token_b (str): The address of the second token to trade, e.g. 0x1234567890123456789012345678901234567890 for ERC20 token - fee (str): The fee to charge for trades, denominated in hundredths of a bip (i.e. 1e-6). - - Returns: - str: A message containing the pool creation details. - - """ - factory_address = get_contract_address(wallet.network_id) - - pool = wallet.invoke_contract( - contract_address=factory_address, - method="createPool", - abi=UNISWAP_V3_FACTORY_ABI, - args={ - "tokenA": token_a, - "tokenB": token_b, - "fee": fee, - }, - ).wait() - return f"Created pool for {token_a} and {token_b} with fee {fee} on network {wallet.network_id}.\nTransaction hash for the pool creation: {pool.transaction.transaction_hash}\nTransaction link for the pool creation: {pool.transaction.transaction_link}" - - -class UniswapV3CreatePoolAction(CdpAction): - """Uniswap V3 create pool action.""" - - name: str = "uniswap_v3_create_pool" - description: str = UNISWAP_V3_CREATE_POOL_PROMPT - args_schema: type[BaseModel] | None = UniswapV3CreatePoolInput - func: Callable[..., str] = uniswap_v3_create_pool diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool.py b/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool.py deleted file mode 100644 index 68b9f6d88..000000000 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool.py +++ /dev/null @@ -1,70 +0,0 @@ -from collections.abc import Callable - -from cdp import SmartContract -from pydantic import BaseModel, Field - -from cdp_agentkit_core.actions.cdp_action import CdpAction -from cdp_agentkit_core.actions.uniswap_v3.constants import ( - UNISWAP_V3_FACTORY_ABI, - get_contract_address, -) - -UNISWAP_V3_GET_POOL_PROMPT = """ -This tool will get the pool contract address for Uniswap V3 pools that have been previously created. It takes in the networkId, the two token addresses, with the value 0x4200000000000000000000000000000000000006 for native gas token and a value like 0x1234567890123456789012345678901234567890 for ERC20 token. It also takes in the pool fee, which is denominated in hundredths of a bip (i.e. 1e-6). Acceptable fee values are 100, 500, 3000, and 10000. Supported networks are Base Sepolia, Base Mainnet, Ethereum Mainnet, Polygon Mainnet, and Arbitrum Mainnet. -""" - - -class UniswapV3GetPoolInput(BaseModel): - """Input argument schema for get pool action.""" - - network_id: str = Field( - ..., - description="The network ID of the network to get the pool on.", - ) - token_a: str = Field( - ..., - description="The address of the first token to trade, e.g. 0x4200000000000000000000000000000000000006 for native gas token", - ) - token_b: str = Field( - ..., - description="The address of the second token to trade, e.g. 0x1234567890123456789012345678901234567890 for ERC20 token", - ) - fee: str = Field( - ..., - description="The fee to charge for trades, denominated in hundredths of a bip (i.e. 1e-6). Acceptable fee values are 100, 500, 3000, and 10000.", - ) - - -def uniswap_v3_get_pool(network_id: str, token_a: str, token_b: str, fee: str) -> str: - """Get the pool contract address for Uniswap V3 pools that have been created. - - Args: - network_id (str): The network ID of the network to get the pool on. - token_a (str): The address of the first token to trade, e.g. 0x4200000000000000000000000000000000000006 for native gas token - token_b (str): The address of the second token to trade, e.g. 0x1234567890123456789012345678901234567890 for ERC20 token - fee (str): The fee to charge for trades, denominated in hundredths of a bip (i.e. 1e-6). - - Returns: - str: A message containing the pool creation details. - - """ - factory_address = get_contract_address(network_id) - - pool_address = SmartContract.read( - network_id=network_id, - contract_address=factory_address, - method="getPool", - abi=UNISWAP_V3_FACTORY_ABI, - args={"tokenA": token_a, "tokenB": token_b, "fee": fee}, - ) - - return f"Pool contract address for {token_a} and {token_b} with fee {fee} on network {network_id} is {pool_address}." - - -class UniswapV3GetPoolAction(CdpAction): - """Uniswap V3 get pool action.""" - - name: str = "uniswap_v3_get_pool" - description: str = UNISWAP_V3_GET_POOL_PROMPT - args_schema: type[BaseModel] | None = UniswapV3GetPoolInput - func: Callable[..., str] = uniswap_v3_get_pool diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool_liquidity.py b/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool_liquidity.py deleted file mode 100644 index 81733b224..000000000 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool_liquidity.py +++ /dev/null @@ -1,57 +0,0 @@ -from collections.abc import Callable - -from cdp import SmartContract -from pydantic import BaseModel, Field - -from cdp_agentkit_core.actions.cdp_action import CdpAction -from cdp_agentkit_core.actions.uniswap_v3.constants import ( - UNISWAP_V3_POOL_ABI, -) - -UNISWAP_V3_GET_POOL_LIQUIDITY_PROMPT = """ -This tool will get the liquidity for Uniswap V3 pools that have been previously created. It takes in the networkId and the pool contract address. Supported networks are Base Sepolia, Base Mainnet, Ethereum Mainnet, Polygon Mainnet, and Arbitrum Mainnet. -""" - - -class UniswapV3GetPoolLiquidityInput(BaseModel): - """Input argument schema for get pool liquidity action.""" - - network_id: str = Field( - ..., - description="The network ID of the network to get the pool on.", - ) - pool_contract_address: str = Field( - ..., - description="The contract address of the pool to get the liquidity for.", - ) - - -def uniswap_v3_get_pool_liquidity(network_id: str, pool_contract_address: str) -> str: - """Get the liquidity for Uniswap V3 pools that have been created. - - Args: - network_id (str): The network ID of the network to get the pool on. - pool_contract_address (str): The contract address of the pool to get the liquidity for. - - Returns: - str: A message containing the liquidity for the pool. - - """ - liquidity = SmartContract.read( - network_id=network_id, - contract_address=pool_contract_address, - method="liquidity", - abi=UNISWAP_V3_POOL_ABI, - args={}, - ) - - return f"Liquidity for pool {pool_contract_address} is {liquidity}." - - -class UniswapV3GetPoolLiquidityAction(CdpAction): - """Uniswap V3 get pool liquidity action.""" - - name: str = "uniswap_v3_get_pool_liquidity" - description: str = UNISWAP_V3_GET_POOL_LIQUIDITY_PROMPT - args_schema: type[BaseModel] | None = UniswapV3GetPoolLiquidityInput - func: Callable[..., str] = uniswap_v3_get_pool_liquidity diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool_observe.py b/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool_observe.py deleted file mode 100644 index 4aaa83393..000000000 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool_observe.py +++ /dev/null @@ -1,67 +0,0 @@ -from collections.abc import Callable - -from cdp import SmartContract -from pydantic import BaseModel, Field - -from cdp_agentkit_core.actions.cdp_action import CdpAction -from cdp_agentkit_core.actions.uniswap_v3.constants import ( - UNISWAP_V3_POOL_ABI, -) - -UNISWAP_V3_GET_POOL_OBSERVE_PROMPT = """ -This tool will get the observation details for Uniswap V3 pools that have been previously created. It takes in a network ID, pool contract address, and list of secondsAgo values and returns the tickCumulative and secondsPerLiquidityCumulativeX128 for each secondsAgo value. -The tickCumulative is the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp. -The secondsPerLiquidityCumulativesX128 is the seconds per in range liquidity for the life of the pool as of the observation timestamp. -Supported networks are Base Sepolia, Base Mainnet, Ethereum Mainnet, Polygon Mainnet, and Arbitrum Mainnet. -""" - - -class UniswapV3GetPoolObserveInput(BaseModel): - """Input argument schema for get pool observe action.""" - - network_id: str = Field( - ..., - description="The network ID of the network to get the pool on.", - ) - pool_contract_address: str = Field( - ..., - description="The contract address of the pool to get the slot0 for.", - ) - seconds_ago: list[str] = Field( - ..., - description="The list of seconds ago values to get the observation for. The seconds ago value is the number of seconds ago from the current block timestamp to get the observation for and is provided as a string.", - ) - - -def uniswap_v3_get_pool_observe( - network_id: str, pool_contract_address: str, seconds_ago: list[str] -) -> str: - """Get the observation for Uniswap V3 pools that have been created. - - Args: - network_id (str): The network ID of the network to get the pool on. - pool_contract_address (str): The contract address of the pool to get the observation for. - seconds_ago (List[str]): The list of seconds ago values to get the observation for. The seconds ago value is the number of seconds ago from the current block timestamp to get the observation for and is provided as a string. - - Returns: - str: A message containing the observation details for the pool. - - """ - observations = SmartContract.read( - network_id=network_id, - contract_address=pool_contract_address, - method="observe", - abi=UNISWAP_V3_POOL_ABI, - args={"secondsAgos": seconds_ago}, - ) - - return f"Observations for pool {pool_contract_address} are {observations}." - - -class UniswapV3GetPoolObserveAction(CdpAction): - """Uniswap V3 get pool observe action.""" - - name: str = "uniswap_v3_get_pool_observe" - description: str = UNISWAP_V3_GET_POOL_OBSERVE_PROMPT - args_schema: type[BaseModel] | None = UniswapV3GetPoolObserveInput - func: Callable[..., str] = uniswap_v3_get_pool_observe diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool_slot0.py b/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool_slot0.py deleted file mode 100644 index bf73360f0..000000000 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/uniswap_v3/get_pool_slot0.py +++ /dev/null @@ -1,62 +0,0 @@ -from collections.abc import Callable - -from cdp import SmartContract -from pydantic import BaseModel, Field - -from cdp_agentkit_core.actions.cdp_action import CdpAction -from cdp_agentkit_core.actions.uniswap_v3.constants import ( - UNISWAP_V3_POOL_ABI, -) - -UNISWAP_V3_GET_POOL_SLOT0_PROMPT = """ -This tool will get the slot0 for Uniswap V3 pools. It takes in a networkId and pool contract address. The slot0 contains the sqrtPriceX96, tick, observationIndex, observationCardinality, observationCardinalityNext, feeProtocol, and unlocked. -The sqrtPriceX96 is the current price of the pool as a sqrt(token1/token0) Q64.96 value. -The tick is the current tick, based on the last transition that was run. This value may not always equal SqrtTickMath getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick boundary. -The observationIndex is the index of the last oracle observation. The observationCardinality is the maximum number of observations stored. -The observationCardinalityNext is the next maximum number of observations. The feeProtocol is the current fee as a percentage of the swap fee taken on withdrawal. -The unlocked is whether the pool is currently locked to reentrancy. Supported networks are Base Sepolia, Base Mainnet, Ethereum Mainnet, Polygon Mainnet, and Arbitrum Mainnet. -""" - - -class UniswapV3GetPoolSlot0Input(BaseModel): - """Input argument schema for get pool slot0 action.""" - - network_id: str = Field( - ..., - description="The network ID of the network to get the pool on.", - ) - pool_contract_address: str = Field( - ..., - description="The contract address of the pool to get the slot0 for.", - ) - - -def uniswap_v3_get_pool_slot0(network_id: str, pool_contract_address: str) -> str: - """Get the slot0 for Uniswap V3 pools that have been created. - - Args: - network_id (str): The network ID of the network to get the pool on. - pool_contract_address (str): The contract address of the pool to get the liquidity for. - - Returns: - str: A message containing the slot0 details for the pool. - - """ - slot0 = SmartContract.read( - network_id=network_id, - contract_address=pool_contract_address, - method="slot0", - abi=UNISWAP_V3_POOL_ABI, - args={}, - ) - - return f"Slot0 for pool {pool_contract_address} is {slot0}." - - -class UniswapV3GetPoolSlot0Action(CdpAction): - """Uniswap V3 get pool slot0 action.""" - - name: str = "uniswap_v3_get_pool_slot0" - description: str = UNISWAP_V3_GET_POOL_SLOT0_PROMPT - args_schema: type[BaseModel] | None = UniswapV3GetPoolSlot0Input - func: Callable[..., str] = uniswap_v3_get_pool_slot0 diff --git a/cdp-agentkit-core/cdp_agentkit_core/actions/wow/create_token.py b/cdp-agentkit-core/cdp_agentkit_core/actions/wow/create_token.py index ce7612e31..28403e038 100644 --- a/cdp-agentkit-core/cdp_agentkit_core/actions/wow/create_token.py +++ b/cdp-agentkit-core/cdp_agentkit_core/actions/wow/create_token.py @@ -11,7 +11,7 @@ ) WOW_CREATE_TOKEN_PROMPT = """ -This tool will create a Zora Wow ERC20 memecoin using the WoW factory. This tool takes the token name and token symbol. It is only supported on Base Sepolia and Base Mainnet. +This tool will create a Zora Wow ERC20 memecoin using the WoW factory. This tool takes the token name and token symbol. It uses a bonding curve so there is no need to add liquidity to the pool upfront. It is only supported on Base Sepolia and Base Mainnet. """ @@ -20,11 +20,11 @@ class WowCreateTokenInput(BaseModel): name: str = Field( ..., - description="The name of the token to create.", + description="The name of the token to create, e.g. WowCoin", ) symbol: str = Field( ..., - description="The symbol of the token to create.", + description="The symbol of the token to create, e.g. WOW", ) diff --git a/cdp-agentkit-core/tests/actions/test_deploy_nft.py b/cdp-agentkit-core/tests/actions/test_deploy_nft.py index 277ea7c9c..5333ef9f3 100644 --- a/cdp-agentkit-core/tests/actions/test_deploy_nft.py +++ b/cdp-agentkit-core/tests/actions/test_deploy_nft.py @@ -59,9 +59,10 @@ def test_deploy_nft_api_error(wallet_factory): mock_wallet = wallet_factory() with patch.object(mock_wallet, "deploy_nft", side_effect=Exception("API error")) as mock_deploy: - with pytest.raises(Exception, match="API error"): - deploy_nft(mock_wallet, MOCK_NAME, MOCK_SYMBOL, MOCK_BASE_URI) + action_response = deploy_nft(mock_wallet, MOCK_NAME, MOCK_SYMBOL, MOCK_BASE_URI) + expected_response = "Error deploying NFT API error" + assert action_response == expected_response mock_deploy.assert_called_once_with( name=MOCK_NAME, symbol=MOCK_SYMBOL, diff --git a/cdp-agentkit-core/tests/actions/test_deploy_token.py b/cdp-agentkit-core/tests/actions/test_deploy_token.py index 15b942464..4c1f3dde8 100644 --- a/cdp-agentkit-core/tests/actions/test_deploy_token.py +++ b/cdp-agentkit-core/tests/actions/test_deploy_token.py @@ -63,9 +63,11 @@ def test_deploy_token_api_error(wallet_factory): with patch.object( mock_wallet, "deploy_token", side_effect=Exception("API error") ) as mock_deploy: - with pytest.raises(Exception, match="API error"): - deploy_token(mock_wallet, MOCK_NAME, MOCK_SYMBOL, MOCK_TOTAL_SUPPLY) + action_response = deploy_token(mock_wallet, MOCK_NAME, MOCK_SYMBOL, MOCK_TOTAL_SUPPLY) + + expected_response = "Error deploying token API error" + assert action_response == expected_response mock_deploy.assert_called_once_with( name=MOCK_NAME, symbol=MOCK_SYMBOL, diff --git a/cdp-agentkit-core/tests/actions/test_mint_nft.py b/cdp-agentkit-core/tests/actions/test_mint_nft.py index 9bea4a5f3..e4fc6324d 100644 --- a/cdp-agentkit-core/tests/actions/test_mint_nft.py +++ b/cdp-agentkit-core/tests/actions/test_mint_nft.py @@ -60,9 +60,11 @@ def test_trade_api_error(wallet_factory): with patch.object( mock_wallet, "invoke_contract", side_effect=Exception("API error") ) as mock_invoke_contract: - with pytest.raises(Exception, match="API error"): - mint_nft(mock_wallet, MOCK_CONTRACT_ADDRESS, MOCK_DESTINATION) + action_response = mint_nft(mock_wallet, MOCK_CONTRACT_ADDRESS, MOCK_DESTINATION) + + expected_response = "Error minting NFT API error" + assert action_response == expected_response mock_invoke_contract.assert_called_once_with( contract_address=MOCK_CONTRACT_ADDRESS, method="mint", diff --git a/cdp-agentkit-core/tests/actions/test_trade.py b/cdp-agentkit-core/tests/actions/test_trade.py index 246c564cb..98d997d24 100644 --- a/cdp-agentkit-core/tests/actions/test_trade.py +++ b/cdp-agentkit-core/tests/actions/test_trade.py @@ -61,9 +61,11 @@ def test_trade_api_error(wallet_factory): mock_wallet = wallet_factory(network_id=MOCK_NETWORK_ID) with patch.object(mock_wallet, "trade", side_effect=Exception("API error")) as mock_trade: - with pytest.raises(Exception, match="API error"): - trade(mock_wallet, MOCK_AMOUNT, MOCK_FROM_ASSET_ID, MOCK_TO_ASSET_ID) + action_response = trade(mock_wallet, MOCK_AMOUNT, MOCK_FROM_ASSET_ID, MOCK_TO_ASSET_ID) + + expected_response = "Error trading assets API error" + assert action_response == expected_response mock_trade.assert_called_once_with( amount=MOCK_AMOUNT, from_asset_id=MOCK_FROM_ASSET_ID, diff --git a/cdp-agentkit-core/tests/actions/test_transfer.py b/cdp-agentkit-core/tests/actions/test_transfer.py index 506450938..892bc1152 100644 --- a/cdp-agentkit-core/tests/actions/test_transfer.py +++ b/cdp-agentkit-core/tests/actions/test_transfer.py @@ -65,9 +65,13 @@ def test_transfer_api_error(wallet_factory): mock_wallet = wallet_factory() with patch.object(mock_wallet, "transfer", side_effect=Exception("API error")) as mock_transfer: - with pytest.raises(Exception, match="API error"): - transfer(mock_wallet, MOCK_AMOUNT, MOCK_ASSET_ID, MOCK_DESTINATION, MOCK_GASLESS) + action_response = transfer( + mock_wallet, MOCK_AMOUNT, MOCK_ASSET_ID, MOCK_DESTINATION, MOCK_GASLESS + ) + expected_response = "Error transferring the asset API error" + + assert action_response == expected_response mock_transfer.assert_called_once_with( amount=MOCK_AMOUNT, asset_id=MOCK_ASSET_ID, diff --git a/cdp-agentkit-core/tests/actions/uniswap_v3/test_create_pool.py b/cdp-agentkit-core/tests/actions/uniswap_v3/test_create_pool.py deleted file mode 100644 index d57f0c1f2..000000000 --- a/cdp-agentkit-core/tests/actions/uniswap_v3/test_create_pool.py +++ /dev/null @@ -1,85 +0,0 @@ -from unittest.mock import patch - -import pytest - -from cdp_agentkit_core.actions.uniswap_v3.constants import UNISWAP_V3_FACTORY_ABI -from cdp_agentkit_core.actions.uniswap_v3.create_pool import ( - UniswapV3CreatePoolInput, - uniswap_v3_create_pool, -) - -MOCK_TOKEN_A = "0x4200000000000000000000000000000000000006" -MOCK_TOKEN_B = "0x1234567890123456789012345678901234567890" -MOCK_FEE = "3000" - - -def test_create_pool_input_model_valid(): - """Test that CreatePoolInput accepts valid parameters.""" - input_model = UniswapV3CreatePoolInput( - token_a=MOCK_TOKEN_A, - token_b=MOCK_TOKEN_B, - fee=MOCK_FEE, - ) - - assert input_model.token_a == MOCK_TOKEN_A - assert input_model.token_b == MOCK_TOKEN_B - assert input_model.fee == MOCK_FEE - - -def test_create_pool_input_model_missing_params(): - """Test that CreatePoolInput raises error when params are missing.""" - with pytest.raises(ValueError): - UniswapV3CreatePoolInput() - - -def test_create_pool_success(wallet_factory, contract_invocation_factory): - """Test successful pool creation with valid parameters.""" - mock_wallet = wallet_factory() - mock_contract_instance = contract_invocation_factory() - - 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 = uniswap_v3_create_pool(mock_wallet, MOCK_TOKEN_A, MOCK_TOKEN_B, MOCK_FEE) - - expected_response = f"Created pool for {MOCK_TOKEN_A} and {MOCK_TOKEN_B} with fee {MOCK_FEE} on network {mock_wallet.network_id}.\nTransaction hash for the pool creation: {mock_contract_instance.transaction.transaction_hash}\nTransaction link for the pool creation: {mock_contract_instance.transaction.transaction_link}" - assert action_response == expected_response - - mock_invoke.assert_called_once_with( - contract_address="0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24", - method="createPool", - abi=UNISWAP_V3_FACTORY_ABI, - args={ - "tokenA": MOCK_TOKEN_A, - "tokenB": MOCK_TOKEN_B, - "fee": MOCK_FEE, - }, - ) - mock_contract_wait.assert_called_once_with() - - -def test_create_pool_api_error(wallet_factory): - """Test create_pool when API error occurs.""" - mock_wallet = wallet_factory() - - with patch.object( - mock_wallet, "invoke_contract", side_effect=Exception("API error") - ) as mock_invoke: - with pytest.raises(Exception, match="API error"): - uniswap_v3_create_pool(mock_wallet, MOCK_TOKEN_A, MOCK_TOKEN_B, MOCK_FEE) - - mock_invoke.assert_called_once_with( - contract_address="0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24", - method="createPool", - abi=UNISWAP_V3_FACTORY_ABI, - args={ - "tokenA": MOCK_TOKEN_A, - "tokenB": MOCK_TOKEN_B, - "fee": MOCK_FEE, - }, - ) diff --git a/cdp-agentkit-core/tests/actions/uniswap_v3/test_get_pool_liquidity.py b/cdp-agentkit-core/tests/actions/uniswap_v3/test_get_pool_liquidity.py deleted file mode 100644 index cae13cd77..000000000 --- a/cdp-agentkit-core/tests/actions/uniswap_v3/test_get_pool_liquidity.py +++ /dev/null @@ -1,68 +0,0 @@ -from unittest.mock import patch - -import pytest - -from cdp_agentkit_core.actions.uniswap_v3.constants import UNISWAP_V3_POOL_ABI -from cdp_agentkit_core.actions.uniswap_v3.get_pool_liquidity import ( - UniswapV3GetPoolLiquidityInput, - uniswap_v3_get_pool_liquidity, -) - -MOCK_POOL_ADDRESS = "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24" -MOCK_NETWORK_ID = "base-sepolia" -MOCK_LIQUIDITY = "1000000000000000000" - - -def test_get_pool_liquidity_input_model_valid(): - """Test that GetPoolLiquidityInput accepts valid parameters.""" - input_model = UniswapV3GetPoolLiquidityInput( - network_id=MOCK_NETWORK_ID, - pool_contract_address=MOCK_POOL_ADDRESS, - ) - - assert input_model.network_id == MOCK_NETWORK_ID - assert input_model.pool_contract_address == MOCK_POOL_ADDRESS - - -def test_get_pool_liquidity_input_model_missing_params(): - """Test that GetPoolLiquidityInput raises error when params are missing.""" - with pytest.raises(ValueError): - UniswapV3GetPoolLiquidityInput() - - -def test_get_pool_liquidity_success(): - """Test successful liquidity retrieval with valid parameters.""" - with patch( - "cdp_agentkit_core.actions.uniswap_v3.get_pool_liquidity.SmartContract.read", - return_value=MOCK_LIQUIDITY, - ) as mock_read: - response = uniswap_v3_get_pool_liquidity(MOCK_NETWORK_ID, MOCK_POOL_ADDRESS) - - expected_response = f"Liquidity for pool {MOCK_POOL_ADDRESS} is {MOCK_LIQUIDITY}." - assert response == expected_response - - mock_read.assert_called_once_with( - network_id=MOCK_NETWORK_ID, - contract_address=MOCK_POOL_ADDRESS, - method="liquidity", - abi=UNISWAP_V3_POOL_ABI, - args={}, - ) - - -def test_get_pool_liquidity_api_error(): - """Test get_pool_liquidity when API error occurs.""" - with patch( - "cdp_agentkit_core.actions.uniswap_v3.get_pool_liquidity.SmartContract.read", - side_effect=Exception("API error"), - ) as mock_read: - with pytest.raises(Exception, match="API error"): - uniswap_v3_get_pool_liquidity(MOCK_NETWORK_ID, MOCK_POOL_ADDRESS) - - mock_read.assert_called_once_with( - network_id=MOCK_NETWORK_ID, - contract_address=MOCK_POOL_ADDRESS, - method="liquidity", - abi=UNISWAP_V3_POOL_ABI, - args={}, - ) diff --git a/cdp-agentkit-core/tests/actions/uniswap_v3/test_get_pool_observe.py b/cdp-agentkit-core/tests/actions/uniswap_v3/test_get_pool_observe.py deleted file mode 100644 index e15f8c7ba..000000000 --- a/cdp-agentkit-core/tests/actions/uniswap_v3/test_get_pool_observe.py +++ /dev/null @@ -1,74 +0,0 @@ -from unittest.mock import patch - -import pytest - -from cdp_agentkit_core.actions.uniswap_v3.constants import UNISWAP_V3_POOL_ABI -from cdp_agentkit_core.actions.uniswap_v3.get_pool_observe import ( - UniswapV3GetPoolObserveInput, - uniswap_v3_get_pool_observe, -) - -MOCK_POOL_ADDRESS = "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24" -MOCK_NETWORK_ID = "base-sepolia" -MOCK_SECONDS_AGO = ["60", "120"] -MOCK_OBSERVATIONS = ( - ["1000000", "2000000"], # tickCumulatives - ["500000", "1000000"], # secondsPerLiquidityCumulativeX128s -) - - -def test_get_pool_observe_input_model_valid(): - """Test that GetPoolObserveInput accepts valid parameters.""" - input_model = UniswapV3GetPoolObserveInput( - network_id=MOCK_NETWORK_ID, - pool_contract_address=MOCK_POOL_ADDRESS, - seconds_ago=MOCK_SECONDS_AGO, - ) - - assert input_model.network_id == MOCK_NETWORK_ID - assert input_model.pool_contract_address == MOCK_POOL_ADDRESS - assert input_model.seconds_ago == MOCK_SECONDS_AGO - - -def test_get_pool_observe_input_model_missing_params(): - """Test that GetPoolObserveInput raises error when params are missing.""" - with pytest.raises(ValueError): - UniswapV3GetPoolObserveInput() - - -def test_get_pool_observe_success(): - """Test successful observation retrieval with valid parameters.""" - with patch( - "cdp_agentkit_core.actions.uniswap_v3.get_pool_observe.SmartContract.read", - return_value=MOCK_OBSERVATIONS, - ) as mock_read: - response = uniswap_v3_get_pool_observe(MOCK_NETWORK_ID, MOCK_POOL_ADDRESS, MOCK_SECONDS_AGO) - - expected_response = f"Observations for pool {MOCK_POOL_ADDRESS} are {MOCK_OBSERVATIONS}." - assert response == expected_response - - mock_read.assert_called_once_with( - network_id=MOCK_NETWORK_ID, - contract_address=MOCK_POOL_ADDRESS, - method="observe", - abi=UNISWAP_V3_POOL_ABI, - args={"secondsAgos": MOCK_SECONDS_AGO}, - ) - - -def test_get_pool_observe_api_error(): - """Test get_pool_observe when API error occurs.""" - with patch( - "cdp_agentkit_core.actions.uniswap_v3.get_pool_observe.SmartContract.read", - side_effect=Exception("API error"), - ) as mock_read: - with pytest.raises(Exception, match="API error"): - uniswap_v3_get_pool_observe(MOCK_NETWORK_ID, MOCK_POOL_ADDRESS, MOCK_SECONDS_AGO) - - mock_read.assert_called_once_with( - network_id=MOCK_NETWORK_ID, - contract_address=MOCK_POOL_ADDRESS, - method="observe", - abi=UNISWAP_V3_POOL_ABI, - args={"secondsAgos": MOCK_SECONDS_AGO}, - ) diff --git a/cdp-agentkit-core/tests/actions/uniswap_v3/test_get_pool_slot0.py b/cdp-agentkit-core/tests/actions/uniswap_v3/test_get_pool_slot0.py deleted file mode 100644 index f30beea9b..000000000 --- a/cdp-agentkit-core/tests/actions/uniswap_v3/test_get_pool_slot0.py +++ /dev/null @@ -1,76 +0,0 @@ -from unittest.mock import patch - -import pytest - -from cdp_agentkit_core.actions.uniswap_v3.constants import UNISWAP_V3_POOL_ABI -from cdp_agentkit_core.actions.uniswap_v3.get_pool_slot0 import ( - UniswapV3GetPoolSlot0Input, - uniswap_v3_get_pool_slot0, -) - -MOCK_POOL_ADDRESS = "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24" -MOCK_NETWORK_ID = "base-sepolia" -MOCK_SLOT0_RESPONSE = ( - "1234567890", # sqrtPriceX96 - "100", # tick - "1", # observationIndex - "50", # observationCardinality - "100", # observationCardinalityNext - "0", # feeProtocol - True, # unlocked -) - - -def test_get_pool_slot0_input_model_valid(): - """Test that GetPoolSlot0Input accepts valid parameters.""" - input_model = UniswapV3GetPoolSlot0Input( - network_id=MOCK_NETWORK_ID, - pool_contract_address=MOCK_POOL_ADDRESS, - ) - - assert input_model.network_id == MOCK_NETWORK_ID - assert input_model.pool_contract_address == MOCK_POOL_ADDRESS - - -def test_get_pool_slot0_input_model_missing_params(): - """Test that GetPoolSlot0Input raises error when params are missing.""" - with pytest.raises(ValueError): - UniswapV3GetPoolSlot0Input() - - -def test_get_pool_slot0_success(): - """Test successful slot0 retrieval with valid parameters.""" - with patch( - "cdp_agentkit_core.actions.uniswap_v3.get_pool_slot0.SmartContract.read", - return_value=MOCK_SLOT0_RESPONSE, - ) as mock_read: - response = uniswap_v3_get_pool_slot0(MOCK_NETWORK_ID, MOCK_POOL_ADDRESS) - - expected_response = f"Slot0 for pool {MOCK_POOL_ADDRESS} is {MOCK_SLOT0_RESPONSE}." - assert response == expected_response - - mock_read.assert_called_once_with( - network_id=MOCK_NETWORK_ID, - contract_address=MOCK_POOL_ADDRESS, - method="slot0", - abi=UNISWAP_V3_POOL_ABI, - args={}, - ) - - -def test_get_pool_slot0_api_error(): - """Test get_pool_slot0 when API error occurs.""" - with patch( - "cdp_agentkit_core.actions.uniswap_v3.get_pool_slot0.SmartContract.read", - side_effect=Exception("API error"), - ) as mock_read: - with pytest.raises(Exception, match="API error"): - uniswap_v3_get_pool_slot0(MOCK_NETWORK_ID, MOCK_POOL_ADDRESS) - - mock_read.assert_called_once_with( - network_id=MOCK_NETWORK_ID, - contract_address=MOCK_POOL_ADDRESS, - method="slot0", - abi=UNISWAP_V3_POOL_ABI, - args={}, - ) diff --git a/cdp-langchain/CHANGELOG.md b/cdp-langchain/CHANGELOG.md index 998e9616a..9f8cb2a98 100644 --- a/cdp-langchain/CHANGELOG.md +++ b/cdp-langchain/CHANGELOG.md @@ -4,9 +4,8 @@ ### Added -- Added `uniswap_v3_create_pool` action to the cdp toolkit. -- Added `uniswap_v3_get_pool`, `uniswap_v3_get_pool_observe`, `uniswap_v3_get_pool_slot0`, and `uniswap_v3_get_pool_liquidity` actions to the cdp toolkit. - Added `wow_create_token` action to the cdp toolkit. + ## [0.0.1] - 2024-11-04 ### Added diff --git a/cdp-langchain/cdp_langchain/__init__.py b/cdp-langchain/cdp_langchain/__init__.py index 8b1378917..40cfa16b9 100644 --- a/cdp-langchain/cdp_langchain/__init__.py +++ b/cdp-langchain/cdp_langchain/__init__.py @@ -1 +1,3 @@ +from cdp_langchain.__version__ import __version__ +__all__ = ["__version__"] diff --git a/cdp-langchain/cdp_langchain/__version__.py b/cdp-langchain/cdp_langchain/__version__.py new file mode 100644 index 000000000..f102a9cad --- /dev/null +++ b/cdp-langchain/cdp_langchain/__version__.py @@ -0,0 +1 @@ +__version__ = "0.0.1" diff --git a/cdp-langchain/cdp_langchain/agent_toolkits/cdp_toolkit.py b/cdp-langchain/cdp_langchain/agent_toolkits/cdp_toolkit.py index dd24148cc..3737da1a1 100644 --- a/cdp-langchain/cdp_langchain/agent_toolkits/cdp_toolkit.py +++ b/cdp-langchain/cdp_langchain/agent_toolkits/cdp_toolkit.py @@ -60,11 +60,7 @@ class CdpToolkit(BaseToolkit): mint_nft deploy_nft register_basename - uniswap_v3_create_pool - uniswap_v3_get_pool - uniswap_v3_get_pool_observe - uniswap_v3_get_pool_slot0 - uniswap_v3_get_pool_liquidity + wow_create_token Use within an agent: .. code-block:: python diff --git a/cdp-langchain/cdp_langchain/constants.py b/cdp-langchain/cdp_langchain/constants.py new file mode 100644 index 000000000..c3b1c3dd2 --- /dev/null +++ b/cdp-langchain/cdp_langchain/constants.py @@ -0,0 +1,4 @@ +"""Specifies package level constants used throughout the package.""" + +# CDP_LANGCHAIN_DEFAULT_SOURCE (str): Denotes the default source for CDP Langchain Agentkit extensions. +CDP_LANGCHAIN_DEFAULT_SOURCE = "cdp-langchain" diff --git a/cdp-langchain/cdp_langchain/utils/cdp_agentkit_wrapper.py b/cdp-langchain/cdp_langchain/utils/cdp_agentkit_wrapper.py index f4f6dfbff..c15555bcd 100644 --- a/cdp-langchain/cdp_langchain/utils/cdp_agentkit_wrapper.py +++ b/cdp-langchain/cdp_langchain/utils/cdp_agentkit_wrapper.py @@ -9,6 +9,8 @@ from pydantic import BaseModel, model_validator from cdp import Wallet +from cdp_langchain import __version__ +from cdp_langchain.constants import CDP_LANGCHAIN_DEFAULT_SOURCE class CdpAgentkitWrapper(BaseModel): @@ -37,7 +39,12 @@ def validate_environment(cls, values: dict) -> Any: "CDP SDK is not installed. " "Please install it with `pip install cdp-sdk`" ) from None - Cdp.configure(cdp_api_key_name, cdp_api_key_private_key) + Cdp.configure( + api_key_name=cdp_api_key_name, + private_key=cdp_api_key_private_key, + source=CDP_LANGCHAIN_DEFAULT_SOURCE, + source_version=__version__, + ) if wallet_data_json: wallet_data = WalletData.from_dict(json.loads(wallet_data_json)) diff --git a/cdp-langchain/tests/utils/test_cdp_agentkit_wrapper.py b/cdp-langchain/tests/utils/test_cdp_agentkit_wrapper.py index 6dc92b655..9820aefd2 100644 --- a/cdp-langchain/tests/utils/test_cdp_agentkit_wrapper.py +++ b/cdp-langchain/tests/utils/test_cdp_agentkit_wrapper.py @@ -7,6 +7,8 @@ from pydantic import ValidationError from cdp import Cdp, Wallet, WalletData +from cdp_langchain import __version__ +from cdp_langchain.constants import CDP_LANGCHAIN_DEFAULT_SOURCE from cdp_langchain.utils import CdpAgentkitWrapper @@ -62,7 +64,10 @@ def test_initialization_with_env_vars( assert wrapper.wallet is not None mock_cdp_configure.assert_called_once_with( - env_vars["CDP_API_KEY_NAME"], env_vars["CDP_API_KEY_PRIVATE_KEY"] + api_key_name=env_vars["CDP_API_KEY_NAME"], + private_key=env_vars["CDP_API_KEY_PRIVATE_KEY"], + source=CDP_LANGCHAIN_DEFAULT_SOURCE, + source_version=__version__, ) mock_wallet_create.assert_called_once_with(network_id=env_vars["NETWORK_ID"]) @@ -83,7 +88,10 @@ def test_initialization_with_direct_values(mock_cdp_configure: Mock, mock_wallet assert wrapper.network_id == test_values["network_id"] mock_cdp_configure.assert_called_once_with( - test_values["cdp_api_key_name"], test_values["cdp_api_key_private_key"] + api_key_name=test_values["cdp_api_key_name"], + private_key=test_values["cdp_api_key_private_key"], + source=CDP_LANGCHAIN_DEFAULT_SOURCE, + source_version=__version__, ) mock_wallet_create.assert_called_once_with(network_id=test_values["network_id"]) @@ -110,7 +118,10 @@ def test_initialization_with_direct_values_and_persisted_wallet( assert wrapper.network_id == test_values["network_id"] mock_cdp_configure.assert_called_once_with( - test_values["cdp_api_key_name"], test_values["cdp_api_key_private_key"] + api_key_name=test_values["cdp_api_key_name"], + private_key=test_values["cdp_api_key_private_key"], + source=CDP_LANGCHAIN_DEFAULT_SOURCE, + source_version=__version__, ) mock_wallet_import_data.assert_called_once()