|
1 | 1 | # An interface for all clients to implement. |
2 | | - |
| 2 | +import json |
3 | 3 | import logging |
| 4 | +import time |
4 | 5 | from abc import ABC, abstractmethod |
5 | 6 | from pathlib import Path |
6 | 7 | from typing import ( |
|
18 | 19 |
|
19 | 20 | from aleph_message.models import ( |
20 | 21 | AlephMessage, |
| 22 | + ItemType, |
21 | 23 | MessagesResponse, |
22 | 24 | MessageType, |
23 | 25 | Payment, |
24 | 26 | PostMessage, |
| 27 | + parse_message, |
25 | 28 | ) |
26 | 29 | from aleph_message.models.execution.environment import HypervisorType |
27 | 30 | from aleph_message.models.execution.program import Encoding |
28 | 31 | from aleph_message.status import MessageStatus |
29 | 32 |
|
| 33 | +from aleph.sdk.conf import settings |
| 34 | +from aleph.sdk.types import Account |
| 35 | +from aleph.sdk.utils import extended_json_encoder |
| 36 | + |
30 | 37 | from ..query.filters import MessageFilter, PostFilter |
31 | 38 | from ..query.responses import PostsResponse |
32 | 39 | from ..types import GenericMessage, StorageEnum |
33 | | -from ..utils import Writable |
| 40 | +from ..utils import Writable, compute_sha256 |
34 | 41 |
|
35 | 42 | DEFAULT_PAGE_SIZE = 200 |
36 | 43 |
|
@@ -231,6 +238,8 @@ def watch_messages( |
231 | 238 |
|
232 | 239 |
|
233 | 240 | class AuthenticatedAlephClient(AlephClient): |
| 241 | + account: Account |
| 242 | + |
234 | 243 | @abstractmethod |
235 | 244 | async def create_post( |
236 | 245 | self, |
@@ -444,6 +453,62 @@ async def forget( |
444 | 453 | "Did you mean to import `AuthenticatedAlephHttpClient`?" |
445 | 454 | ) |
446 | 455 |
|
| 456 | + async def generate_signed_message( |
| 457 | + self, |
| 458 | + message_type: MessageType, |
| 459 | + content: Dict[str, Any], |
| 460 | + channel: Optional[str], |
| 461 | + allow_inlining: bool = True, |
| 462 | + storage_engine: StorageEnum = StorageEnum.storage, |
| 463 | + ) -> AlephMessage: |
| 464 | + """Generate a signed aleph.im message ready to be sent to the network. |
| 465 | +
|
| 466 | + If the content is not inlined, it will be pushed to the storage engine via the API of a Core Channel Node. |
| 467 | +
|
| 468 | + :param message_type: Type of the message (PostMessage, ...) |
| 469 | + :param content: User-defined content of the message |
| 470 | + :param channel: Channel to use (Default: "TEST") |
| 471 | + :param allow_inlining: Whether to allow inlining the content of the message (Default: True) |
| 472 | + :param storage_engine: Storage engine to use (Default: "storage") |
| 473 | + """ |
| 474 | + |
| 475 | + message_dict: Dict[str, Any] = { |
| 476 | + "sender": self.account.get_address(), |
| 477 | + "chain": self.account.CHAIN, |
| 478 | + "type": message_type, |
| 479 | + "content": content, |
| 480 | + "time": time.time(), |
| 481 | + "channel": channel, |
| 482 | + } |
| 483 | + |
| 484 | + # Use the Pydantic encoder to serialize types like UUID, datetimes, etc. |
| 485 | + item_content: str = json.dumps( |
| 486 | + content, separators=(",", ":"), default=extended_json_encoder |
| 487 | + ) |
| 488 | + |
| 489 | + if allow_inlining and (len(item_content) < settings.MAX_INLINE_SIZE): |
| 490 | + message_dict["item_content"] = item_content |
| 491 | + message_dict["item_hash"] = compute_sha256(item_content) |
| 492 | + message_dict["item_type"] = ItemType.inline |
| 493 | + else: |
| 494 | + if storage_engine == StorageEnum.ipfs: |
| 495 | + message_dict["item_hash"] = await self.ipfs_push( |
| 496 | + content=content, |
| 497 | + ) |
| 498 | + message_dict["item_type"] = ItemType.ipfs |
| 499 | + else: # storage |
| 500 | + assert storage_engine == StorageEnum.storage |
| 501 | + message_dict["item_hash"] = await self.storage_push( |
| 502 | + content=content, |
| 503 | + ) |
| 504 | + message_dict["item_type"] = ItemType.storage |
| 505 | + |
| 506 | + message_dict = await self.account.sign_message(message_dict) |
| 507 | + return parse_message(message_dict) |
| 508 | + |
| 509 | + # Alias for backwards compatibility |
| 510 | + _prepare_aleph_message = generate_signed_message |
| 511 | + |
447 | 512 | @abstractmethod |
448 | 513 | async def submit( |
449 | 514 | self, |
|
0 commit comments