Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 12 additions & 19 deletions python/cdp/evm_local_account.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import asyncio
from concurrent.futures import ThreadPoolExecutor
from typing import Any

import nest_asyncio
from eth_account.datastructures import SignedMessage, SignedTransaction
from eth_account.messages import SignableMessage, _hash_eip191_message, encode_typed_data
from eth_account.signers.base import BaseAccount
Expand All @@ -11,35 +11,28 @@
from cdp.errors import UserInputValidationError
from cdp.evm_server_account import EvmServerAccount

# Apply nest-asyncio to allow nested event loops, but only if compatible
try:
nest_asyncio.apply()
except ValueError as e:
# If nest_asyncio can't patch the loop (e.g., uvloop), silently continue
# This commonly happens when uvloop is installed and running
if "Can't patch loop" in str(e):
pass
else:
# Re-raise other ValueError exceptions
raise


def _run_async(coroutine):
"""Run an async coroutine synchronously.

If no event loop is running, asyncio.run is used directly.
If an event loop is already running, the coroutine is executed
in a background thread to avoid nested loop issues.

Args:
coroutine: The coroutine to run
coroutine: The coroutine to run.

Returns:
Any: The result of the coroutine
Any: The result of the coroutine.

"""
try:
loop = asyncio.get_event_loop()
asyncio.get_running_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
return loop.run_until_complete(coroutine)
return asyncio.run(coroutine)

with ThreadPoolExecutor(max_workers=1) as executor:
return executor.submit(asyncio.run, coroutine).result()


class EvmLocalAccount(BaseAccount):
Expand Down
1 change: 1 addition & 0 deletions python/changelog.d/591.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Removed `nest-asyncio` dependency and replaced it with a thread-safe fallback in `EvmLocalAccount`, restoring compatibility with Python 3.12+ and modern uvicorn.
1 change: 0 additions & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ dependencies = [
"web3>=7.6.0,<=7.10.0",
"solana>=0.36.6",
"solders>=0.26.0",
"nest-asyncio>=1.6.0,<2",
"base58>=2.1.1",
]

Expand Down
13 changes: 1 addition & 12 deletions python/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.