From 18f6016a70f609daecbab5fa71ac08b4c7d05cbd Mon Sep 17 00:00:00 2001 From: Darryl Sladden Date: Tue, 24 Feb 2026 19:29:23 -0800 Subject: [PATCH 1/5] Fix asyncio event loop conflicts in CdpEvmWalletProvider - Replace asyncio.run() calls in __init__ with _run_async() helper - Improve _run_async() to detect existing event loops and handle them properly - Run coroutines in separate thread when event loop already exists - Prevents misleading ETIMEDOUT errors when real issue is asyncio conflict - Fixes compatibility with Jupyter notebooks, web frameworks, and agent systems Fixes #967 --- .../cdp_evm_wallet_provider.py | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_evm_wallet_provider.py b/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_evm_wallet_provider.py index 37ad760b1..3bf99a16a 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_evm_wallet_provider.py +++ b/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_evm_wallet_provider.py @@ -66,9 +66,9 @@ def __init__(self, config: CdpEvmWalletProviderConfig): client = self.get_client() if config.address: - account = asyncio.run(self._get_account(client, config.address)) + account = self._run_async(self._get_account(client, config.address)) else: - account = asyncio.run(self._create_account(client)) + account = self._run_async(self._create_account(client)) self._account = account @@ -366,8 +366,30 @@ def _run_async(self, coroutine): """ try: - loop = asyncio.get_event_loop() + # Check if we're in an existing event loop + loop = asyncio.get_running_loop() + # If we reach this point, there's already a running event loop + # We need to run the coroutine in a new thread with a new event loop + import concurrent.futures + import threading + + def run_in_thread(): + new_loop = asyncio.new_event_loop() + asyncio.set_event_loop(new_loop) + try: + return new_loop.run_until_complete(coroutine) + finally: + new_loop.close() + + with concurrent.futures.ThreadPoolExecutor() as executor: + future = executor.submit(run_in_thread) + return future.result() + except RuntimeError: + # No running event loop, safe to create and use a new one loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - return loop.run_until_complete(coroutine) + try: + return loop.run_until_complete(coroutine) + finally: + loop.close() From 2322f9ee1893f43d3db46dfbecd6a0a4bdc66cf7 Mon Sep 17 00:00:00 2001 From: Darryl Sladden Date: Wed, 25 Feb 2026 21:47:07 -0800 Subject: [PATCH 2/5] Fix asyncio event loop conflicts in CdpSmartWalletProvider and CdpSolanaWalletProvider; add changelog entry --- .../changelog.d/968.bugfix.md | 1 + .../cdp_smart_wallet_provider.py | 29 ++++++++++++++++--- .../cdp_solana_wallet_provider.py | 29 ++++++++++++++++--- 3 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 python/coinbase-agentkit/changelog.d/968.bugfix.md diff --git a/python/coinbase-agentkit/changelog.d/968.bugfix.md b/python/coinbase-agentkit/changelog.d/968.bugfix.md new file mode 100644 index 000000000..e65af34af --- /dev/null +++ b/python/coinbase-agentkit/changelog.d/968.bugfix.md @@ -0,0 +1 @@ +Fixed asyncio event loop conflicts in CdpEvmWalletProvider, CdpSmartWalletProvider, and CdpSolanaWalletProvider when used within existing async contexts (e.g., Jupyter notebooks, async frameworks) diff --git a/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_smart_wallet_provider.py b/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_smart_wallet_provider.py index ad2c2160d..0089b50f6 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_smart_wallet_provider.py +++ b/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_smart_wallet_provider.py @@ -96,12 +96,12 @@ async def initialize_accounts(): smart_account = await cdp.evm.create_smart_account(owner=owner) return owner, smart_account - owner, smart_account = asyncio.run(initialize_accounts()) + owner, smart_account = self._run_async(initialize_accounts()) self._address = smart_account.address self._owner = owner finally: - asyncio.run(client.close()) + self._run_async(client.close()) self._gas_limit_multiplier = ( max(config.gas.gas_limit_multiplier, 1) @@ -171,11 +171,32 @@ def _run_async(self, coroutine): """ try: - loop = asyncio.get_event_loop() + # Check if we're in an existing event loop + loop = asyncio.get_running_loop() + # If we reach this point, there's already a running event loop + # We need to run the coroutine in a new thread with a new event loop + import concurrent.futures + + def run_in_thread(): + new_loop = asyncio.new_event_loop() + asyncio.set_event_loop(new_loop) + try: + return new_loop.run_until_complete(coroutine) + finally: + new_loop.close() + + with concurrent.futures.ThreadPoolExecutor() as executor: + future = executor.submit(run_in_thread) + return future.result() + except RuntimeError: + # No running event loop, safe to create and use a new one loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - return loop.run_until_complete(coroutine) + try: + return loop.run_until_complete(coroutine) + finally: + loop.close() async def _get_smart_account(self, cdp): """Get the smart account, handling server wallet owners differently. diff --git a/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_solana_wallet_provider.py b/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_solana_wallet_provider.py index 38f36901d..88693b43b 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_solana_wallet_provider.py +++ b/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_solana_wallet_provider.py @@ -76,11 +76,11 @@ async def initialize_wallet(): wallet = await cdp.solana.create_account() return wallet - wallet = asyncio.run(initialize_wallet()) + wallet = self._run_async(initialize_wallet()) self._address = wallet.address finally: - asyncio.run(client.close()) + self._run_async(client.close()) except ImportError as e: raise ImportError( @@ -113,11 +113,32 @@ def _run_async(self, coroutine): """ try: - loop = asyncio.get_event_loop() + # Check if we're in an existing event loop + loop = asyncio.get_running_loop() + # If we reach this point, there's already a running event loop + # We need to run the coroutine in a new thread with a new event loop + import concurrent.futures + + def run_in_thread(): + new_loop = asyncio.new_event_loop() + asyncio.set_event_loop(new_loop) + try: + return new_loop.run_until_complete(coroutine) + finally: + new_loop.close() + + with concurrent.futures.ThreadPoolExecutor() as executor: + future = executor.submit(run_in_thread) + return future.result() + except RuntimeError: + # No running event loop, safe to create and use a new one loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - return loop.run_until_complete(coroutine) + try: + return loop.run_until_complete(coroutine) + finally: + loop.close() def get_address(self) -> str: """Get the wallet address. From 2e6c79e17f15e944223e5617737c95bd9bcfe2c1 Mon Sep 17 00:00:00 2001 From: Darryl Sladden Date: Wed, 25 Feb 2026 23:20:56 -0800 Subject: [PATCH 3/5] Update test mocks to use _run_async instead of asyncio.run --- .../cdp_evm_server_wallet_provider/conftest.py | 2 +- .../test_initialization.py | 10 +++++----- .../cdp_evm_smart_wallet_provider/conftest.py | 7 ++++++- .../test_initialization.py | 11 ++++++----- .../cdp_solana_wallet_provider/conftest.py | 12 ++++++++++-- .../test_basic_methods.py | 2 +- .../test_error_handling.py | 14 +++++++------- .../test_initialization.py | 18 +++++++++--------- .../cdp_solana_wallet_provider/test_signing.py | 17 +++++++++-------- .../test_solana_specific.py | 8 ++++---- .../test_transactions.py | 17 +++++++++-------- 11 files changed, 67 insertions(+), 51 deletions(-) diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/conftest.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/conftest.py index e552640b7..bcd12ba93 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/conftest.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/conftest.py @@ -136,7 +136,7 @@ def mocked_wallet_provider(mock_cdp_client, mock_account, mock_web3, mock_wallet ) # Patch the async run to return the mock account directly - with patch("asyncio.run", return_value=mock_account): + with patch.object(CdpEvmWalletProvider, "_run_async", return_value=mock_account): provider = CdpEvmWalletProvider(config) # Manually set account and wallet attributes diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/test_initialization.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/test_initialization.py index 67fa6242f..cc8c753cb 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/test_initialization.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/test_initialization.py @@ -25,7 +25,7 @@ def test_init_with_config(mock_cdp_client, mock_account): """Test initialization with config.""" - with patch("asyncio.run") as mock_run: + with patch.object(CdpEvmWalletProvider, "_run_async") as mock_run: mock_run.return_value = mock_account config = CdpEvmWalletProviderConfig( @@ -44,7 +44,7 @@ def test_init_with_config(mock_cdp_client, mock_account): def test_init_with_env_vars(mock_cdp_client, mock_account): """Test initialization with environment variables.""" with ( - patch("asyncio.run") as mock_run, + patch.object(CdpEvmWalletProvider, "_run_async") as mock_run, patch.dict( os.environ, { @@ -66,7 +66,7 @@ def test_init_with_env_vars(mock_cdp_client, mock_account): def test_init_with_default_network(mock_cdp_client, mock_account): """Test initialization with default network when no network ID is provided.""" with ( - patch("asyncio.run") as mock_run, + patch.object(CdpEvmWalletProvider, "_run_async") as mock_run, patch( "os.getenv", side_effect=lambda key, default=None: "base-sepolia" if key == "NETWORK_ID" else None, @@ -99,7 +99,7 @@ def test_init_with_missing_credentials(): def test_init_with_invalid_network(mock_cdp_client): """Test initialization with invalid network.""" # Use a known invalid network ID - with patch("asyncio.run", side_effect=ValueError("Invalid network ID")): + with patch.object(CdpEvmWalletProvider, "_run_async", side_effect=ValueError("Invalid network ID")): config = CdpEvmWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, api_key_secret=MOCK_API_KEY_SECRET, @@ -113,7 +113,7 @@ def test_init_with_invalid_network(mock_cdp_client): def test_init_with_account_creation_error(mock_cdp_client): """Test initialization when account creation fails.""" - with patch("asyncio.run", side_effect=Exception("Failed to create account")): + with patch.object(CdpEvmWalletProvider, "_run_async", side_effect=Exception("Failed to create account")): config = CdpEvmWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, api_key_secret=MOCK_API_KEY_SECRET, diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_smart_wallet_provider/conftest.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_smart_wallet_provider/conftest.py index d7bf80ce2..0eafcdb1e 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_smart_wallet_provider/conftest.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_smart_wallet_provider/conftest.py @@ -114,7 +114,7 @@ def mock_asyncio(): # Create a side effect for asyncio.run that handles the initialization coroutine def run_side_effect(coro): # Special handling for the initialization_accounts coroutine - if coro.__name__ == "initialize_accounts": + if hasattr(coro, "__name__") and coro.__name__ == "initialize_accounts": # Return a tuple of mock owner and smart account mock_owner = Mock(spec=Account) mock_owner.address = "0x123456789012345678901234567890123456789012" @@ -127,7 +127,12 @@ def run_side_effect(coro): return None mock_asyncio.run = Mock(side_effect=run_side_effect) + + # Also patch _run_async on the class so __init__ works with our mocks + original_run_async = CdpSmartWalletProvider._run_async + CdpSmartWalletProvider._run_async = lambda self, coro: run_side_effect(coro) yield mock_asyncio + CdpSmartWalletProvider._run_async = original_run_async @pytest.fixture diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_smart_wallet_provider/test_initialization.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_smart_wallet_provider/test_initialization.py index e73057fa0..ee6dc9973 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_smart_wallet_provider/test_initialization.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_smart_wallet_provider/test_initialization.py @@ -124,13 +124,14 @@ def test_init_with_private_key_owner(mock_cdp_client, mock_asyncio, mock_network ) as mock_account_class: mock_account_class.from_key.return_value = mock_owner - # Update mock_asyncio.run to return a tuple with the owner and smart_account for initialization - def run_side_effect(coro): - if coro.__name__ == "initialize_accounts": + # Update _run_async to return the right values for initialization + def run_async_side_effect(self, coro): + if hasattr(coro, "__name__") and coro.__name__ == "initialize_accounts": return (mock_owner, mock_smart_account) return None - mock_asyncio.run.side_effect = run_side_effect + # Patch _run_async on the class for this test + CdpSmartWalletProvider._run_async = run_async_side_effect async def create_smart_account_mock(*args, **kwargs): return mock_smart_account @@ -147,7 +148,7 @@ async def create_smart_account_mock(*args, **kwargs): provider = CdpSmartWalletProvider(config) - # Don't check if from_key was called, since we're mocking asyncio.run + # Don't check if from_key was called, since we're mocking _run_async # We only care that the provider was initialized correctly assert provider.get_address() == MOCK_ADDRESS assert provider._owner == mock_owner diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/conftest.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/conftest.py index 18177be79..b56da635e 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/conftest.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/conftest.py @@ -120,9 +120,17 @@ def mocked_wallet_provider(mock_cdp_client, mock_solana_client, mock_public_key) network_id=MOCK_NETWORK_ID, ) - # Patch asyncio.run to return the mock account + # Patch _run_async to handle initialization coroutines synchronously mock_account = Mock(address=MOCK_ADDRESS) - with patch("asyncio.run", return_value=mock_account): + + def mock_run_async(self, coro): + # For initialize_wallet, return the mock account + if hasattr(coro, "__name__") and coro.__name__ == "initialize_wallet": + return mock_account + # For client.close, just return None + return None + + with patch.object(CdpSolanaWalletProvider, "_run_async", mock_run_async): provider = CdpSolanaWalletProvider(config) yield provider diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_basic_methods.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_basic_methods.py index 70e65c880..1c7f5d2d5 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_basic_methods.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_basic_methods.py @@ -92,7 +92,7 @@ def test_get_network_different_networks(): with ( patch("coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider.CdpClient"), patch("coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider.SolanaClient"), - patch("asyncio.run", return_value=Mock(address=MOCK_ADDRESS)), + patch.object(CdpSolanaWalletProvider, "_run_async", return_value=Mock(address=MOCK_ADDRESS)), ): config = CdpSolanaWalletProviderConfig( api_key_id="test_key", diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py index 43bcd0352..3cec5bfd1 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py @@ -23,7 +23,7 @@ async def raise_connection_error(*args, **kwargs): mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) with ( - patch("asyncio.run", side_effect=ConnectionError(error_msg)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=ConnectionError(error_msg)), pytest.raises(ConnectionError, match=error_msg), ): mocked_wallet_provider.native_transfer("SomeAddress", Decimal("0.5")) @@ -32,7 +32,7 @@ async def raise_connection_error(*args, **kwargs): mock_cdp_client.solana.sign_message = raise_connection_error with ( - patch("asyncio.run", side_effect=ConnectionError(error_msg)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=ConnectionError(error_msg)), pytest.raises(ConnectionError, match=error_msg), ): mocked_wallet_provider.sign_message("test message") @@ -51,7 +51,7 @@ async def raise_value_error(*args, **kwargs): mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) with ( - patch("asyncio.run", side_effect=ValueError(address_error)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=ValueError(address_error)), pytest.raises(ValueError, match=address_error), ): mocked_wallet_provider.native_transfer("invalid_address", Decimal("1.0")) @@ -75,7 +75,7 @@ async def raise_auth_error(*args, **kwargs): mock_cdp_client.solana.get_account = raise_auth_error with ( - patch("asyncio.run", side_effect=Exception(auth_error)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=Exception(auth_error)), pytest.raises(Exception, match=auth_error), ): mocked_wallet_provider.native_transfer("SomeAddress", Decimal("1.0")) @@ -85,7 +85,7 @@ async def raise_auth_error(*args, **kwargs): mock_cdp_client.solana.sign_message = AsyncMock(side_effect=Exception(rate_limit_error)) with ( - patch("asyncio.run", side_effect=Exception(rate_limit_error)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=Exception(rate_limit_error)), pytest.raises(Exception, match=rate_limit_error), ): mocked_wallet_provider.sign_message("test") @@ -104,7 +104,7 @@ async def raise_balance_error(*args, **kwargs): mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) with ( - patch("asyncio.run", side_effect=Exception(balance_error)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=Exception(balance_error)), pytest.raises(Exception, match=balance_error), ): mocked_wallet_provider.native_transfer("SomeAddress", Decimal("1000000")) @@ -118,7 +118,7 @@ async def raise_timeout(*args, **kwargs): mock_wallet.transfer = raise_timeout with ( - patch("asyncio.run", side_effect=TimeoutError(timeout_error)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=TimeoutError(timeout_error)), pytest.raises(TimeoutError, match=timeout_error), ): mocked_wallet_provider.native_transfer("SomeAddress", Decimal("1.0")) diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_initialization.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_initialization.py index 2d50fec18..554350129 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_initialization.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_initialization.py @@ -26,7 +26,7 @@ def test_init_with_config(mock_cdp_client, mock_solana_client, mock_public_key): """Test initialization with config.""" mock_account = Mock(address=MOCK_ADDRESS) - with patch("asyncio.run", return_value=mock_account): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=mock_account): config = CdpSolanaWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, api_key_secret=MOCK_API_KEY_SECRET, @@ -44,7 +44,7 @@ def test_init_with_env_vars(mock_cdp_client, mock_solana_client, mock_public_key """Test initialization with environment variables.""" mock_account = Mock(address=MOCK_ADDRESS) with ( - patch("asyncio.run", return_value=mock_account), + patch.object(CdpSolanaWalletProvider, "_run_async", return_value=mock_account), patch.dict( os.environ, { @@ -65,7 +65,7 @@ def test_init_with_default_network(mock_cdp_client, mock_solana_client, mock_pub """Test initialization with default network when no network ID is provided.""" mock_account = Mock(address=MOCK_ADDRESS) with ( - patch("asyncio.run", return_value=mock_account), + patch.object(CdpSolanaWalletProvider, "_run_async", return_value=mock_account), patch( "os.getenv", side_effect=lambda key, default=None: "solana-devnet" if key == "NETWORK_ID" else None, @@ -99,8 +99,8 @@ async def mock_init_wallet(): # Configure the mocks mock_cdp_client.solana.get_account.return_value = mock_account - with patch("asyncio.run") as mock_run: - # Make asyncio.run call our async function and return the account + with patch.object(CdpSolanaWalletProvider, "_run_async") as mock_run: + # Make _run_async return the account directly mock_run.side_effect = lambda coro: mock_account config = CdpSolanaWalletProviderConfig( @@ -114,14 +114,14 @@ async def mock_init_wallet(): provider = CdpSolanaWalletProvider(config) assert provider.get_address() == existing_address - # The asyncio.run was called once during initialization + # The _run_async was called once during initialization assert mock_run.called def test_init_with_mainnet(mock_cdp_client, mock_solana_client, mock_public_key): """Test initialization with mainnet configuration.""" mock_account = Mock(address=MOCK_ADDRESS) - with patch("asyncio.run", return_value=mock_account): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=mock_account): config = CdpSolanaWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, api_key_secret=MOCK_API_KEY_SECRET, @@ -138,7 +138,7 @@ def test_init_with_mainnet(mock_cdp_client, mock_solana_client, mock_public_key) def test_init_with_testnet(mock_cdp_client, mock_solana_client, mock_public_key): """Test initialization with testnet configuration.""" mock_account = Mock(address=MOCK_ADDRESS) - with patch("asyncio.run", return_value=mock_account): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=mock_account): config = CdpSolanaWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, api_key_secret=MOCK_API_KEY_SECRET, @@ -179,7 +179,7 @@ def test_init_with_cdp_import_error(): def test_init_with_account_creation_error(mock_cdp_client, mock_solana_client, mock_public_key): """Test initialization when account creation fails.""" - with patch("asyncio.run", side_effect=Exception("Failed to create account")): + with patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=Exception("Failed to create account")): config = CdpSolanaWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, api_key_secret=MOCK_API_KEY_SECRET, diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_signing.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_signing.py index 533c8b6e8..60dcd6774 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_signing.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_signing.py @@ -4,6 +4,7 @@ import pytest +from coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider import CdpSolanaWalletProvider from .conftest import MOCK_SIGNATURE # ========================================================= @@ -18,7 +19,7 @@ def test_sign_message(mocked_wallet_provider, mock_cdp_client): # Configure the mock to return signature mock_cdp_client.solana.sign_message = AsyncMock(return_value=MOCK_SIGNATURE) - with patch("asyncio.run", return_value=MOCK_SIGNATURE): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_SIGNATURE): signature = mocked_wallet_provider.sign_message(message) assert signature == MOCK_SIGNATURE @@ -31,7 +32,7 @@ def test_sign_message_binary(mocked_wallet_provider, mock_cdp_client): # Configure the mock to return signature mock_cdp_client.solana.sign_message = AsyncMock(return_value=MOCK_SIGNATURE) - with patch("asyncio.run", return_value=MOCK_SIGNATURE): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_SIGNATURE): signature = mocked_wallet_provider.sign_message(binary_message) assert signature == MOCK_SIGNATURE @@ -44,7 +45,7 @@ def test_sign_message_empty(mocked_wallet_provider, mock_cdp_client): # Configure the mock to return signature mock_cdp_client.solana.sign_message = AsyncMock(return_value=MOCK_SIGNATURE) - with patch("asyncio.run", return_value=MOCK_SIGNATURE): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_SIGNATURE): signature = mocked_wallet_provider.sign_message(message) assert signature == MOCK_SIGNATURE @@ -57,7 +58,7 @@ def test_sign_message_long(mocked_wallet_provider, mock_cdp_client): # Configure the mock to return signature mock_cdp_client.solana.sign_message = AsyncMock(return_value=MOCK_SIGNATURE) - with patch("asyncio.run", return_value=MOCK_SIGNATURE): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_SIGNATURE): signature = mocked_wallet_provider.sign_message(message) assert signature == MOCK_SIGNATURE @@ -75,7 +76,7 @@ async def raise_error(*args, **kwargs): mock_cdp_client.solana.sign_message = raise_error with ( - patch("asyncio.run", side_effect=Exception(error_msg)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=Exception(error_msg)), pytest.raises(Exception, match=error_msg), ): mocked_wallet_provider.sign_message(message) @@ -93,7 +94,7 @@ async def raise_connection_error(*args, **kwargs): mock_cdp_client.solana.sign_message = raise_connection_error with ( - patch("asyncio.run", side_effect=ConnectionError(error_msg)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=ConnectionError(error_msg)), pytest.raises(ConnectionError, match=error_msg), ): mocked_wallet_provider.sign_message(message) @@ -111,7 +112,7 @@ async def raise_timeout_error(*args, **kwargs): mock_cdp_client.solana.sign_message = raise_timeout_error with ( - patch("asyncio.run", side_effect=TimeoutError(error_msg)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=TimeoutError(error_msg)), pytest.raises(TimeoutError, match=error_msg), ): mocked_wallet_provider.sign_message(message) @@ -124,7 +125,7 @@ def test_sign_message_with_unicode(mocked_wallet_provider, mock_cdp_client): # Configure the mock to return signature mock_cdp_client.solana.sign_message = AsyncMock(return_value=MOCK_SIGNATURE) - with patch("asyncio.run", return_value=MOCK_SIGNATURE): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_SIGNATURE): signature = mocked_wallet_provider.sign_message(message) assert signature == MOCK_SIGNATURE diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_solana_specific.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_solana_specific.py index eb9700aa4..c60c3d503 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_solana_specific.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_solana_specific.py @@ -35,7 +35,7 @@ def test_solana_network_configuration(): patch( "coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider.SolanaClient" ) as mock_solana_client, - patch("asyncio.run", return_value=Mock(address=MOCK_ADDRESS)), + patch.object(CdpSolanaWalletProvider, "_run_async", return_value=Mock(address=MOCK_ADDRESS)), ): config = CdpSolanaWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, @@ -106,7 +106,7 @@ def test_solana_transfer_parameters(mocked_wallet_provider, mock_cdp_client): # Configure get_account to return our mock wallet mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) - with patch("asyncio.run", return_value="test_signature"): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value="test_signature"): mocked_wallet_provider.native_transfer(to_address, amount) # Verify transfer was called with correct parameters @@ -128,7 +128,7 @@ def test_network_id_defaults(): with ( patch("coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider.CdpClient"), patch("coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider.SolanaClient"), - patch("asyncio.run", return_value=Mock(address=MOCK_ADDRESS)), + patch.object(CdpSolanaWalletProvider, "_run_async", return_value=Mock(address=MOCK_ADDRESS)), patch.dict( "os.environ", { @@ -158,7 +158,7 @@ def test_async_context_manager_usage(mocked_wallet_provider, mock_cdp_client): mock_wallet.transfer = AsyncMock(return_value=Mock(signature="test_sig")) mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) - with patch("asyncio.run", return_value="test_sig"): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value="test_sig"): mocked_wallet_provider.native_transfer("SomeAddress", Decimal("1.0")) # Note: In the actual implementation, close() is called in a finally block diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_transactions.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_transactions.py index 3c3373afd..e7750edf4 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_transactions.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_transactions.py @@ -5,6 +5,7 @@ import pytest +from coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider import CdpSolanaWalletProvider from .conftest import ( MOCK_ADDRESS_TO, MOCK_TRANSACTION_SIGNATURE, @@ -26,7 +27,7 @@ def test_native_transfer(mocked_wallet_provider, mock_cdp_client): mock_wallet.transfer = AsyncMock(return_value=mock_transaction) mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) - with patch("asyncio.run", return_value=MOCK_TRANSACTION_SIGNATURE): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_TRANSACTION_SIGNATURE): tx_signature = mocked_wallet_provider.native_transfer(to_address, amount) assert tx_signature == MOCK_TRANSACTION_SIGNATURE @@ -42,7 +43,7 @@ def test_native_transfer_full_sol(mocked_wallet_provider, mock_cdp_client): mock_wallet.transfer = AsyncMock(return_value=mock_transaction) mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) - with patch("asyncio.run", return_value=MOCK_TRANSACTION_SIGNATURE): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_TRANSACTION_SIGNATURE): tx_signature = mocked_wallet_provider.native_transfer(to_address, amount) assert tx_signature == MOCK_TRANSACTION_SIGNATURE @@ -58,7 +59,7 @@ def test_native_transfer_small_amount(mocked_wallet_provider, mock_cdp_client): mock_wallet.transfer = AsyncMock(return_value=mock_transaction) mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) - with patch("asyncio.run", return_value=MOCK_TRANSACTION_SIGNATURE): + with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_TRANSACTION_SIGNATURE): tx_signature = mocked_wallet_provider.native_transfer(to_address, small_amount) assert tx_signature == MOCK_TRANSACTION_SIGNATURE @@ -79,7 +80,7 @@ async def raise_error(*args, **kwargs): mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) with ( - patch("asyncio.run", side_effect=Exception(error_msg)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=Exception(error_msg)), pytest.raises(Exception, match=error_msg), ): mocked_wallet_provider.native_transfer(to_address, amount) @@ -100,7 +101,7 @@ async def raise_connection_error(*args, **kwargs): mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) with ( - patch("asyncio.run", side_effect=ConnectionError(error_msg)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=ConnectionError(error_msg)), pytest.raises(ConnectionError, match=error_msg), ): mocked_wallet_provider.native_transfer(to_address, amount) @@ -121,7 +122,7 @@ async def raise_timeout_error(*args, **kwargs): mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) with ( - patch("asyncio.run", side_effect=TimeoutError(error_msg)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=TimeoutError(error_msg)), pytest.raises(TimeoutError, match=error_msg), ): mocked_wallet_provider.native_transfer(to_address, amount) @@ -142,7 +143,7 @@ async def raise_value_error(*args, **kwargs): mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) with ( - patch("asyncio.run", side_effect=ValueError(error_msg)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=ValueError(error_msg)), pytest.raises(ValueError, match=error_msg), ): mocked_wallet_provider.native_transfer(invalid_address, amount) @@ -163,7 +164,7 @@ async def raise_zero_amount_error(*args, **kwargs): mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) with ( - patch("asyncio.run", side_effect=ValueError(error_msg)), + patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=ValueError(error_msg)), pytest.raises(ValueError, match=error_msg), ): mocked_wallet_provider.native_transfer(to_address, amount) From 2f7995c75e95fe5d14dfffa129679cdfc1eb787e Mon Sep 17 00:00:00 2001 From: Darryl Sladden Date: Wed, 25 Feb 2026 23:35:49 -0800 Subject: [PATCH 4/5] Fix test fixtures: restore _run_async after init, add missing import --- .../cdp_evm_server_wallet_provider/conftest.py | 16 ++++++++++------ .../cdp_solana_wallet_provider/conftest.py | 18 +++++++----------- .../test_error_handling.py | 2 ++ 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/conftest.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/conftest.py index bcd12ba93..42a083431 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/conftest.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/conftest.py @@ -135,12 +135,16 @@ def mocked_wallet_provider(mock_cdp_client, mock_account, mock_web3, mock_wallet network_id=MOCK_NETWORK_ID, ) - # Patch the async run to return the mock account directly - with patch.object(CdpEvmWalletProvider, "_run_async", return_value=mock_account): + # Patch _run_async only during init to return the mock account + original_run_async = CdpEvmWalletProvider._run_async + CdpEvmWalletProvider._run_async = lambda self, coro: mock_account + try: provider = CdpEvmWalletProvider(config) + finally: + CdpEvmWalletProvider._run_async = original_run_async - # Manually set account and wallet attributes - provider._account = mock_account - provider._wallet = mock_wallet + # Manually set account and wallet attributes + provider._account = mock_account + provider._wallet = mock_wallet - yield provider + yield provider diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/conftest.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/conftest.py index b56da635e..6af2f9380 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/conftest.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/conftest.py @@ -120,17 +120,13 @@ def mocked_wallet_provider(mock_cdp_client, mock_solana_client, mock_public_key) network_id=MOCK_NETWORK_ID, ) - # Patch _run_async to handle initialization coroutines synchronously + # Patch _run_async only during init, then restore it mock_account = Mock(address=MOCK_ADDRESS) - - def mock_run_async(self, coro): - # For initialize_wallet, return the mock account - if hasattr(coro, "__name__") and coro.__name__ == "initialize_wallet": - return mock_account - # For client.close, just return None - return None - - with patch.object(CdpSolanaWalletProvider, "_run_async", mock_run_async): + original_run_async = CdpSolanaWalletProvider._run_async + CdpSolanaWalletProvider._run_async = lambda self, coro: mock_account + try: provider = CdpSolanaWalletProvider(config) + finally: + CdpSolanaWalletProvider._run_async = original_run_async - yield provider + yield provider diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py index 3cec5bfd1..babc22e23 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py @@ -5,6 +5,8 @@ import pytest +from coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider import CdpSolanaWalletProvider + # ========================================================= # error handling tests # ========================================================= From ac1bc0a3565a2f61d73ce4fa9a9adf73e1070e1a Mon Sep 17 00:00:00 2001 From: Darryl Sladden Date: Thu, 26 Feb 2026 02:02:11 -0800 Subject: [PATCH 5/5] fix: remove unused threading import, ruff format all changed files --- .../wallet_providers/cdp_evm_wallet_provider.py | 7 +++---- .../test_initialization.py | 8 ++++++-- .../cdp_solana_wallet_provider/test_basic_methods.py | 4 +++- .../test_error_handling.py | 8 ++++++-- .../test_initialization.py | 4 +++- .../test_solana_specific.py | 8 ++++++-- .../cdp_solana_wallet_provider/test_transactions.py | 12 +++++++++--- 7 files changed, 36 insertions(+), 15 deletions(-) diff --git a/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_evm_wallet_provider.py b/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_evm_wallet_provider.py index 3bf99a16a..43585341d 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_evm_wallet_provider.py +++ b/python/coinbase-agentkit/coinbase_agentkit/wallet_providers/cdp_evm_wallet_provider.py @@ -371,8 +371,7 @@ def _run_async(self, coroutine): # If we reach this point, there's already a running event loop # We need to run the coroutine in a new thread with a new event loop import concurrent.futures - import threading - + def run_in_thread(): new_loop = asyncio.new_event_loop() asyncio.set_event_loop(new_loop) @@ -380,11 +379,11 @@ def run_in_thread(): return new_loop.run_until_complete(coroutine) finally: new_loop.close() - + with concurrent.futures.ThreadPoolExecutor() as executor: future = executor.submit(run_in_thread) return future.result() - + except RuntimeError: # No running event loop, safe to create and use a new one loop = asyncio.new_event_loop() diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/test_initialization.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/test_initialization.py index cc8c753cb..99512eb6a 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/test_initialization.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_evm_server_wallet_provider/test_initialization.py @@ -99,7 +99,9 @@ def test_init_with_missing_credentials(): def test_init_with_invalid_network(mock_cdp_client): """Test initialization with invalid network.""" # Use a known invalid network ID - with patch.object(CdpEvmWalletProvider, "_run_async", side_effect=ValueError("Invalid network ID")): + with patch.object( + CdpEvmWalletProvider, "_run_async", side_effect=ValueError("Invalid network ID") + ): config = CdpEvmWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, api_key_secret=MOCK_API_KEY_SECRET, @@ -113,7 +115,9 @@ def test_init_with_invalid_network(mock_cdp_client): def test_init_with_account_creation_error(mock_cdp_client): """Test initialization when account creation fails.""" - with patch.object(CdpEvmWalletProvider, "_run_async", side_effect=Exception("Failed to create account")): + with patch.object( + CdpEvmWalletProvider, "_run_async", side_effect=Exception("Failed to create account") + ): config = CdpEvmWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, api_key_secret=MOCK_API_KEY_SECRET, diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_basic_methods.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_basic_methods.py index 1c7f5d2d5..b43fbce61 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_basic_methods.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_basic_methods.py @@ -92,7 +92,9 @@ def test_get_network_different_networks(): with ( patch("coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider.CdpClient"), patch("coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider.SolanaClient"), - patch.object(CdpSolanaWalletProvider, "_run_async", return_value=Mock(address=MOCK_ADDRESS)), + patch.object( + CdpSolanaWalletProvider, "_run_async", return_value=Mock(address=MOCK_ADDRESS) + ), ): config = CdpSolanaWalletProviderConfig( api_key_id="test_key", diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py index babc22e23..edd421055 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_error_handling.py @@ -87,7 +87,9 @@ async def raise_auth_error(*args, **kwargs): mock_cdp_client.solana.sign_message = AsyncMock(side_effect=Exception(rate_limit_error)) with ( - patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=Exception(rate_limit_error)), + patch.object( + CdpSolanaWalletProvider, "_run_async", side_effect=Exception(rate_limit_error) + ), pytest.raises(Exception, match=rate_limit_error), ): mocked_wallet_provider.sign_message("test") @@ -120,7 +122,9 @@ async def raise_timeout(*args, **kwargs): mock_wallet.transfer = raise_timeout with ( - patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=TimeoutError(timeout_error)), + patch.object( + CdpSolanaWalletProvider, "_run_async", side_effect=TimeoutError(timeout_error) + ), pytest.raises(TimeoutError, match=timeout_error), ): mocked_wallet_provider.native_transfer("SomeAddress", Decimal("1.0")) diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_initialization.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_initialization.py index 554350129..e41dd20c9 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_initialization.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_initialization.py @@ -179,7 +179,9 @@ def test_init_with_cdp_import_error(): def test_init_with_account_creation_error(mock_cdp_client, mock_solana_client, mock_public_key): """Test initialization when account creation fails.""" - with patch.object(CdpSolanaWalletProvider, "_run_async", side_effect=Exception("Failed to create account")): + with patch.object( + CdpSolanaWalletProvider, "_run_async", side_effect=Exception("Failed to create account") + ): config = CdpSolanaWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, api_key_secret=MOCK_API_KEY_SECRET, diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_solana_specific.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_solana_specific.py index c60c3d503..2e674844f 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_solana_specific.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_solana_specific.py @@ -35,7 +35,9 @@ def test_solana_network_configuration(): patch( "coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider.SolanaClient" ) as mock_solana_client, - patch.object(CdpSolanaWalletProvider, "_run_async", return_value=Mock(address=MOCK_ADDRESS)), + patch.object( + CdpSolanaWalletProvider, "_run_async", return_value=Mock(address=MOCK_ADDRESS) + ), ): config = CdpSolanaWalletProviderConfig( api_key_id=MOCK_API_KEY_ID, @@ -128,7 +130,9 @@ def test_network_id_defaults(): with ( patch("coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider.CdpClient"), patch("coinbase_agentkit.wallet_providers.cdp_solana_wallet_provider.SolanaClient"), - patch.object(CdpSolanaWalletProvider, "_run_async", return_value=Mock(address=MOCK_ADDRESS)), + patch.object( + CdpSolanaWalletProvider, "_run_async", return_value=Mock(address=MOCK_ADDRESS) + ), patch.dict( "os.environ", { diff --git a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_transactions.py b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_transactions.py index e7750edf4..73e247266 100644 --- a/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_transactions.py +++ b/python/coinbase-agentkit/tests/wallet_providers/cdp_solana_wallet_provider/test_transactions.py @@ -27,7 +27,9 @@ def test_native_transfer(mocked_wallet_provider, mock_cdp_client): mock_wallet.transfer = AsyncMock(return_value=mock_transaction) mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) - with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_TRANSACTION_SIGNATURE): + with patch.object( + CdpSolanaWalletProvider, "_run_async", return_value=MOCK_TRANSACTION_SIGNATURE + ): tx_signature = mocked_wallet_provider.native_transfer(to_address, amount) assert tx_signature == MOCK_TRANSACTION_SIGNATURE @@ -43,7 +45,9 @@ def test_native_transfer_full_sol(mocked_wallet_provider, mock_cdp_client): mock_wallet.transfer = AsyncMock(return_value=mock_transaction) mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) - with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_TRANSACTION_SIGNATURE): + with patch.object( + CdpSolanaWalletProvider, "_run_async", return_value=MOCK_TRANSACTION_SIGNATURE + ): tx_signature = mocked_wallet_provider.native_transfer(to_address, amount) assert tx_signature == MOCK_TRANSACTION_SIGNATURE @@ -59,7 +63,9 @@ def test_native_transfer_small_amount(mocked_wallet_provider, mock_cdp_client): mock_wallet.transfer = AsyncMock(return_value=mock_transaction) mock_cdp_client.solana.get_account = AsyncMock(return_value=mock_wallet) - with patch.object(CdpSolanaWalletProvider, "_run_async", return_value=MOCK_TRANSACTION_SIGNATURE): + with patch.object( + CdpSolanaWalletProvider, "_run_async", return_value=MOCK_TRANSACTION_SIGNATURE + ): tx_signature = mocked_wallet_provider.native_transfer(to_address, small_amount) assert tx_signature == MOCK_TRANSACTION_SIGNATURE