diff --git a/python/src/uagents/agent.py b/python/src/uagents/agent.py index 57acf4d4..d328a672 100644 --- a/python/src/uagents/agent.py +++ b/python/src/uagents/agent.py @@ -54,7 +54,12 @@ DefaultRegistrationPolicy, update_agent_status, ) -from uagents.resolver import GlobalResolver, Resolver, get_agent_address +from uagents.resolver import ( + GlobalResolver, + Resolver, + get_agent_address, + parse_identifier, +) from uagents.storage import KeyValueStore, get_or_create_private_keys from uagents.types import ( AgentEndpoint, @@ -148,6 +153,7 @@ class AgentRepresentation: def __init__( self, address: str, + identifier: str, name: Optional[str], signing_callback: Callable, ): @@ -160,6 +166,7 @@ def __init__( signing_callback (Callable): The callback for signing messages. """ self._address = address + self._identifier = identifier self._name = name self._signing_callback = signing_callback @@ -193,7 +200,7 @@ def identifier(self) -> str: Returns: str: The agent's address and network prefix. """ - return TESTNET_PREFIX + "://" + self._address + return self._identifier def sign_digest(self, data: bytes) -> str: """ @@ -441,6 +448,7 @@ def _build_context(self) -> InternalContext: return InternalContext( agent=AgentRepresentation( address=self.address, + identifier=self.identifier, name=self._name, signing_callback=self._identity.sign_digest, ), @@ -584,7 +592,8 @@ def identifier(self) -> str: str: The agent's identifier. """ prefix = TESTNET_PREFIX if self._test else MAINNET_PREFIX - return prefix + "://" + self._identity.address + domain = f"{self._domain}/" if self._domain else "" + return prefix + "://" + domain + self._identity.address @property def wallet(self) -> LocalWallet: @@ -1249,6 +1258,8 @@ async def _process_message_queue(self): # get an element from the queue schema_digest, sender, message, session = await self._message_queue.get() + _, _, parsed_address = parse_identifier(sender) + # lookup the model definition model_class: Optional[Type[Model]] = self._models.get(schema_digest) if model_class is None: @@ -1263,7 +1274,7 @@ async def _process_message_queue(self): self._message_cache.add_entry( EnvelopeHistoryEntry( version=1, - sender=sender, + sender=parsed_address, target=self.address, session=session, schema_digest=schema_digest, @@ -1275,6 +1286,7 @@ async def _process_message_queue(self): context = ExternalContext( agent=AgentRepresentation( address=self.address, + identifier=self.identifier, name=self._name, signing_callback=self._identity.sign_digest, ), @@ -1305,7 +1317,7 @@ async def _process_message_queue(self): self._logger.warning(f"Unable to parse message: {ex}") await _send_error_message( context, - sender, + parsed_address, ErrorMessage( error=f"Message does not conform to expected schema: {ex}" ), @@ -1317,12 +1329,12 @@ async def _process_message_queue(self): schema_digest ) if handler is None: - if not is_user_address(sender): + if not is_user_address(parsed_address): handler = self._signed_message_handlers.get(schema_digest) elif schema_digest in self._signed_message_handlers: await _send_error_message( context, - sender, + parsed_address, ErrorMessage( error="Message must be sent from verified agent address" ), diff --git a/python/src/uagents/asgi.py b/python/src/uagents/asgi.py index 2150cf32..dc3f2c85 100644 --- a/python/src/uagents/asgi.py +++ b/python/src/uagents/asgi.py @@ -24,6 +24,7 @@ from uagents.dispatch import dispatcher from uagents.envelope import Envelope from uagents.models import ErrorMessage, Model +from uagents.resolver import parse_identifier from uagents.types import RestHandlerDetails, RestMethod from uagents.utils import get_logger @@ -336,14 +337,15 @@ async def __call__(self, scope, receive, send): # pylint: disable=too-many-bra send, 400, body={"error": "contents do not match envelope schema"} ) return + _, _, parsed_address = parse_identifier(env.sender) expects_response = headers.get(b"x-uagents-connection") == b"sync" if expects_response: # Add a future that will be resolved once the query is answered - self._queries[env.sender] = asyncio.Future() + self._queries[parsed_address] = asyncio.Future() - if not is_user_address(env.sender): # verify signature if sent from agent + if not is_user_address(parsed_address): # verify signature if sent from agent try: env.verify() except Exception as err: @@ -356,12 +358,16 @@ async def __call__(self, scope, receive, send): # pylint: disable=too-many-bra return await dispatcher.dispatch_msg( - env.sender, env.target, env.schema_digest, env.decode_payload(), env.session + env.sender, # fully qualified address of the sender + env.target, + env.schema_digest, + env.decode_payload(), + env.session, ) # wait for any queries to be resolved if expects_response: - response_msg, schema_digest = await self._queries[env.sender] + response_msg, schema_digest = await self._queries[parsed_address] if (env.expires is not None) and ( datetime.now() > datetime.fromtimestamp(env.expires) ): @@ -370,7 +376,7 @@ async def __call__(self, scope, receive, send): # pylint: disable=too-many-bra ).model_dump_json() schema_digest = ERROR_MESSAGE_DIGEST sender = env.target - target = env.sender + target = parsed_address response = enclose_response_raw( response_msg, schema_digest, sender, env.session, target=target ) diff --git a/python/src/uagents/context.py b/python/src/uagents/context.py index d2c8158d..ba39780a 100644 --- a/python/src/uagents/context.py +++ b/python/src/uagents/context.py @@ -494,7 +494,7 @@ async def send_raw( # Handle external dispatch of messages env = Envelope( version=1, - sender=self.agent.address, + sender=self.agent.identifier, target=destination_address, session=self._session, schema_digest=message_schema_digest, diff --git a/python/src/uagents/envelope.py b/python/src/uagents/envelope.py index 4816f54e..e0822e36 100644 --- a/python/src/uagents/envelope.py +++ b/python/src/uagents/envelope.py @@ -14,6 +14,7 @@ ) from uagents.crypto import Identity +from uagents.resolver import parse_identifier from uagents.types import JsonStr @@ -93,7 +94,8 @@ def verify(self) -> bool: """ if self.signature is None: raise ValueError("Envelope signature is missing") - return Identity.verify_digest(self.sender, self._digest(), self.signature) + _, _, parsed_address = parse_identifier(self.sender) + return Identity.verify_digest(parsed_address, self._digest(), self.signature) def _digest(self) -> bytes: """