diff --git a/integrations/tortoise-ORM/README.md b/integrations/tortoise-ORM/README.md new file mode 100644 index 00000000..a4f1ead6 --- /dev/null +++ b/integrations/tortoise-ORM/README.md @@ -0,0 +1,113 @@ +# Room Booking Example + +Welcome to the Room Booking example! This guide demonstrates how to create a distributed agent system where a guest can request a room booking from a hotel. This example focuses on using Tortoise ORM for database management within the agents to handle room availability and booking processes. + +To prepare for running the example, ensure you're in the proper directory and have configured your environment with the necessary dependencies: + + + +``` +poetry install +poetry shell +``` + + +## Using Tortoise ORM for Database Management + +### Defining the Models + +- **Description**: Models are used to define the structure of the data exchanged between agents. In this example, we have `RoomRequest` and `RoomResponse` models for the booking request and response, and an `Availability` model for managing room availability and pricing. + +``` +from uagents import Model +from tortoise import fields, models + +class RoomRequest(Model): + max_price: int + +class RoomResponse(Model): + success: bool + +class Availability(models.Model): + id = fields.IntField(pk=True) + room_available = fields.BooleanField(default=True) + min_price = fields.FloatField(default=0.0) +``` + +### Hotel Agent with Tortoise ORM + +- **Description**: The hotel agent uses Tortoise ORM to manage room availability in a SQLite database. On startup, the database is initialized, and the room availability is set. The agent processes room booking requests and updates the database accordingly. + +``` +from uagents import Agent, Context +from tortoise import Tortoise +from models import Availability, RoomRequest, RoomResponse + +HOTEL_SEED = "put_hotel_seed_phrase_here" + +hotel = Agent( + name="hotel", + port=8001, + seed=HOTEL_SEED, + endpoint=["http://127.0.0.1:8001/submit"], +) + +print(f"hotel's agent address: {hotel.address}") + +@hotel.on_event("startup") +async def startup(_ctx: Context): + await Tortoise.init( + db_url="sqlite://db.sqlite3", modules={"models": ["models"]} + ) + await Tortoise.generate_schemas() + + await Availability.create( + room_available=True, + min_price=50, + ) + +@hotel.on_event("shutdown") +async def shutdown(_ctx: Context): + await Tortoise.close_connections() + +@hotel.on_message(model=RoomRequest) +async def message_handler(ctx: Context, sender: str, msg: RoomRequest): + availability = await Availability.first() + success = False + if availability.room_available: + ctx.logger.info(f"Room available, attempting to book") + if availability.min_price <= msg.max_price: + success = True + ctx.logger.info(f"Offer of ${msg.max_price} accepted!") + availability.room_available = False + await availability.save() + else: + ctx.logger.info(f"Offer of ${msg.max_price} was too low, won't accept") + else: + ctx.logger.info(f"Room unavailable") + + await ctx.send(sender, RoomResponse(success=success)) + +if __name__ == "__main__": + hotel.run() +``` + +## Running the Example + +To observe the room booking interaction between the guest and hotel agents, run: + +``` +python guest.py +python hotel.py +``` + + +This command starts both agents. The guest agent periodically sends a room booking request to the hotel agent, which processes the request based on room availability and price, and responds accordingly. + +## Key Points + +- Ensure the guest and hotel agents are configured with appropriate seed phrases and endpoints. +- The hotel agent manages room availability using Tortoise ORM and responds to booking requests based on predefined criteria. +- The guest agent continuously sends booking requests until a successful booking is achieved. + +By following this example, you can implement a simple room booking system with distributed agents, demonstrating the potential of agent-based architectures in automating tasks and interactions. diff --git a/integrations/tortoise-ORM/guest.py b/integrations/tortoise-ORM/guest.py new file mode 100644 index 00000000..f2be42c1 --- /dev/null +++ b/integrations/tortoise-ORM/guest.py @@ -0,0 +1,41 @@ +from uagents import Agent, Context +from models import RoomRequest, RoomResponse + +HOTEL_ADDRESS = "put_HOTEL_ADDRESS_here" +GUEST_SEED = "put_guest_seed_phrase_here" + +guest = Agent( + name="guest", + port=8000, + seed=GUEST_SEED, + endpoint=["http://127.0.0.1:8000/submit"], +) + +request = RoomRequest(max_price=70) + +@guest.on_event("startup") +async def startup(ctx: Context): + ctx.storage.set("completed", False) + +@guest.on_interval(period=8.0) +async def send_message(ctx: Context): + + completed = ctx.storage.get("completed") + + if not completed: + ctx.logger.info(f"Sending room booking request: {request}") + await ctx.send(HOTEL_ADDRESS, request) + + +@guest.on_message(RoomResponse, replies=set()) +async def booking_handler(ctx: Context, _sender: str, msg: RoomResponse): + if msg.success: + ctx.logger.info("Booking was successful") + else: + ctx.logger.info("Booking was unsuccessful") + + ctx.storage.set("completed", True) + + +if __name__ == "__main__": + guest.run() diff --git a/integrations/tortoise-ORM/hotel.py b/integrations/tortoise-ORM/hotel.py new file mode 100644 index 00000000..16c5ca19 --- /dev/null +++ b/integrations/tortoise-ORM/hotel.py @@ -0,0 +1,54 @@ +from uagents import Agent, Context, Model +from tortoise import Tortoise +from models import Availability, RoomRequest, RoomResponse + + +HOTEL_SEED = "put_hotel_seed_phrase_here" + +hotel = Agent( + name="hotel", + port=8001, + seed=HOTEL_SEED , + endpoint=["http://127.0.0.1:8001/submit"], +) + +print(f"hotel's agent address: {hotel.address}") + +@hotel.on_event("startup") +async def startup(_ctx: Context): + await Tortoise.init( + db_url="sqlite://db.sqlite3", modules={"models": ["models"]} + ) + await Tortoise.generate_schemas() + + await Availability.create( + room_available=True, + min_price=50, + ) + + +@hotel.on_event("shutdown") +async def shutdown(_ctx: Context): + await Tortoise.close_connections() + +@hotel.on_message(model=RoomRequest) +async def message_handler(ctx: Context, sender: str, msg: RoomRequest): + availability = await Availability.first() + success = False + if availability.room_available: + ctx.logger.info(f"Room available, attempting to book") + if availability.min_price <= msg.max_price: + success = True + ctx.logger.info(f"Offer of ${msg.max_price} accepted!") + availability.room_available = False + await availability.save() + else: + ctx.logger.info(f"Offer of ${msg.max_price} was to low, won't accept ") + else: + ctx.logger.info(f"Room unavailable") + + await ctx.send(sender, RoomResponse(success=success)) + + +if __name__ == "__main__": + hotel.run() diff --git a/integrations/tortoise-ORM/models.py b/integrations/tortoise-ORM/models.py new file mode 100644 index 00000000..b123ada9 --- /dev/null +++ b/integrations/tortoise-ORM/models.py @@ -0,0 +1,14 @@ +from uagents import Model +from tortoise import fields, models + +class RoomRequest(Model): + max_price: int + +class RoomResponse(Model): + success: bool + +class Availability(models.Model): + id = fields.IntField(pk=True) + room_available = fields.BooleanField(default=True) + min_price = fields.FloatField(default=0.0) + diff --git a/python/poetry.lock b/integrations/tortoise-ORM/poetry.lock similarity index 58% rename from python/poetry.lock rename to integrations/tortoise-ORM/poetry.lock index ad6e327b..55c0ae46 100644 --- a/python/poetry.lock +++ b/integrations/tortoise-ORM/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -96,20 +96,6 @@ yarl = ">=1.0,<2.0" [package.extras] speedups = ["Brotli", "aiodns", "brotlicffi"] -[[package]] -name = "aioresponses" -version = "0.7.6" -description = "Mock out requests made by ClientSession from aiohttp package" -optional = false -python-versions = "*" -files = [ - {file = "aioresponses-0.7.6-py2.py3-none-any.whl", hash = "sha256:d2c26defbb9b440ea2685ec132e90700907fd10bcca3e85ec2f157219f0d26f7"}, - {file = "aioresponses-0.7.6.tar.gz", hash = "sha256:f795d9dbda2d61774840e7e32f5366f45752d1adc1b74c9362afd017296c7ee1"}, -] - -[package.dependencies] -aiohttp = ">=3.3.0,<4.0.0" - [[package]] name = "aiosignal" version = "1.3.1" @@ -128,7 +114,7 @@ frozenlist = ">=1.1.0" name = "aiosqlite" version = "0.17.0" description = "asyncio bridge to the standard sqlite3 module" -optional = true +optional = false python-versions = ">=3.6" files = [ {file = "aiosqlite-0.17.0-py3-none-any.whl", hash = "sha256:6c49dc6d3405929b1d08eeccc72306d3677503cc5e5e43771efc1e00232e8231"}, @@ -138,28 +124,6 @@ files = [ [package.dependencies] typing_extensions = ">=3.7.2" -[[package]] -name = "anyio" -version = "4.3.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = true -python-versions = ">=3.8" -files = [ - {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, - {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} - -[package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] - [[package]] name = "apispec" version = "6.6.0" @@ -181,17 +145,6 @@ marshmallow = ["marshmallow (>=3.18.0)"] tests = ["apispec[marshmallow,yaml]", "openapi-spec-validator (==0.7.1)", "pytest"] yaml = ["PyYAML (>=3.10)"] -[[package]] -name = "asn1crypto" -version = "1.5.1" -description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" -optional = true -python-versions = "*" -files = [ - {file = "asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67"}, - {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, -] - [[package]] name = "async-timeout" version = "4.0.3" @@ -222,20 +175,6 @@ tests = ["attrs[tests-no-zope]", "zope-interface"] tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] -[[package]] -name = "babel" -version = "2.14.0" -description = "Internationalization utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, - {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, -] - -[package.extras] -dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] - [[package]] name = "bech32" version = "1.2.0" @@ -248,89 +187,60 @@ files = [ ] [[package]] -name = "certifi" -version = "2024.2.2" -description = "Python package for providing Mozilla's CA Bundle." +name = "black" +version = "24.3.0" +description = "The uncompromising code formatter." optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, -] - -[[package]] -name = "cffi" -version = "1.16.0" -description = "Foreign Function Interface for Python calling C code." -optional = true python-versions = ">=3.8" files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, + {file = "black-24.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7d5e026f8da0322b5662fa7a8e752b3fa2dac1c1cbc213c3d7ff9bdd0ab12395"}, + {file = "black-24.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9f50ea1132e2189d8dff0115ab75b65590a3e97de1e143795adb4ce317934995"}, + {file = "black-24.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2af80566f43c85f5797365077fb64a393861a3730bd110971ab7a0c94e873e7"}, + {file = "black-24.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:4be5bb28e090456adfc1255e03967fb67ca846a03be7aadf6249096100ee32d0"}, + {file = "black-24.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4f1373a7808a8f135b774039f61d59e4be7eb56b2513d3d2f02a8b9365b8a8a9"}, + {file = "black-24.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aadf7a02d947936ee418777e0247ea114f78aff0d0959461057cae8a04f20597"}, + {file = "black-24.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c02e4ea2ae09d16314d30912a58ada9a5c4fdfedf9512d23326128ac08ac3d"}, + {file = "black-24.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:bf21b7b230718a5f08bd32d5e4f1db7fc8788345c8aea1d155fc17852b3410f5"}, + {file = "black-24.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2818cf72dfd5d289e48f37ccfa08b460bf469e67fb7c4abb07edc2e9f16fb63f"}, + {file = "black-24.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4acf672def7eb1725f41f38bf6bf425c8237248bb0804faa3965c036f7672d11"}, + {file = "black-24.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7ed6668cbbfcd231fa0dc1b137d3e40c04c7f786e626b405c62bcd5db5857e4"}, + {file = "black-24.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:56f52cfbd3dabe2798d76dbdd299faa046a901041faf2cf33288bc4e6dae57b5"}, + {file = "black-24.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:79dcf34b33e38ed1b17434693763301d7ccbd1c5860674a8f871bd15139e7837"}, + {file = "black-24.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e19cb1c6365fd6dc38a6eae2dcb691d7d83935c10215aef8e6c38edee3f77abd"}, + {file = "black-24.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65b76c275e4c1c5ce6e9870911384bff5ca31ab63d19c76811cb1fb162678213"}, + {file = "black-24.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b5991d523eee14756f3c8d5df5231550ae8993e2286b8014e2fdea7156ed0959"}, + {file = "black-24.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c45f8dff244b3c431b36e3224b6be4a127c6aca780853574c00faf99258041eb"}, + {file = "black-24.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6905238a754ceb7788a73f02b45637d820b2f5478b20fec82ea865e4f5d4d9f7"}, + {file = "black-24.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7de8d330763c66663661a1ffd432274a2f92f07feeddd89ffd085b5744f85e7"}, + {file = "black-24.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:7bb041dca0d784697af4646d3b62ba4a6b028276ae878e53f6b4f74ddd6db99f"}, + {file = "black-24.3.0-py3-none-any.whl", hash = "sha256:41622020d7120e01d377f74249e677039d20e6344ff5851de8a10f11f513bf93"}, + {file = "black-24.3.0.tar.gz", hash = "sha256:a0c9c4a0771afc6919578cec71ce82a3e31e054904e7197deacbc9382671c41f"}, ] [package.dependencies] -pycparser = "*" +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] [[package]] -name = "cfgv" -version = "3.4.0" -description = "Validate configuration and produce human readable error messages." +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." optional = false -python-versions = ">=3.8" +python-versions = ">=3.6" files = [ - {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, - {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] @@ -446,53 +356,6 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} -[[package]] -name = "coincurve" -version = "17.0.0" -description = "Cross-platform Python CFFI bindings for libsecp256k1" -optional = true -python-versions = ">=3.7" -files = [ - {file = "coincurve-17.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac8c87d6fd080faa74e7ecf64a6ed20c11a254863238759eb02c3f13ad12b0c4"}, - {file = "coincurve-17.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:25dfa105beba24c8de886f8ed654bb1133866e4e22cfd7ea5ad8438cae6ed924"}, - {file = "coincurve-17.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:698efdd53e4fe1bbebaee9b75cbc851be617974c1c60098e9145cb7198ae97fb"}, - {file = "coincurve-17.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30dd44d1039f1d237aaa2da6d14a455ca88df3bcb00610b41f3253fdca1be97b"}, - {file = "coincurve-17.0.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d154e2eb5711db8c5ef52fcd80935b5a0e751c057bc6ffb215a7bb409aedef03"}, - {file = "coincurve-17.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c71caffb97dd3d0c243beb62352669b1e5dafa3a4bccdbb27d36bd82f5e65d20"}, - {file = "coincurve-17.0.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:747215254e51dd4dfbe6dded9235491263da5d88fe372d66541ca16b51ea078f"}, - {file = "coincurve-17.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad2f6df39ba1e2b7b14bb984505ffa7d0a0ecdd697e8d7dbd19e04bc245c87ed"}, - {file = "coincurve-17.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0503326963916c85b61d16f611ea0545f03c9e418fa8007c233c815429e381e8"}, - {file = "coincurve-17.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1013c1597b65684ae1c3e42497f9ef5a04527fa6136a84a16b34602606428c74"}, - {file = "coincurve-17.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4beef321fd6434448aab03a0c245f31c4e77f43b54b82108c0948d29852ac7e"}, - {file = "coincurve-17.0.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f47806527d3184da3e8b146fac92a8ed567bbd225194f4517943d8cdc85f9542"}, - {file = "coincurve-17.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:51e56373ac79f4ec1cfc5da53d72c55f5e5ac28d848b0849ef5e687ace857888"}, - {file = "coincurve-17.0.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3d694ad194bee9e8792e2e75879dc5238d8a184010cde36c5ad518fcfe2cd8f2"}, - {file = "coincurve-17.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:74cedb3d3a1dc5abe0c9c2396e1b82cc64496babc5b42e007e72e185cb1edad8"}, - {file = "coincurve-17.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:db874c5c1dcb1f3a19379773b5e8cffc777625a7a7a60dd9a67206e31e62e2e9"}, - {file = "coincurve-17.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:896b01941254f0a218cf331a9bddfe2d43892f7f1ba10d6e372e2eb744a744c2"}, - {file = "coincurve-17.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6aec70238dbe7a5d66b5f9438ff45b08eb5e0990d49c32ebb65247c5d5b89d7a"}, - {file = "coincurve-17.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d24284d17162569df917a640f19d9654ba3b43cf560ced8864f270da903f73a5"}, - {file = "coincurve-17.0.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ea057f777842396d387103c606babeb3a1b4c6126769cc0a12044312fc6c465"}, - {file = "coincurve-17.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b88642edf7f281649b0c0b6ffade051945ccceae4b885e40445634877d0b3049"}, - {file = "coincurve-17.0.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a80a207131813b038351c5bdae8f20f5f774bbf53622081f208d040dd2b7528f"}, - {file = "coincurve-17.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f1ef72574aa423bc33665ef4be859164a478bad24d48442da874ef3dc39a474d"}, - {file = "coincurve-17.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfd4fab857bcd975edc39111cb5f5c104f138dac2e9ace35ea8434d37bcea3be"}, - {file = "coincurve-17.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:73f39579dd651a9fc29da5a8fc0d8153d872bcbc166f876457baced1a1c01501"}, - {file = "coincurve-17.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8852dc01af4f0fe941ffd04069f7e4fecdce9b867a016f823a02286a1a1f07b5"}, - {file = "coincurve-17.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1bef812da1da202cdd601a256825abcf26d86e8634fac3ec3e615e3bb3ff08c"}, - {file = "coincurve-17.0.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abbefc9ccb170cb255a31df32457c2e43084b9f37589d0694dacc2dea6ddaf7c"}, - {file = "coincurve-17.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:abbd9d017a7638dc38a3b9bb4851f8801b7818d4e5ac22e0c75e373b3c1dbff0"}, - {file = "coincurve-17.0.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e2c2e8a1f0b1f8e48049c891af4ae3cad65d115d358bde72f6b8abdbb8a23170"}, - {file = "coincurve-17.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8c571445b166c714af4f8155e38a894376c16c0431e88963f2fff474a9985d87"}, - {file = "coincurve-17.0.0-py3-none-win32.whl", hash = "sha256:b956b0b2c85e25a7d00099970ff5d8338254b45e46f0a940f4a2379438ce0dde"}, - {file = "coincurve-17.0.0-py3-none-win_amd64.whl", hash = "sha256:630388080da3026e0b0176cc6762eaabecba857ee3fc85767577dea063ea7c6e"}, - {file = "coincurve-17.0.0.tar.gz", hash = "sha256:68da55aff898702952fda3ee04fd6ed60bb6b91f919c69270786ed766b548b93"}, -] - -[package.dependencies] -asn1crypto = "*" -cffi = ">=1.3.0" - [[package]] name = "colorama" version = "0.4.6" @@ -526,136 +389,6 @@ pycryptodome = ">=3.18.0,<4.0.0" python-dateutil = "*" requests = "*" -[[package]] -name = "cytoolz" -version = "0.12.3" -description = "Cython implementation of Toolz: High performance functional utilities" -optional = true -python-versions = ">=3.7" -files = [ - {file = "cytoolz-0.12.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bbe58e26c84b163beba0fbeacf6b065feabc8f75c6d3fe305550d33f24a2d346"}, - {file = "cytoolz-0.12.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c51b66ada9bfdb88cf711bf350fcc46f82b83a4683cf2413e633c31a64df6201"}, - {file = "cytoolz-0.12.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e70d9c615e5c9dc10d279d1e32e846085fe1fd6f08d623ddd059a92861f4e3dd"}, - {file = "cytoolz-0.12.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a83f4532707963ae1a5108e51fdfe1278cc8724e3301fee48b9e73e1316de64f"}, - {file = "cytoolz-0.12.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d028044524ee2e815f36210a793c414551b689d4f4eda28f8bbb0883ad78bf5f"}, - {file = "cytoolz-0.12.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c2875bcd1397d0627a09a4f9172fa513185ad302c63758efc15b8eb33cc2a98"}, - {file = "cytoolz-0.12.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:131ff4820e5d64a25d7ad3c3556f2d8aa65c66b3f021b03f8a8e98e4180dd808"}, - {file = "cytoolz-0.12.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:04afa90d9d9d18394c40d9bed48c51433d08b57c042e0e50c8c0f9799735dcbd"}, - {file = "cytoolz-0.12.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:dc1ca9c610425f9854323669a671fc163300b873731584e258975adf50931164"}, - {file = "cytoolz-0.12.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bfa3f8e01bc423a933f2e1c510cbb0632c6787865b5242857cc955cae220d1bf"}, - {file = "cytoolz-0.12.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:f702e295dddef5f8af4a456db93f114539b8dc2a7a9bc4de7c7e41d169aa6ec3"}, - {file = "cytoolz-0.12.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0fbad1fb9bb47e827d00e01992a099b0ba79facf5e5aa453be066033232ac4b5"}, - {file = "cytoolz-0.12.3-cp310-cp310-win32.whl", hash = "sha256:8587c3c3dbe78af90c5025288766ac10dc2240c1e76eb0a93a4e244c265ccefd"}, - {file = "cytoolz-0.12.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e45803d9e75ef90a2f859ef8f7f77614730f4a8ce1b9244375734567299d239"}, - {file = "cytoolz-0.12.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3ac4f2fb38bbc67ff1875b7d2f0f162a247f43bd28eb7c9d15e6175a982e558d"}, - {file = "cytoolz-0.12.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0cf1e1e96dd86829a0539baf514a9c8473a58fbb415f92401a68e8e52a34ecd5"}, - {file = "cytoolz-0.12.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08a438701c6141dd34eaf92e9e9a1f66e23a22f7840ef8a371eba274477de85d"}, - {file = "cytoolz-0.12.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6b6f11b0d7ed91be53166aeef2a23a799e636625675bb30818f47f41ad31821"}, - {file = "cytoolz-0.12.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7fde09384d23048a7b4ac889063761e44b89a0b64015393e2d1d21d5c1f534a"}, - {file = "cytoolz-0.12.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d3bfe45173cc8e6c76206be3a916d8bfd2214fb2965563e288088012f1dabfc"}, - {file = "cytoolz-0.12.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27513a5d5b6624372d63313574381d3217a66e7a2626b056c695179623a5cb1a"}, - {file = "cytoolz-0.12.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d294e5e81ff094fe920fd545052ff30838ea49f9e91227a55ecd9f3ca19774a0"}, - {file = "cytoolz-0.12.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:727b01a2004ddb513496507a695e19b5c0cfebcdfcc68349d3efd92a1c297bf4"}, - {file = "cytoolz-0.12.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:fe1e1779a39dbe83f13886d2b4b02f8c4b10755e3c8d9a89b630395f49f4f406"}, - {file = "cytoolz-0.12.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:de74ef266e2679c3bf8b5fc20cee4fc0271ba13ae0d9097b1491c7a9bcadb389"}, - {file = "cytoolz-0.12.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e04d22049233394e0b08193aca9737200b4a2afa28659d957327aa780ddddf2"}, - {file = "cytoolz-0.12.3-cp311-cp311-win32.whl", hash = "sha256:20d36430d8ac809186736fda735ee7d595b6242bdb35f69b598ef809ebfa5605"}, - {file = "cytoolz-0.12.3-cp311-cp311-win_amd64.whl", hash = "sha256:780c06110f383344d537f48d9010d79fa4f75070d214fc47f389357dd4f010b6"}, - {file = "cytoolz-0.12.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:86923d823bd19ce35805953b018d436f6b862edd6a7c8b747a13d52b39ed5716"}, - {file = "cytoolz-0.12.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a3e61acfd029bfb81c2c596249b508dfd2b4f72e31b7b53b62e5fb0507dd7293"}, - {file = "cytoolz-0.12.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd728f4e6051af6af234651df49319da1d813f47894d4c3c8ab7455e01703a37"}, - {file = "cytoolz-0.12.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fe8c6267caa7ec67bcc37e360f0d8a26bc3bdce510b15b97f2f2e0143bdd3673"}, - {file = "cytoolz-0.12.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99462abd8323c52204a2a0ce62454ce8fa0f4e94b9af397945c12830de73f27e"}, - {file = "cytoolz-0.12.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da125221b1fa25c690fcd030a54344cecec80074df018d906fc6a99f46c1e3a6"}, - {file = "cytoolz-0.12.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c18e351956f70db9e2d04ff02f28e9a41839250d3f936a4c8a1eabd1c3094d2"}, - {file = "cytoolz-0.12.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:921e6d2440ac758c4945c587b1d1d9b781b72737ac0c0ca5d5e02ca1db8bded2"}, - {file = "cytoolz-0.12.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1651a9bd591a8326329ce1d6336f3129161a36d7061a4d5ea9e5377e033364cf"}, - {file = "cytoolz-0.12.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8893223b87c2782bd59f9c4bd5c7bf733edd8728b523c93efb91d7468b486528"}, - {file = "cytoolz-0.12.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:e4d2961644153c5ae186db964aa9f6109da81b12df0f1d3494b4e5cf2c332ee2"}, - {file = "cytoolz-0.12.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:71b6eb97f6695f7ba8ce69c49b707a351c5f46fd97f5aeb5f6f2fb0d6e72b887"}, - {file = "cytoolz-0.12.3-cp312-cp312-win32.whl", hash = "sha256:cee3de65584e915053412cd178729ff510ad5f8f585c21c5890e91028283518f"}, - {file = "cytoolz-0.12.3-cp312-cp312-win_amd64.whl", hash = "sha256:9eef0d23035fa4dcfa21e570961e86c375153a7ee605cdd11a8b088c24f707f6"}, - {file = "cytoolz-0.12.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9a38332cfad2a91e89405b7c18b3f00e2edc951c225accbc217597d3e4e9fde"}, - {file = "cytoolz-0.12.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f501ae1353071fa5d6677437bbeb1aeb5622067dce0977cedc2c5ec5843b202"}, - {file = "cytoolz-0.12.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56f899758146a52e2f8cfb3fb6f4ca19c1e5814178c3d584de35f9e4d7166d91"}, - {file = "cytoolz-0.12.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:800f0526adf9e53d3c6acda748f4def1f048adaa780752f154da5cf22aa488a2"}, - {file = "cytoolz-0.12.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0976a3fcb81d065473173e9005848218ce03ddb2ec7d40dd6a8d2dba7f1c3ae"}, - {file = "cytoolz-0.12.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c835eab01466cb67d0ce6290601ebef2d82d8d0d0a285ed0d6e46989e4a7a71a"}, - {file = "cytoolz-0.12.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4fba0616fcd487e34b8beec1ad9911d192c62e758baa12fcb44448b9b6feae22"}, - {file = "cytoolz-0.12.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6f6e8207d732651e0204779e1ba5a4925c93081834570411f959b80681f8d333"}, - {file = "cytoolz-0.12.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:8119bf5961091cfe644784d0bae214e273b3b3a479f93ee3baab97bbd995ccfe"}, - {file = "cytoolz-0.12.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7ad1331cb68afeec58469c31d944a2100cee14eac221553f0d5218ace1a0b25d"}, - {file = "cytoolz-0.12.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:92c53d508fb8a4463acc85b322fa24734efdc66933a5c8661bdc862103a3373d"}, - {file = "cytoolz-0.12.3-cp37-cp37m-win32.whl", hash = "sha256:2c6dd75dae3d84fa8988861ab8b1189d2488cb8a9b8653828f9cd6126b5e7abd"}, - {file = "cytoolz-0.12.3-cp37-cp37m-win_amd64.whl", hash = "sha256:caf07a97b5220e6334dd32c8b6d8b2bd255ca694eca5dfe914bb5b880ee66cdb"}, - {file = "cytoolz-0.12.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ed0cfb9326747759e2ad81cb6e45f20086a273b67ac3a4c00b19efcbab007c60"}, - {file = "cytoolz-0.12.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:96a5a0292575c3697121f97cc605baf2fd125120c7dcdf39edd1a135798482ca"}, - {file = "cytoolz-0.12.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b76f2f50a789c44d6fd7f773ec43d2a8686781cd52236da03f7f7d7998989bee"}, - {file = "cytoolz-0.12.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2905fdccacc64b4beba37f95cab9d792289c80f4d70830b70de2fc66c007ec01"}, - {file = "cytoolz-0.12.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ebe23028eac51251f22ba01dba6587d30aa9c320372ca0c14eeab67118ec3f"}, - {file = "cytoolz-0.12.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96c715404a3825e37fe3966fe84c5f8a1f036e7640b2a02dbed96cac0c933451"}, - {file = "cytoolz-0.12.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bac0adffc1b6b6a4c5f1fd1dd2161afb720bcc771a91016dc6bdba59af0a5d3"}, - {file = "cytoolz-0.12.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:37441bf4a2a4e2e0fe9c3b0ea5e72db352f5cca03903977ffc42f6f6c5467be9"}, - {file = "cytoolz-0.12.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f04037302049cb30033f7fa4e1d0e44afe35ed6bfcf9b380fc11f2a27d3ed697"}, - {file = "cytoolz-0.12.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f37b60e66378e7a116931d7220f5352186abfcc950d64856038aa2c01944929c"}, - {file = "cytoolz-0.12.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ec9be3e4b6f86ea8b294d34c990c99d2ba6c526ef1e8f46f1d52c263d4f32cd7"}, - {file = "cytoolz-0.12.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0e9199c9e3fbf380a92b8042c677eb9e7ed4bccb126de5e9c0d26f5888d96788"}, - {file = "cytoolz-0.12.3-cp38-cp38-win32.whl", hash = "sha256:18cd61e078bd6bffe088e40f1ed02001387c29174750abce79499d26fa57f5eb"}, - {file = "cytoolz-0.12.3-cp38-cp38-win_amd64.whl", hash = "sha256:765b8381d4003ceb1a07896a854eee2c31ebc950a4ae17d1e7a17c2a8feb2a68"}, - {file = "cytoolz-0.12.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b4a52dd2a36b0a91f7aa50ca6c8509057acc481a24255f6cb07b15d339a34e0f"}, - {file = "cytoolz-0.12.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:581f1ce479769fe7eeb9ae6d87eadb230df8c7c5fff32138162cdd99d7fb8fc3"}, - {file = "cytoolz-0.12.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46f505d4c6eb79585c8ad0b9dc140ef30a138c880e4e3b40230d642690e36366"}, - {file = "cytoolz-0.12.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59276021619b432a5c21c01cda8320b9cc7dbc40351ffc478b440bfccd5bbdd3"}, - {file = "cytoolz-0.12.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e44f4c25e1e7cf6149b499c74945a14649c8866d36371a2c2d2164e4649e7755"}, - {file = "cytoolz-0.12.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c64f8e60c1dd69e4d5e615481f2d57937746f4a6be2d0f86e9e7e3b9e2243b5e"}, - {file = "cytoolz-0.12.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33c63186f3bf9d7ef1347bc0537bb9a0b4111a0d7d6e619623cabc18fef0dc3b"}, - {file = "cytoolz-0.12.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fdddb9d988405f24035234f1e8d1653ab2e48cc2404226d21b49a129aefd1d25"}, - {file = "cytoolz-0.12.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6986632d8a969ea1e720990c818dace1a24c11015fd7c59b9fea0b65ef71f726"}, - {file = "cytoolz-0.12.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0ba1cbc4d9cd7571c917f88f4a069568e5121646eb5d82b2393b2cf84712cf2a"}, - {file = "cytoolz-0.12.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7d267ffc9a36c0a9a58c7e0adc9fa82620f22e4a72533e15dd1361f57fc9accf"}, - {file = "cytoolz-0.12.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95e878868a172a41fbf6c505a4b967309e6870e22adc7b1c3b19653d062711fa"}, - {file = "cytoolz-0.12.3-cp39-cp39-win32.whl", hash = "sha256:8e21932d6d260996f7109f2a40b2586070cb0a0cf1d65781e156326d5ebcc329"}, - {file = "cytoolz-0.12.3-cp39-cp39-win_amd64.whl", hash = "sha256:0d8edfbc694af6c9bda4db56643fb8ed3d14e47bec358c2f1417de9a12d6d1fb"}, - {file = "cytoolz-0.12.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:55f9bd1ae6c2a27eda5abe2a0b65a83029d2385c5a1da7b8ef47af5905d7e905"}, - {file = "cytoolz-0.12.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2d271393c378282727f1231d40391ae93b93ddc0997448acc21dd0cb6a1e56d"}, - {file = "cytoolz-0.12.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee98968d6a66ee83a8ceabf31182189ab5d8598998c8ce69b6d5843daeb2db60"}, - {file = "cytoolz-0.12.3-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01cfb8518828c1189200c02a5010ea404407fb18fd5589e29c126e84bbeadd36"}, - {file = "cytoolz-0.12.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:456395d7aec01db32bf9e6db191d667347c78d8d48e77234521fa1078f60dabb"}, - {file = "cytoolz-0.12.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:cd88028bb897fba99ddd84f253ca6bef73ecb7bdf3f3cf25bc493f8f97d3c7c5"}, - {file = "cytoolz-0.12.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59b19223e7f7bd7a73ec3aa6fdfb73b579ff09c2bc0b7d26857eec2d01a58c76"}, - {file = "cytoolz-0.12.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a79d72b08048a0980a59457c239555f111ac0c8bdc140c91a025f124104dbb4"}, - {file = "cytoolz-0.12.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1dd70141b32b717696a72b8876e86bc9c6f8eff995c1808e299db3541213ff82"}, - {file = "cytoolz-0.12.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:a1445c91009eb775d479e88954c51d0b4cf9a1e8ce3c503c2672d17252882647"}, - {file = "cytoolz-0.12.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ca6a9a9300d5bda417d9090107c6d2b007683efc59d63cc09aca0e7930a08a85"}, - {file = "cytoolz-0.12.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be6feb903d2a08a4ba2e70e950e862fd3be9be9a588b7c38cee4728150a52918"}, - {file = "cytoolz-0.12.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92b6f43f086e5a965d33d62a145ae121b4ccb6e0789ac0acc895ce084fec8c65"}, - {file = "cytoolz-0.12.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:534fa66db8564d9b13872d81d54b6b09ae592c585eb826aac235bd6f1830f8ad"}, - {file = "cytoolz-0.12.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:fea649f979def23150680de1bd1d09682da3b54932800a0f90f29fc2a6c98ba8"}, - {file = "cytoolz-0.12.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a447247ed312dd64e3a8d9483841ecc5338ee26d6e6fbd29cd373ed030db0240"}, - {file = "cytoolz-0.12.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba3f843aa89f35467b38c398ae5b980a824fdbdb94065adc6ec7c47a0a22f4c7"}, - {file = "cytoolz-0.12.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:582c22f97a380211fb36a7b65b1beeb84ea11d82015fa84b054be78580390082"}, - {file = "cytoolz-0.12.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47feb089506fc66e1593cd9ade3945693a9d089a445fbe9a11385cab200b9f22"}, - {file = "cytoolz-0.12.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ba9002d2f043943744a9dc8e50a47362bcb6e6f360dc0a1abcb19642584d87bb"}, - {file = "cytoolz-0.12.3.tar.gz", hash = "sha256:4503dc59f4ced53a54643272c61dc305d1dbbfbd7d6bdf296948de9f34c3a282"}, -] - -[package.dependencies] -toolz = ">=0.8.0" - -[package.extras] -cython = ["cython"] - -[[package]] -name = "distlib" -version = "0.3.8" -description = "Distribution utilities" -optional = false -python-versions = "*" -files = [ - {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, - {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, -] - [[package]] name = "ecdsa" version = "0.18.0" @@ -674,172 +407,6 @@ six = ">=1.9.0" gmpy = ["gmpy"] gmpy2 = ["gmpy2"] -[[package]] -name = "eciespy" -version = "0.3.13" -description = "Elliptic Curve Integrated Encryption Scheme for secp256k1 in Python" -optional = true -python-versions = ">=3.7,<4.0" -files = [ - {file = "eciespy-0.3.13-py3-none-any.whl", hash = "sha256:80981063dc5aaa43260963ad9f9454ddeaaf452aed09c23cb90d51360b77ca92"}, - {file = "eciespy-0.3.13.tar.gz", hash = "sha256:41426f6263775c1b797c58cadbc2805be9d1a8102ae13e8831c153d1651aaee2"}, -] - -[package.dependencies] -coincurve = ">=13,<18" -eth-keys = ">=0.4.0,<0.5.0" -pycryptodome = ">=3.15.0,<4.0.0" - -[[package]] -name = "eth-hash" -version = "0.7.0" -description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" -optional = true -python-versions = ">=3.8, <4" -files = [ - {file = "eth-hash-0.7.0.tar.gz", hash = "sha256:bacdc705bfd85dadd055ecd35fd1b4f846b671add101427e089a4ca2e8db310a"}, - {file = "eth_hash-0.7.0-py3-none-any.whl", hash = "sha256:b8d5a230a2b251f4a291e3164a23a14057c4a6de4b0aa4a16fa4dc9161b57e2f"}, -] - -[package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -pycryptodome = ["pycryptodome (>=3.6.6,<4)"] -pysha3 = ["pysha3 (>=1.0.0,<2.0.0)", "safe-pysha3 (>=1.0.0)"] -test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] - -[[package]] -name = "eth-keys" -version = "0.4.0" -description = "Common API for Ethereum key operations." -optional = true -python-versions = "*" -files = [ - {file = "eth-keys-0.4.0.tar.gz", hash = "sha256:7d18887483bc9b8a3fdd8e32ddcb30044b9f08fcb24a380d93b6eee3a5bb3216"}, - {file = "eth_keys-0.4.0-py3-none-any.whl", hash = "sha256:e07915ffb91277803a28a379418bdd1fad1f390c38ad9353a0f189789a440d5d"}, -] - -[package.dependencies] -eth-typing = ">=3.0.0,<4" -eth-utils = ">=2.0.0,<3.0.0" - -[package.extras] -coincurve = ["coincurve (>=7.0.0,<16.0.0)"] -dev = ["asn1tools (>=0.146.2,<0.147)", "bumpversion (==0.5.3)", "eth-hash[pycryptodome]", "eth-hash[pysha3]", "eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)", "factory-boy (>=3.0.1,<3.1)", "flake8 (==3.0.4)", "hypothesis (>=5.10.3,<6.0.0)", "mypy (==0.782)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)", "tox (==3.20.0)", "twine"] -eth-keys = ["eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)"] -lint = ["flake8 (==3.0.4)", "mypy (==0.782)"] -test = ["asn1tools (>=0.146.2,<0.147)", "eth-hash[pycryptodome]", "eth-hash[pysha3]", "factory-boy (>=3.0.1,<3.1)", "hypothesis (>=5.10.3,<6.0.0)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)"] - -[[package]] -name = "eth-typing" -version = "3.5.2" -description = "eth-typing: Common type annotations for ethereum python packages" -optional = true -python-versions = ">=3.7.2, <4" -files = [ - {file = "eth-typing-3.5.2.tar.gz", hash = "sha256:22bf051ddfaa35ff827c30090de167e5c5b8cc6d343f7f35c9b1c7553f6ab64d"}, - {file = "eth_typing-3.5.2-py3-none-any.whl", hash = "sha256:1842e628fb1ffa929b94f89a9d33caafbeb9978dc96abb6036a12bc91f1c624b"}, -] - -[package.dependencies] -typing-extensions = ">=4.0.1" - -[package.extras] -dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "ipython", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "types-setuptools", "wheel"] -docs = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -lint = ["black (>=23)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)", "types-setuptools"] -test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] - -[[package]] -name = "eth-utils" -version = "2.3.1" -description = "eth-utils: Common utility functions for python code that interacts with Ethereum" -optional = true -python-versions = ">=3.7,<4" -files = [ - {file = "eth-utils-2.3.1.tar.gz", hash = "sha256:56a969b0536d4969dcb27e580521de35abf2dbed8b1bf072b5c80770c4324e27"}, - {file = "eth_utils-2.3.1-py3-none-any.whl", hash = "sha256:614eedc5ffcaf4e6708ca39e23b12bd69526a312068c1170c773bd1307d13972"}, -] - -[package.dependencies] -cytoolz = {version = ">=0.10.1", markers = "implementation_name == \"cpython\""} -eth-hash = ">=0.3.1" -eth-typing = ">=3.0.0" -toolz = {version = ">0.8.2", markers = "implementation_name == \"pypy\""} - -[package.extras] -dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "flake8 (==3.8.3)", "hypothesis (>=4.43.0)", "ipython", "isort (>=5.11.0)", "mypy (==0.971)", "pydocstyle (>=5.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "types-setuptools", "wheel"] -docs = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -lint = ["black (>=23)", "flake8 (==3.8.3)", "isort (>=5.11.0)", "mypy (==0.971)", "pydocstyle (>=5.0.0)", "types-setuptools"] -test = ["hypothesis (>=4.43.0)", "mypy (==0.971)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "types-setuptools"] - -[[package]] -name = "exceptiongroup" -version = "1.2.0" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, - {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "fastapi" -version = "0.97.0" -description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -optional = true -python-versions = ">=3.7" -files = [ - {file = "fastapi-0.97.0-py3-none-any.whl", hash = "sha256:95d757511c596409930bd20673358d4a4d709004edb85c5d24d6ffc48fabcbf2"}, - {file = "fastapi-0.97.0.tar.gz", hash = "sha256:b53248ee45f64f19bb7600953696e3edf94b0f7de94df1e5433fc5c6136fa986"}, -] - -[package.dependencies] -pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" -starlette = ">=0.27.0,<0.28.0" - -[package.extras] -all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] - -[[package]] -name = "fetchai-babble" -version = "0.4.1" -description = "A simple python library for interacting with the Fetch.ai messaging service (called Memorandum)" -optional = true -python-versions = ">=3.7,<4.0" -files = [ - {file = "fetchai_babble-0.4.1-py3-none-any.whl", hash = "sha256:96de5491145e8ed311f526f1516eed4807d99b1eda9fc221c5027b22a72f2ef5"}, - {file = "fetchai_babble-0.4.1.tar.gz", hash = "sha256:03220e7c42feb1344f10f8c3f157508c58496b34303259960fafcd3fff0d4d3b"}, -] - -[package.dependencies] -bech32 = ">=1.2.0,<2.0.0" -ecdsa = ">=0.18.0,<0.19.0" -eciespy = ">=0.3.13,<0.4.0" -pycryptodome = ">=3.16.0,<4.0.0" -pyjwt = ">=2.6.0,<3.0.0" -requests = ">=2.28.2,<3.0.0" - -[[package]] -name = "filelock" -version = "3.13.3" -description = "A platform independent file lock." -optional = false -python-versions = ">=3.8" -files = [ - {file = "filelock-3.13.3-py3-none-any.whl", hash = "sha256:5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb"}, - {file = "filelock-3.13.3.tar.gz", hash = "sha256:a79895a25bbefdf55d1a2a0a80968f7dbb28edcd6d4234a0afb3f37ecde4b546"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] -typing = ["typing-extensions (>=4.8)"] - [[package]] name = "frozenlist" version = "1.4.1" @@ -926,57 +493,6 @@ files = [ {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, ] -[[package]] -name = "geographiclib" -version = "2.0" -description = "The geodesic routines from GeographicLib" -optional = true -python-versions = ">=3.7" -files = [ - {file = "geographiclib-2.0-py3-none-any.whl", hash = "sha256:6b7225248e45ff7edcee32becc4e0a1504c606ac5ee163a5656d482e0cd38734"}, - {file = "geographiclib-2.0.tar.gz", hash = "sha256:f7f41c85dc3e1c2d3d935ec86660dc3b2c848c83e17f9a9e51ba9d5146a15859"}, -] - -[[package]] -name = "geopy" -version = "2.4.1" -description = "Python Geocoding Toolbox" -optional = true -python-versions = ">=3.7" -files = [ - {file = "geopy-2.4.1-py3-none-any.whl", hash = "sha256:ae8b4bc5c1131820f4d75fce9d4aaaca0c85189b3aa5d64c3dcaf5e3b7b882a7"}, - {file = "geopy-2.4.1.tar.gz", hash = "sha256:50283d8e7ad07d89be5cb027338c6365a32044df3ae2556ad3f52f4840b3d0d1"}, -] - -[package.dependencies] -geographiclib = ">=1.52,<3" - -[package.extras] -aiohttp = ["aiohttp"] -dev = ["coverage", "flake8 (>=5.0,<5.1)", "isort (>=5.10.0,<5.11.0)", "pytest (>=3.10)", "pytest-asyncio (>=0.17)", "readme-renderer", "sphinx (<=4.3.2)", "sphinx-issues", "sphinx-rtd-theme (>=0.5.0)"] -dev-docs = ["readme-renderer", "sphinx (<=4.3.2)", "sphinx-issues", "sphinx-rtd-theme (>=0.5.0)"] -dev-lint = ["flake8 (>=5.0,<5.1)", "isort (>=5.10.0,<5.11.0)"] -dev-test = ["coverage", "pytest (>=3.10)", "pytest-asyncio (>=0.17)", "sphinx (<=4.3.2)"] -requests = ["requests (>=2.16.2)", "urllib3 (>=1.24.2)"] -timezone = ["pytz"] - -[[package]] -name = "ghp-import" -version = "2.1.0" -description = "Copy your docs directly to the gh-pages branch." -optional = false -python-versions = "*" -files = [ - {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, - {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, -] - -[package.dependencies] -python-dateutil = ">=2.8.1" - -[package.extras] -dev = ["flake8", "markdown", "twine", "wheel"] - [[package]] name = "googleapis-common-protos" version = "1.63.0" @@ -1071,20 +587,6 @@ files = [ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] -[[package]] -name = "identify" -version = "2.5.35" -description = "File identification library for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"}, - {file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"}, -] - -[package.extras] -license = ["ukkonen"] - [[package]] name = "idna" version = "3.6" @@ -1096,64 +598,17 @@ files = [ {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] -[[package]] -name = "importlib-metadata" -version = "7.1.0" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, - {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, -] - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - [[package]] name = "iso8601" -version = "1.1.0" +version = "0.1.16" description = "Simple module to parse ISO 8601 dates" -optional = true -python-versions = ">=3.6.2,<4.0" -files = [ - {file = "iso8601-1.1.0-py3-none-any.whl", hash = "sha256:8400e90141bf792bce2634df533dc57e3bee19ea120a87bebcd3da89a58ad73f"}, - {file = "iso8601-1.1.0.tar.gz", hash = "sha256:32811e7b81deee2063ea6d2e94f8819a86d1f3811e49d23623a41fa832bef03f"}, -] - -[[package]] -name = "jinja2" -version = "3.1.3" -description = "A very fast and expressive template engine." optional = false -python-versions = ">=3.7" +python-versions = "*" files = [ - {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, - {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, + {file = "iso8601-0.1.16-py2.py3-none-any.whl", hash = "sha256:906714829fedbc89955d52806c903f2332e3948ed94e31e85037f9e0226b8376"}, + {file = "iso8601-0.1.16.tar.gz", hash = "sha256:36532f77cc800594e8f16641edae7f1baf7932f05d8e508545b95fc53c6dc85b"}, ] -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - [[package]] name = "jsonschema" version = "4.21.1" @@ -1189,175 +644,6 @@ files = [ [package.dependencies] referencing = ">=0.31.0" -[[package]] -name = "markdown" -version = "3.6" -description = "Python implementation of John Gruber's Markdown." -optional = false -python-versions = ">=3.8" -files = [ - {file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"}, - {file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"}, -] - -[package.dependencies] -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} - -[package.extras] -docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] -testing = ["coverage", "pyyaml"] - -[[package]] -name = "markupsafe" -version = "2.1.5" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.7" -files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, -] - -[[package]] -name = "mergedeep" -version = "1.3.4" -description = "A deep merge function for 🐍." -optional = false -python-versions = ">=3.6" -files = [ - {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, - {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, -] - -[[package]] -name = "mkdocs" -version = "1.5.3" -description = "Project documentation with Markdown." -optional = false -python-versions = ">=3.7" -files = [ - {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"}, - {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"}, -] - -[package.dependencies] -click = ">=7.0" -colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} -ghp-import = ">=1.0" -importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} -jinja2 = ">=2.11.1" -markdown = ">=3.2.1" -markupsafe = ">=2.0.1" -mergedeep = ">=1.3.4" -packaging = ">=20.5" -pathspec = ">=0.11.1" -platformdirs = ">=2.2.0" -pyyaml = ">=5.1" -pyyaml-env-tag = ">=0.1" -watchdog = ">=2.0" - -[package.extras] -i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] - -[[package]] -name = "mkdocs-material" -version = "9.5.17" -description = "Documentation that simply works" -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_material-9.5.17-py3-none-any.whl", hash = "sha256:14a2a60119a785e70e765dd033e6211367aca9fc70230e577c1cf6a326949571"}, - {file = "mkdocs_material-9.5.17.tar.gz", hash = "sha256:06ae1275a72db1989cf6209de9e9ecdfbcfdbc24c58353877b2bb927dbe413e4"}, -] - -[package.dependencies] -babel = ">=2.10,<3.0" -colorama = ">=0.4,<1.0" -jinja2 = ">=3.0,<4.0" -markdown = ">=3.2,<4.0" -mkdocs = ">=1.5.3,<1.6.0" -mkdocs-material-extensions = ">=1.3,<2.0" -paginate = ">=0.5,<1.0" -pygments = ">=2.16,<3.0" -pymdown-extensions = ">=10.2,<11.0" -regex = ">=2022.4" -requests = ">=2.26,<3.0" - -[package.extras] -git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"] -imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"] -recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] - -[[package]] -name = "mkdocs-material-extensions" -version = "1.3.1" -description = "Extension pack for Python Markdown and MkDocs Material." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, - {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, -] - [[package]] name = "msgpack" version = "1.0.8" @@ -1420,7 +706,7 @@ files = [ {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, - {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, + {file = "msgpack-1.0.8-py3-none-any.whl", hash = "sha256:24f727df1e20b9876fa6e95f840a2a2651e34c0ad147676356f4bf5fbb0206ca"}, ] [[package]] @@ -1523,19 +809,16 @@ files = [ ] [[package]] -name = "nodeenv" -version = "1.8.0" -description = "Node.js virtual environment builder" +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +python-versions = ">=3.5" files = [ - {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, - {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] -[package.dependencies] -setuptools = "*" - [[package]] name = "packaging" version = "24.0" @@ -1547,16 +830,6 @@ files = [ {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, ] -[[package]] -name = "paginate" -version = "0.5.6" -description = "Divides large result sets into pages for easier browsing" -optional = false -python-versions = "*" -files = [ - {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"}, -] - [[package]] name = "pathspec" version = "0.12.1" @@ -1583,39 +856,6 @@ files = [ docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -[[package]] -name = "pluggy" -version = "1.4.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, - {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "pre-commit" -version = "3.7.0" -description = "A framework for managing and maintaining multi-language pre-commit hooks." -optional = false -python-versions = ">=3.9" -files = [ - {file = "pre_commit-3.7.0-py2.py3-none-any.whl", hash = "sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab"}, - {file = "pre_commit-3.7.0.tar.gz", hash = "sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060"}, -] - -[package.dependencies] -cfgv = ">=2.0.0" -identify = ">=1.0.0" -nodeenv = ">=0.11.1" -pyyaml = ">=5.1" -virtualenv = ">=20.10.0" - [[package]] name = "protobuf" version = "4.25.3" @@ -1636,17 +876,6 @@ files = [ {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, ] -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = true -python-versions = ">=3.8" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - [[package]] name = "pycryptodome" version = "3.20.0" @@ -1740,102 +969,17 @@ typing-extensions = ">=4.2.0" dotenv = ["python-dotenv (>=0.10.4)"] email = ["email-validator (>=1.0.3)"] -[[package]] -name = "pygments" -version = "2.17.2" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.7" -files = [ - {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, - {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, -] - -[package.extras] -plugins = ["importlib-metadata"] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pyjwt" -version = "2.8.0" -description = "JSON Web Token implementation in Python" -optional = true -python-versions = ">=3.7" -files = [ - {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, - {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, -] - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pymdown-extensions" -version = "10.7.1" -description = "Extension pack for Python Markdown." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pymdown_extensions-10.7.1-py3-none-any.whl", hash = "sha256:f5cc7000d7ff0d1ce9395d216017fa4df3dde800afb1fb72d1c7d3fd35e710f4"}, - {file = "pymdown_extensions-10.7.1.tar.gz", hash = "sha256:c70e146bdd83c744ffc766b4671999796aba18842b268510a329f7f64700d584"}, -] - -[package.dependencies] -markdown = ">=3.5" -pyyaml = "*" - -[package.extras] -extra = ["pygments (>=2.12)"] - -[[package]] -name = "pyngrok" -version = "5.2.3" -description = "A Python wrapper for ngrok." -optional = true -python-versions = ">=3.5" -files = [ - {file = "pyngrok-5.2.3.tar.gz", hash = "sha256:0704c4f67553012deb5d2be473ab1a2822d153b5da83eaac4d518063f12d440c"}, -] - -[package.dependencies] -PyYAML = "*" - [[package]] name = "pypika-tortoise" version = "0.1.6" description = "Forked from pypika and streamline just for tortoise-orm" -optional = true +optional = false python-versions = ">=3.7,<4.0" files = [ {file = "pypika-tortoise-0.1.6.tar.gz", hash = "sha256:d802868f479a708e3263724c7b5719a26ad79399b2a70cea065f4a4cadbebf36"}, {file = "pypika_tortoise-0.1.6-py3-none-any.whl", hash = "sha256:2d68bbb7e377673743cff42aa1059f3a80228d411fbcae591e4465e173109fd8"}, ] -[[package]] -name = "pytest" -version = "7.4.4" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} - -[package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -1854,87 +998,13 @@ six = ">=1.5" name = "pytz" version = "2024.1" description = "World timezone definitions, modern and historical" -optional = true +optional = false python-versions = "*" files = [ {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, ] -[[package]] -name = "pyyaml" -version = "6.0.1" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, -] - -[[package]] -name = "pyyaml-env-tag" -version = "0.1" -description = "A custom YAML tag for referencing environment variables in YAML files. " -optional = false -python-versions = ">=3.6" -files = [ - {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, - {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, -] - -[package.dependencies] -pyyaml = "*" - [[package]] name = "referencing" version = "0.34.0" @@ -1950,108 +1020,6 @@ files = [ attrs = ">=22.2.0" rpds-py = ">=0.7.0" -[[package]] -name = "regex" -version = "2023.12.25" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.7" -files = [ - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, - {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, - {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, - {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, - {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, - {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, - {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, - {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, - {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, - {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, - {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, - {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, - {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, - {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, - {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, -] - [[package]] name = "requests" version = "2.31.0" @@ -2181,48 +1149,6 @@ files = [ {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, ] -[[package]] -name = "ruff" -version = "0.3.5" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -files = [ - {file = "ruff-0.3.5-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:aef5bd3b89e657007e1be6b16553c8813b221ff6d92c7526b7e0227450981eac"}, - {file = "ruff-0.3.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:89b1e92b3bd9fca249153a97d23f29bed3992cff414b222fcd361d763fc53f12"}, - {file = "ruff-0.3.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e55771559c89272c3ebab23326dc23e7f813e492052391fe7950c1a5a139d89"}, - {file = "ruff-0.3.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dabc62195bf54b8a7876add6e789caae0268f34582333cda340497c886111c39"}, - {file = "ruff-0.3.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a05f3793ba25f194f395578579c546ca5d83e0195f992edc32e5907d142bfa3"}, - {file = "ruff-0.3.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dfd3504e881082959b4160ab02f7a205f0fadc0a9619cc481982b6837b2fd4c0"}, - {file = "ruff-0.3.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87258e0d4b04046cf1d6cc1c56fadbf7a880cc3de1f7294938e923234cf9e498"}, - {file = "ruff-0.3.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:712e71283fc7d9f95047ed5f793bc019b0b0a29849b14664a60fd66c23b96da1"}, - {file = "ruff-0.3.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a532a90b4a18d3f722c124c513ffb5e5eaff0cc4f6d3aa4bda38e691b8600c9f"}, - {file = "ruff-0.3.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:122de171a147c76ada00f76df533b54676f6e321e61bd8656ae54be326c10296"}, - {file = "ruff-0.3.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d80a6b18a6c3b6ed25b71b05eba183f37d9bc8b16ace9e3d700997f00b74660b"}, - {file = "ruff-0.3.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a7b6e63194c68bca8e71f81de30cfa6f58ff70393cf45aab4c20f158227d5936"}, - {file = "ruff-0.3.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a759d33a20c72f2dfa54dae6e85e1225b8e302e8ac655773aff22e542a300985"}, - {file = "ruff-0.3.5-py3-none-win32.whl", hash = "sha256:9d8605aa990045517c911726d21293ef4baa64f87265896e491a05461cae078d"}, - {file = "ruff-0.3.5-py3-none-win_amd64.whl", hash = "sha256:dc56bb16a63c1303bd47563c60482a1512721053d93231cf7e9e1c6954395a0e"}, - {file = "ruff-0.3.5-py3-none-win_arm64.whl", hash = "sha256:faeeae9905446b975dcf6d4499dc93439b131f1443ee264055c5716dd947af55"}, - {file = "ruff-0.3.5.tar.gz", hash = "sha256:a067daaeb1dc2baf9b82a32dae67d154d95212080c80435eb052d95da647763d"}, -] - -[[package]] -name = "setuptools" -version = "69.2.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "setuptools-69.2.0-py3-none-any.whl", hash = "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c"}, - {file = "setuptools-69.2.0.tar.gz", hash = "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - [[package]] name = "six" version = "1.16.0" @@ -2234,35 +1160,6 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = true -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "starlette" -version = "0.27.0" -description = "The little ASGI library that shines." -optional = true -python-versions = ">=3.7" -files = [ - {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, - {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, -] - -[package.dependencies] -anyio = ">=3.4.0,<5" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} - -[package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] - [[package]] name = "tomli" version = "2.0.1" @@ -2274,41 +1171,28 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -[[package]] -name = "toolz" -version = "0.12.1" -description = "List processing tools and functional utilities" -optional = true -python-versions = ">=3.7" -files = [ - {file = "toolz-0.12.1-py3-none-any.whl", hash = "sha256:d22731364c07d72eea0a0ad45bafb2c2937ab6fd38a3507bf55eae8744aa7d85"}, - {file = "toolz-0.12.1.tar.gz", hash = "sha256:ecca342664893f177a13dac0e6b41cbd8ac25a358e5f215316d43e2100224f4d"}, -] - [[package]] name = "tortoise-orm" -version = "0.19.3" +version = "0.17.8" description = "Easy async ORM for python, built with relations in mind" -optional = true +optional = false python-versions = ">=3.7,<4.0" files = [ - {file = "tortoise_orm-0.19.3-py3-none-any.whl", hash = "sha256:9e368820c70a0866ef9c521d43aa5503485bd7a20a561edc0933b7b0f7036fbc"}, - {file = "tortoise_orm-0.19.3.tar.gz", hash = "sha256:ca574bca5191f55608f9013314b1f5d1c6ffd4165a1fcc2f60f6c902f529b3b6"}, + {file = "tortoise-orm-0.17.8.tar.gz", hash = "sha256:1f5020e9964d32a4d6ed685d466b5d7285de328a63ee92ee988c1e4baf8fefbf"}, + {file = "tortoise_orm-0.17.8-py3-none-any.whl", hash = "sha256:f18c41bb83be4748a6ca259ed7309ca954b35f5790971824bbc79a11d2b1ef3b"}, ] [package.dependencies] aiosqlite = ">=0.16.0,<0.18.0" -iso8601 = ">=1.0.2,<2.0.0" -pypika-tortoise = ">=0.1.6,<0.2.0" +iso8601 = ">=0.1.13,<0.2.0" +pypika-tortoise = ">=0.1.1,<0.2.0" pytz = "*" [package.extras] -accel = ["ciso8601", "orjson", "uvloop"] +accel = ["ciso8601 (>=2.1.2,<3.0.0)", "python-rapidjson", "uvloop (>=0.14.0,<0.15.0)"] aiomysql = ["aiomysql"] -asyncmy = ["asyncmy (>=0.2.5,<0.3.0)"] -asyncodbc = ["asyncodbc (>=0.1.1,<0.2.0)"] +asyncmy = ["asyncmy"] asyncpg = ["asyncpg"] -psycopg = ["psycopg[binary,pool] (==3.0.12)"] [[package]] name = "typing-extensions" @@ -2321,6 +1205,36 @@ files = [ {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, ] +[[package]] +name = "uagents" +version = "0.11.0" +description = "Lightweight framework for rapid agent-based development" +optional = false +python-versions = ">=3.9,<3.13" +files = [ + {file = "uagents-0.11.0-py3-none-any.whl", hash = "sha256:6ed259ed4e1ba79e157d85cdecc312f3036dac019431fc35730e75e62c72d13b"}, + {file = "uagents-0.11.0.tar.gz", hash = "sha256:f9bb4c0764a391c8d26fef4c229afcae70ee239e45310a15fa57e03b42f19e81"}, +] + +[package.dependencies] +aiohttp = ">=3.8.3,<4.0.0" +apispec = ">=6.0.2,<7.0.0" +bech32 = ">=1.2.0,<2.0.0" +cosmpy = ">=0.9.2,<0.10.0" +ecdsa = ">=0.18.0,<0.19.0" +msgpack = ">=1.0.4,<2.0.0" +pydantic = ">=1.10.2,<2.0.0" +uvicorn = ">=0.20.0,<0.21.0" +websockets = ">=10.4,<11.0" + +[package.extras] +all = ["fastapi (>=0.97.0,<0.98.0)", "fetchai-babble (>=0.4.1,<0.5.0)", "geopy (>=2.3.0,<3.0.0)", "pyngrok (>=5.2.3,<6.0.0)", "tortoise-orm (>=0.19.2,<0.20.0)"] +geo = ["geopy (>=2.3.0,<3.0.0)"] +orm = ["tortoise-orm (>=0.19.2,<0.20.0)"] +proxy = ["fastapi (>=0.97.0,<0.98.0)"] +remote-agents = ["pyngrok (>=5.2.3,<6.0.0)"] +wallet = ["fetchai-babble (>=0.4.1,<0.5.0)"] + [[package]] name = "urllib3" version = "2.2.1" @@ -2356,67 +1270,6 @@ h11 = ">=0.8" [package.extras] standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] -[[package]] -name = "virtualenv" -version = "20.25.1" -description = "Virtual Python Environment builder" -optional = false -python-versions = ">=3.7" -files = [ - {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"}, - {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"}, -] - -[package.dependencies] -distlib = ">=0.3.7,<1" -filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<5" - -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] - -[[package]] -name = "watchdog" -version = "4.0.0" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.8" -files = [ - {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:39cb34b1f1afbf23e9562501673e7146777efe95da24fab5707b88f7fb11649b"}, - {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c522392acc5e962bcac3b22b9592493ffd06d1fc5d755954e6be9f4990de932b"}, - {file = "watchdog-4.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c47bdd680009b11c9ac382163e05ca43baf4127954c5f6d0250e7d772d2b80c"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8350d4055505412a426b6ad8c521bc7d367d1637a762c70fdd93a3a0d595990b"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:11e12fafb13372e18ca1bbf12d50f593e7280646687463dd47730fd4f4d5d257"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5369136a6474678e02426bd984466343924d1df8e2fd94a9b443cb7e3aa20d19"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76ad8484379695f3fe46228962017a7e1337e9acadafed67eb20aabb175df98b"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:45cc09cc4c3b43fb10b59ef4d07318d9a3ecdbff03abd2e36e77b6dd9f9a5c85"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eed82cdf79cd7f0232e2fdc1ad05b06a5e102a43e331f7d041e5f0e0a34a51c4"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba30a896166f0fee83183cec913298151b73164160d965af2e93a20bbd2ab605"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d18d7f18a47de6863cd480734613502904611730f8def45fc52a5d97503e5101"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2895bf0518361a9728773083908801a376743bcc37dfa252b801af8fd281b1ca"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87e9df830022488e235dd601478c15ad73a0389628588ba0b028cb74eb72fed8"}, - {file = "watchdog-4.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6e949a8a94186bced05b6508faa61b7adacc911115664ccb1923b9ad1f1ccf7b"}, - {file = "watchdog-4.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6a4db54edea37d1058b08947c789a2354ee02972ed5d1e0dca9b0b820f4c7f92"}, - {file = "watchdog-4.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d31481ccf4694a8416b681544c23bd271f5a123162ab603c7d7d2dd7dd901a07"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:6a9c71a0b02985b4b0b6d14b875a6c86ddea2fdbebd0c9a720a806a8bbffc69f"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:557ba04c816d23ce98a06e70af6abaa0485f6d94994ec78a42b05d1c03dcbd50"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:d0f9bd1fd919134d459d8abf954f63886745f4660ef66480b9d753a7c9d40927"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f9b2fdca47dc855516b2d66eef3c39f2672cbf7e7a42e7e67ad2cbfcd6ba107d"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:73c7a935e62033bd5e8f0da33a4dcb763da2361921a69a5a95aaf6c93aa03a87"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269"}, - {file = "watchdog-4.0.0-py3-none-win32.whl", hash = "sha256:8f9a542c979df62098ae9c58b19e03ad3df1c9d8c6895d96c0d51da17b243b1c"}, - {file = "watchdog-4.0.0-py3-none-win_amd64.whl", hash = "sha256:f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245"}, - {file = "watchdog-4.0.0-py3-none-win_ia64.whl", hash = "sha256:9a03e16e55465177d416699331b0f3564138f1807ecc5f2de9d55d8f188d08c7"}, - {file = "watchdog-4.0.0.tar.gz", hash = "sha256:e3e7065cbdabe6183ab82199d7a4f6b3ba0a438c5a512a68559846ccb76a78ec"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - [[package]] name = "websockets" version = "10.4" @@ -2598,30 +1451,7 @@ files = [ idna = ">=2.0" multidict = ">=4.0" -[[package]] -name = "zipp" -version = "3.18.1" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.8" -files = [ - {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"}, - {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] - -[extras] -all = ["fastapi", "fetchai-babble", "geopy", "pyngrok", "tortoise-orm"] -geo = ["geopy"] -orm = ["tortoise-orm"] -proxy = ["fastapi"] -remote-agents = ["pyngrok"] -wallet = ["fetchai-babble"] - [metadata] lock-version = "2.0" -python-versions = ">=3.9,<3.13" -content-hash = "e51915f239868ec296faf2d3ced120770763b4bb9219da96981556b976de1859" +python-versions = ">=3.10,<3.12" +content-hash = "93a5657483ae06cb218f76420e3147df1f09aee87622bc1ee00c1cc0918a94c3" diff --git a/integrations/tortoise-ORM/pyproject.toml b/integrations/tortoise-ORM/pyproject.toml new file mode 100644 index 00000000..3abb1ad0 --- /dev/null +++ b/integrations/tortoise-ORM/pyproject.toml @@ -0,0 +1,17 @@ +[tool.poetry] +name = "tortoise-db" +version = "0.1.0" +description = "" +authors = ["Alejandro-Morales "] +readme = "README.md" + +[tool.poetry.dependencies] +python = ">=3.10,<3.12" +uagents = "*" +black = "^24.3.0" +tortoise-orm = "^0.17.4" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/python/examples/01-first-agent/main.py b/python/examples/01-first-agent/main.py deleted file mode 100644 index ac0fae07..00000000 --- a/python/examples/01-first-agent/main.py +++ /dev/null @@ -1,12 +0,0 @@ -from uagents import Agent, Context - -agent = Agent(name="alice") - - -@agent.on_event("startup") -async def introduce_agent(ctx: Context): - ctx.logger.info(f"Hello, I'm agent {agent.name} and my address is {agent.address}.") - - -if __name__ == "__main__": - agent.run() diff --git a/python/examples/02-interval-task/main.py b/python/examples/02-interval-task/main.py deleted file mode 100644 index f539992b..00000000 --- a/python/examples/02-interval-task/main.py +++ /dev/null @@ -1,17 +0,0 @@ -from uagents import Agent, Context - -agent = Agent(name="alice") - - -@agent.on_event("startup") -async def introduce_agent(ctx: Context): - ctx.logger.info(f"Hello, I'm agent {agent.name} and my address is {agent.address}.") - - -@agent.on_interval(period=2.0) -async def say_hello(ctx: Context): - ctx.logger.info("Hello!") - - -if __name__ == "__main__": - agent.run() diff --git a/python/examples/03-multiple-agents/main.py b/python/examples/03-multiple-agents/main.py deleted file mode 100644 index 88e316a2..00000000 --- a/python/examples/03-multiple-agents/main.py +++ /dev/null @@ -1,22 +0,0 @@ -from uagents import Agent, Bureau, Context - -alice = Agent(name="alice") -bob = Agent(name="bob") - - -@alice.on_interval(period=2.0) -async def introduce_alice(ctx: Context): - ctx.logger.info(f"Hello, I'm agent {alice.name}.") - - -@bob.on_interval(period=2.0) -async def introduce_bob(ctx: Context): - ctx.logger.info(f"Hello, I'm agent {bob.name}.") - - -bureau = Bureau() -bureau.add(alice) -bureau.add(bob) - -if __name__ == "__main__": - bureau.run() diff --git a/python/examples/04-storage/main.py b/python/examples/04-storage/main.py deleted file mode 100644 index 149cbfb4..00000000 --- a/python/examples/04-storage/main.py +++ /dev/null @@ -1,19 +0,0 @@ -from uagents import Agent, Context - -agent = Agent(name="bob") - - -@agent.on_event("startup") -async def initialize_storage(ctx: Context): - ctx.storage.set("count", 0) - - -@agent.on_interval(period=1.0) -async def on_interval(ctx: Context): - current_count = ctx.storage.get("count") - ctx.logger.info(f"My count is: {current_count}") - ctx.storage.set("count", current_count + 1) - - -if __name__ == "__main__": - agent.run() diff --git a/python/examples/05-send-msg/main.py b/python/examples/05-send-msg/main.py deleted file mode 100644 index 8a958931..00000000 --- a/python/examples/05-send-msg/main.py +++ /dev/null @@ -1,28 +0,0 @@ -from uagents import Agent, Bureau, Context, Model - - -class Message(Model): - text: str - - -alice = Agent(name="alice", seed="alice recovery phrase") -bob = Agent(name="bob", seed="bob recovery phrase") - - -@alice.on_interval(period=2.0) -async def send_message(ctx: Context): - msg = f"Hello there {bob.name} my name is {alice.name}." - await ctx.send(bob.address, Message(text=msg)) - - -@bob.on_message(model=Message) -async def message_handler(ctx: Context, sender: str, msg: Message): - ctx.logger.info(f"Received message from {sender}: {msg.text}") - - -bureau = Bureau() -bureau.add(alice) -bureau.add(bob) - -if __name__ == "__main__": - bureau.run() diff --git a/python/examples/06-send-tokens/main.py b/python/examples/06-send-tokens/main.py deleted file mode 100644 index 4f61b9fe..00000000 --- a/python/examples/06-send-tokens/main.py +++ /dev/null @@ -1,68 +0,0 @@ -from uagents import Agent, Bureau, Context, Model -from uagents.network import wait_for_tx_to_complete -from uagents.setup import fund_agent_if_low - - -class PaymentRequest(Model): - wallet_address: str - amount: int - denom: str - - -class TransactionInfo(Model): - tx_hash: str - - -AMOUNT = 100 -DENOM = "atestfet" - -alice = Agent(name="alice", seed="alice secret phrase") -bob = Agent(name="bob", seed="bob secret phrase") - - -fund_agent_if_low(bob.wallet.address(), min_balance=AMOUNT) - - -@alice.on_interval(period=10.0) -async def request_funds(ctx: Context): - await ctx.send( - bob.address, - PaymentRequest( - wallet_address=str(alice.wallet.address()), amount=AMOUNT, denom=DENOM - ), - ) - - -@alice.on_message(model=TransactionInfo) -async def confirm_transaction(ctx: Context, sender: str, msg: TransactionInfo): - ctx.logger.info(f"Received transaction info from {sender}: {msg}") - tx_resp = await wait_for_tx_to_complete(msg.tx_hash, ctx.ledger) - - coin_received = tx_resp.events["coin_received"] - if ( - coin_received["receiver"] == str(alice.wallet.address()) - and coin_received["amount"] == f"{AMOUNT}{DENOM}" - ): - ctx.logger.info(f"Transaction was successful: {coin_received}") - - -@bob.on_message(model=PaymentRequest, replies=TransactionInfo) -async def send_payment(ctx: Context, sender: str, msg: PaymentRequest): - ctx.logger.info(f"Received payment request from {sender}: {msg}") - - # send the payment - transaction = ctx.ledger.send_tokens( - msg.wallet_address, msg.amount, msg.denom, bob.wallet - ) - - # send the tx hash so alice can confirm - await ctx.send(alice.address, TransactionInfo(tx_hash=transaction.tx_hash)) - - -bureau = Bureau() -bureau.add(alice) -bureau.add(bob) - - -if __name__ == "__main__": - bureau.run() diff --git a/python/examples/07-msg-verification/main.py b/python/examples/07-msg-verification/main.py deleted file mode 100644 index 329939f7..00000000 --- a/python/examples/07-msg-verification/main.py +++ /dev/null @@ -1,67 +0,0 @@ -import hashlib - -from uagents import Agent, Bureau, Context, Model -from uagents.crypto import Identity - - -class Message(Model): - message: str - digest: str - signature: str - - -def encode(message: str) -> bytes: - hasher = hashlib.sha256() - hasher.update(message.encode()) - return hasher.digest() - - -alice = Agent(name="alice", seed="alice recovery password") -bob = Agent(name="bob", seed="bob recovery password") - - -@alice.on_interval(period=3.0) -async def send_message(ctx: Context): - msg = "Hello there bob." - digest = encode(msg) - await ctx.send( - bob.address, - Message(message=msg, digest=digest.hex(), signature=alice.sign_digest(digest)), - ) - - -@alice.on_message(model=Message) -async def alice_rx_message(ctx: Context, sender: str, msg: Message): - assert Identity.verify_digest( - sender, bytes.fromhex(msg.digest), msg.signature - ), "couldn't verify bob's message" - - ctx.logger.info("Bob's message verified!") - ctx.logger.info(f"Received message from {sender}: {msg.message}") - - -@bob.on_message(model=Message) -async def bob_rx_message(ctx: Context, sender: str, msg: Message): - assert Identity.verify_digest( - sender, bytes.fromhex(msg.digest), msg.signature - ), "couldn't verify alice's message" - ctx.logger.info("Alice's message verified!") - - ctx.logger.info(f"Received message from {sender}: {msg.message}") - - msg = "Hello there alice." - digest = encode(msg) - - # send the response - await ctx.send( - alice.address, - Message(message=msg, digest=digest.hex(), signature=bob.sign_digest(digest)), - ) - - -bureau = Bureau() -bureau.add(alice) -bureau.add(bob) - -if __name__ == "__main__": - bureau.run() diff --git a/python/examples/09-booking-protocol-demo/protocols/__init__.py b/python/examples/09-booking-protocol-demo/protocols/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python/examples/09-booking-protocol-demo/protocols/book.py b/python/examples/09-booking-protocol-demo/protocols/book.py deleted file mode 100644 index fd5b1538..00000000 --- a/python/examples/09-booking-protocol-demo/protocols/book.py +++ /dev/null @@ -1,42 +0,0 @@ -from uagents import Context, Model, Protocol - -from .query import TableStatus - - -class BookTableRequest(Model): - table_number: int - time_start: int - duration: int - - -class BookTableResponse(Model): - success: bool - - -book_proto = Protocol(name="RestaurantBookingProtocolExample", version="0.1.0") - - -@book_proto.on_message(model=BookTableRequest, replies=BookTableResponse) -async def handle_book_request(ctx: Context, sender: str, msg: BookTableRequest): - tables = { - int(num): TableStatus(**status) - for ( - num, - status, - ) in ctx.storage._data.items() # pylint: disable=protected-access - if isinstance(num, int) - } - table = tables[msg.table_number] - - if ( - table.time_start <= msg.time_start - and table.time_end >= msg.time_start + msg.duration - ): - success = True - table.time_start = msg.time_start + msg.duration - ctx.storage.set(msg.table_number, table.dict()) - else: - success = False - - # send the response - await ctx.send(sender, BookTableResponse(success=success)) diff --git a/python/examples/09-booking-protocol-demo/protocols/query.py b/python/examples/09-booking-protocol-demo/protocols/query.py deleted file mode 100644 index 8ed3be2d..00000000 --- a/python/examples/09-booking-protocol-demo/protocols/query.py +++ /dev/null @@ -1,64 +0,0 @@ -from typing import List - -from uagents import Context, Model, Protocol - - -class TableStatus(Model): - seats: int - time_start: int - time_end: int - - -class QueryTableRequest(Model): - guests: int - time_start: int - duration: int - - -class QueryTableResponse(Model): - tables: List[int] - - -class GetTotalQueries(Model): - pass - - -class TotalQueries(Model): - total_queries: int - - -query_proto = Protocol(name="RestaurantQueryProtocolExample", version="0.1.0") - - -@query_proto.on_message(model=QueryTableRequest, replies=QueryTableResponse) -async def handle_query_request(ctx: Context, sender: str, msg: QueryTableRequest): - tables = { - int(num): TableStatus(**status) - for ( - num, - status, - ) in ctx.storage._data.items() # pylint: disable=protected-access - if isinstance(num, int) - } - - available_tables = [] - for number, status in tables.items(): - if ( - status.seats >= msg.guests - and status.time_start <= msg.time_start - and status.time_end >= msg.time_start + msg.duration - ): - available_tables.append(int(number)) - - ctx.logger.info(f"Query: {msg}. Available tables: {available_tables}.") - - await ctx.send(sender, QueryTableResponse(tables=available_tables)) - - total_queries = int(ctx.storage.get("total_queries") or 0) - ctx.storage.set("total_queries", total_queries + 1) - - -@query_proto.on_query(model=GetTotalQueries, replies=TotalQueries) -async def handle_get_total_queries(ctx: Context, sender: str, _msg: GetTotalQueries): - total_queries = int(ctx.storage.get("total_queries") or 0) - await ctx.send(sender, TotalQueries(total_queries=total_queries)) diff --git a/python/examples/09-booking-protocol-demo/query.py b/python/examples/09-booking-protocol-demo/query.py deleted file mode 100644 index 3d059626..00000000 --- a/python/examples/09-booking-protocol-demo/query.py +++ /dev/null @@ -1,16 +0,0 @@ -import asyncio - -from protocols.query import GetTotalQueries, TotalQueries -from uagents.query import query - -RESTAURANT_ADDRESS = "agent1qfpqn9jhvp9cg33f27q6jvmuv52dgyg9rfuu37rmxrletlqe7lewwjed5gy" - - -async def main(): - env = await query(RESTAURANT_ADDRESS, GetTotalQueries()) - msg = TotalQueries.parse_raw(env.decode_payload()) - print(f"Query response: {msg.json()}\n\n") - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/python/examples/09-booking-protocol-demo/restaurant.py b/python/examples/09-booking-protocol-demo/restaurant.py deleted file mode 100644 index 487a98fa..00000000 --- a/python/examples/09-booking-protocol-demo/restaurant.py +++ /dev/null @@ -1,30 +0,0 @@ -from protocols.book import book_proto -from protocols.query import TableStatus, query_proto -from uagents import Agent - -restaurant = Agent( - name="restaurant", - port=8001, - seed="restaurant recovery phrase", - endpoint={ - "http://127.0.0.1:8001/submit": {}, - }, -) - - -# build the restaurant agent from stock protocols and publish their details -restaurant.include(query_proto, publish_manifest=True) -restaurant.include(book_proto, publish_manifest=True) - - -TABLES = { - 1: TableStatus(seats=2, time_start=16, time_end=22), - 2: TableStatus(seats=4, time_start=19, time_end=21), - 3: TableStatus(seats=4, time_start=17, time_end=19), -} - -for number, status in TABLES.items(): - restaurant.storage.set(number, status.dict()) - -if __name__ == "__main__": - restaurant.run() diff --git a/python/examples/09-booking-protocol-demo/user.py b/python/examples/09-booking-protocol-demo/user.py deleted file mode 100644 index 24787ab4..00000000 --- a/python/examples/09-booking-protocol-demo/user.py +++ /dev/null @@ -1,64 +0,0 @@ -from protocols.book import BookTableRequest, BookTableResponse -from protocols.query import ( - QueryTableRequest, - QueryTableResponse, -) -from uagents import Agent, Context - -RESTAURANT_ADDRESS = ( - "test-agent://agent1qfpqn9jhvp9cg33f27q6jvmuv52dgyg9rfuu37rmxrletlqe7lewwjed5gy" -) - -user = Agent( - name="user", - port=8000, - seed="user recovery phrase", - endpoint={ - "http://127.0.0.1:8000/submit": {}, - }, -) - - -table_query = QueryTableRequest( - guests=3, - time_start=19, - duration=2, -) - - -@user.on_interval(period=3.0, messages=QueryTableRequest) -async def interval(ctx: Context): - completed = ctx.storage.get("completed") - - if not completed: - await ctx.send(RESTAURANT_ADDRESS, table_query) - - -@user.on_message(QueryTableResponse, replies={BookTableRequest}) -async def handle_query_response(ctx: Context, sender: str, msg: QueryTableResponse): - if len(msg.tables) > 0: - ctx.logger.info("There is a free table, attempting to book one now") - table_number = msg.tables[0] - request = BookTableRequest( - table_number=table_number, - time_start=table_query.time_start, - duration=table_query.duration, - ) - await ctx.send(sender, request) - else: - ctx.logger.info("No free tables - nothing more to do") - ctx.storage.set("completed", True) - - -@user.on_message(BookTableResponse, replies=set()) -async def handle_book_response(ctx: Context, _sender: str, msg: BookTableResponse): - if msg.success: - ctx.logger.info("Table reservation was successful") - else: - ctx.logger.info("Table reservation was UNSUCCESSFUL") - - ctx.storage.set("completed", True) - - -if __name__ == "__main__": - user.run() diff --git a/python/examples/10-cleaning-demo/cleaner.py b/python/examples/10-cleaning-demo/cleaner.py deleted file mode 100644 index a1f6cda3..00000000 --- a/python/examples/10-cleaning-demo/cleaner.py +++ /dev/null @@ -1,55 +0,0 @@ -from datetime import datetime - -from protocols.cleaning import cleaning_proto -from protocols.cleaning.models import Availability, Provider, Service, ServiceType -from pytz import utc -from tortoise import Tortoise -from uagents import Agent, Context - -cleaner = Agent( - name="cleaner", - port=8001, - seed="cleaner secret phrase", - endpoint={ - "http://127.0.0.1:8001/submit": {}, - }, -) - - -# build the cleaning service agent from the cleaning protocol -cleaner.include(cleaning_proto) - - -@cleaner.on_event("startup") -async def startup(_ctx: Context): - await Tortoise.init( - db_url="sqlite://db.sqlite3", modules={"models": ["protocols.cleaning.models"]} - ) - await Tortoise.generate_schemas() - - provider = await Provider.create(name=cleaner.name, location="London Kings Cross") - - floor = await Service.create(type=ServiceType.FLOOR) - window = await Service.create(type=ServiceType.WINDOW) - laundry = await Service.create(type=ServiceType.LAUNDRY) - - await provider.services.add(floor) - await provider.services.add(window) - await provider.services.add(laundry) - - await Availability.create( - provider=provider, - time_start=utc.localize(datetime.fromisoformat("2022-01-31 00:00:00")), - time_end=utc.localize(datetime.fromisoformat("2023-05-01 00:00:00")), - max_distance=10, - min_hourly_price=5, - ) - - -@cleaner.on_event("shutdown") -async def shutdown(_ctx: Context): - await Tortoise.close_connections() - - -if __name__ == "__main__": - cleaner.run() diff --git a/python/examples/10-cleaning-demo/protocols/__init__.py b/python/examples/10-cleaning-demo/protocols/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python/examples/10-cleaning-demo/protocols/cleaning/__init__.py b/python/examples/10-cleaning-demo/protocols/cleaning/__init__.py deleted file mode 100644 index c13dc5e3..00000000 --- a/python/examples/10-cleaning-demo/protocols/cleaning/__init__.py +++ /dev/null @@ -1,118 +0,0 @@ -from datetime import datetime, timedelta -from typing import List - -from geopy.distance import geodesic -from geopy.geocoders import Nominatim -from uagents import Context, Model, Protocol - -from .models import Availability, Provider, User - -PROTOCOL_NAME = "cleaning" -PROTOCOL_VERSION = "0.1.0" - - -class ServiceRequest(Model): - user: str - location: str - time_start: datetime - duration: timedelta - services: List[int] - max_price: float - - -class ServiceResponse(Model): - accept: bool - price: float - - -class ServiceBooking(Model): - location: str - time_start: datetime - duration: timedelta - services: List[int] - price: float - - -class BookingResponse(Model): - success: bool - - -cleaning_proto = Protocol(name=PROTOCOL_NAME, version=PROTOCOL_VERSION) - - -def in_service_region( - location: str, availability: Availability, provider: Provider -) -> bool: - geolocator = Nominatim(user_agent="micro_agents") - - user_location = geolocator.geocode(location) - cleaner_location = geolocator.geocode(provider.location) - - if user_location is None: - raise RuntimeError(f"user location {location} not found") - - if cleaner_location is None: - raise RuntimeError(f"provider location {provider.location} not found") - - cleaner_coordinates = (cleaner_location.latitude, cleaner_location.longitude) - user_coordinates = (user_location.latitude, user_location.longitude) - - service_distance = geodesic(user_coordinates, cleaner_coordinates).miles - in_range = service_distance <= availability.max_distance - - return in_range - - -@cleaning_proto.on_message(model=ServiceRequest, replies=ServiceResponse) -async def handle_query_request(ctx: Context, sender: str, msg: ServiceRequest): - provider = await Provider.filter(name=ctx.name).first() - availability = await Availability.get(provider=provider) - services = [int(service.type) for service in await provider.services] - markup = provider.markup - - user, _ = await User.get_or_create(name=msg.user, address=sender) - msg_duration_hours: float = msg.duration.total_seconds() / 3600 - ctx.logger.info(f"Received service request from user `{user.name}`") - - if ( - set(msg.services) <= set(services) - and in_service_region(msg.location, availability, provider) - and availability.time_start <= msg.time_start - and availability.time_end >= msg.time_start + msg.duration - and availability.min_hourly_price * msg_duration_hours < msg.max_price - ): - accept = True - price = markup * availability.min_hourly_price * msg_duration_hours - ctx.logger.info(f"I am available! Proposing price: {price}.") - else: - accept = False - price = 0 - ctx.logger.info("I am not available. Declining request.") - - await ctx.send(sender, ServiceResponse(accept=accept, price=price)) - - -@cleaning_proto.on_message(model=ServiceBooking, replies=BookingResponse) -async def handle_book_request(ctx: Context, sender: str, msg: ServiceBooking): - provider = await Provider.filter(name=ctx.name).first() - availability = await Availability.get(provider=provider) - services = [int(service.type) for service in await provider.services] - - user = await User.get(address=sender) - msg_duration_hours: float = msg.duration.total_seconds() / 3600 - ctx.logger.info(f"Received booking request from user `{user.name}`") - - success = ( - set(msg.services) <= set(services) - and availability.time_start <= msg.time_start - and availability.time_end >= msg.time_start + msg.duration - and msg.price <= availability.min_hourly_price * msg_duration_hours - ) - - if success: - availability.time_start = msg.time_start + msg.duration - await availability.save() - ctx.logger.info("Accepted task and updated availability.") - - # send the response - await ctx.send(sender, BookingResponse(success=success)) diff --git a/python/examples/10-cleaning-demo/protocols/cleaning/models.py b/python/examples/10-cleaning-demo/protocols/cleaning/models.py deleted file mode 100644 index 699dba63..00000000 --- a/python/examples/10-cleaning-demo/protocols/cleaning/models.py +++ /dev/null @@ -1,42 +0,0 @@ -from enum import Enum - -from tortoise import fields, models - - -class ServiceType(int, Enum): - FLOOR = 1 - WINDOW = 2 - LAUNDRY = 3 - IRON = 4 - BATHROOM = 5 - - -class User(models.Model): - id = fields.IntField(pk=True) - name = fields.CharField(max_length=64) - address = fields.CharField(max_length=100) - created_at = fields.DatetimeField(auto_now_add=True) - - -class Service(models.Model): - id = fields.IntField(pk=True) - type = fields.IntEnumField(ServiceType) - - -class Provider(models.Model): - id = fields.IntField(pk=True) - name = fields.CharField(max_length=64) - location = fields.CharField(max_length=64) - created_at = fields.DatetimeField(auto_now_add=True) - availability = fields.ReverseRelation["Availability"] - services = fields.ManyToManyField("models.Service") - markup = fields.FloatField(default=1.1) - - -class Availability(models.Model): - id = fields.IntField(pk=True) - provider = fields.OneToOneField("models.Provider", related_name="availability") - max_distance = fields.IntField(default=10) - time_start = fields.DatetimeField() - time_end = fields.DatetimeField() - min_hourly_price = fields.FloatField(default=0.0) diff --git a/python/examples/10-cleaning-demo/user.py b/python/examples/10-cleaning-demo/user.py deleted file mode 100644 index 75fa84d7..00000000 --- a/python/examples/10-cleaning-demo/user.py +++ /dev/null @@ -1,78 +0,0 @@ -from datetime import datetime, timedelta - -from protocols.cleaning import ( - BookingResponse, - ServiceBooking, - ServiceRequest, - ServiceResponse, -) -from protocols.cleaning.models import ServiceType -from pytz import utc -from uagents import Agent, Context - -CLEANER_ADDRESS = ( - "test-agent://agent1qdfdx6952trs028fxyug7elgcktam9f896ays6u9art4uaf75hwy2j9m87w" -) - -user = Agent( - name="user", - port=8000, - seed="cleaning user recovery phrase", - endpoint={ - "http://127.0.0.1:8000/submit": {}, - }, -) - - -request = ServiceRequest( - user=user.name, - location="London Kings Cross", - time_start=utc.localize(datetime.fromisoformat("2023-04-10 16:00:00")), - duration=timedelta(hours=4), - services=[ServiceType.WINDOW, ServiceType.LAUNDRY], - max_price=60, -) - -MARKDOWN = 0.8 - - -@user.on_interval(period=3.0, messages=ServiceRequest) -async def interval(ctx: Context): - ctx.storage.set("markdown", MARKDOWN) - completed = ctx.storage.get("completed") - - if not completed: - ctx.logger.info(f"Requesting cleaning service: {request}") - await ctx.send(CLEANER_ADDRESS, request) - - -@user.on_message(ServiceResponse, replies=ServiceBooking) -async def handle_query_response(ctx: Context, sender: str, msg: ServiceResponse): - markdown = ctx.storage.get("markdown") - if msg.accept: - ctx.logger.info("Cleaner is available, attempting to book now") - booking = ServiceBooking( - location=request.location, - time_start=request.time_start, - duration=request.duration, - services=request.services, - price=markdown * msg.price, - ) - await ctx.send(sender, booking) - else: - ctx.logger.info("Cleaner is not available - nothing more to do") - ctx.storage.set("completed", True) - - -@user.on_message(BookingResponse, replies=set()) -async def handle_book_response(ctx: Context, _sender: str, msg: BookingResponse): - if msg.success: - ctx.logger.info("Booking was successful") - else: - ctx.logger.info("Booking was UNSUCCESSFUL") - - ctx.storage.set("completed", True) - - -if __name__ == "__main__": - user.run() diff --git a/python/examples/11-mailbox-agents/alice.py b/python/examples/11-mailbox-agents/alice.py deleted file mode 100644 index 60c2fc46..00000000 --- a/python/examples/11-mailbox-agents/alice.py +++ /dev/null @@ -1,36 +0,0 @@ -from uagents import Agent, Context, Model - - -class Message(Model): - message: str - - -# First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) -SEED_PHRASE = "put_your_seed_phrase_here" - -# Copy the address shown below -print(f"Your agent's address is: {Agent(seed=SEED_PHRASE).address}") - -# Then go to https://agentverse.ai, register your agent in the Mailroom -# and copy the agent's mailbox key -AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" - -# Now your agent is ready to join the agentverse! -agent = Agent( - name="alice", - seed=SEED_PHRASE, - mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", -) - - -@agent.on_message(model=Message, replies={Message}) -async def handle_message(ctx: Context, sender: str, msg: Message): - ctx.logger.info(f"Received message from {sender}: {msg.message}") - - # send the response - ctx.logger.info("Sending message to bob") - await ctx.send(sender, Message(message="hello there bob")) - - -if __name__ == "__main__": - agent.run() diff --git a/python/examples/11-mailbox-agents/bob.py b/python/examples/11-mailbox-agents/bob.py deleted file mode 100644 index 72a50930..00000000 --- a/python/examples/11-mailbox-agents/bob.py +++ /dev/null @@ -1,41 +0,0 @@ -from uagents import Agent, Context, Model - - -class Message(Model): - message: str - - -# Copy ALICE_ADDRESS generated in alice.py -ALICE_ADDRESS = "paste_alice_address_here" - -# Generate a second seed phrase (e.g. https://pypi.org/project/mnemonic/) -SEED_PHRASE = "put_your_seed_phrase_here" - -# Copy the address shown below -print(f"Your agent's address is: {Agent(seed=SEED_PHRASE).address}") - -# Then go to https://agentverse.ai, register your agent in the Mailroom -# and copy the agent's mailbox key -AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" - -# Now your agent is ready to join the agentverse! -agent = Agent( - name="bob", - seed=SEED_PHRASE, - mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", -) - - -@agent.on_interval(period=2.0) -async def send_message(ctx: Context): - ctx.logger.info("Sending message to alice") - await ctx.send(ALICE_ADDRESS, Message(message="hello there alice")) - - -@agent.on_message(model=Message, replies=set()) -async def on_message(ctx: Context, sender: str, msg: Message): - ctx.logger.info(f"Received message from {sender}: {msg.message}") - - -if __name__ == "__main__": - agent.run() diff --git a/python/examples/14-broadcast/main.py b/python/examples/14-broadcast/main.py deleted file mode 100644 index e25bb284..00000000 --- a/python/examples/14-broadcast/main.py +++ /dev/null @@ -1,56 +0,0 @@ -from uagents import Agent, Bureau, Context, Model, Protocol - -# create agents -# alice and bob will support the protocol -# charles will try to reach all agents supporting the protocol -alice = Agent(name="alice", seed="alice recovery phrase") -bob = Agent(name="bob", seed="bob recovery phrase") -charles = Agent(name="charles", seed="charles recovery phrase") - - -class BroadcastExampleRequest(Model): - pass - - -class BroadcastExampleResponse(Model): - text: str - - -# define protocol -proto = Protocol(name="proto", version="1.0") - - -@proto.on_message(model=BroadcastExampleRequest, replies=BroadcastExampleResponse) -async def handle_request(ctx: Context, sender: str, _msg: BroadcastExampleRequest): - await ctx.send( - sender, BroadcastExampleResponse(text=f"Hello from {ctx.agent.name}") - ) - - -# include protocol -# Note: after the first registration on the almanac smart contract, it will -# take about 5 minutes before the agents can be found through the protocol -alice.include(proto) -bob.include(proto) - - -# let charles send the message to all agents supporting the protocol -@charles.on_interval(period=5) -async def say_hello(ctx: Context): - status_list = await ctx.broadcast(proto.digest, message=BroadcastExampleRequest()) - ctx.logger.info(f"Trying to contact {len(status_list)} agents.") - - -@charles.on_message(model=BroadcastExampleResponse) -async def handle_response(ctx: Context, sender: str, msg: BroadcastExampleResponse): - ctx.logger.info(f"Received response from {sender}: {msg.text}") - - -bureau = Bureau(port=8000, endpoint="http://localhost:8000/submit") -bureau.add(alice) -bureau.add(bob) -bureau.add(charles) - - -if __name__ == "__main__": - bureau.run() diff --git a/python/examples/15-wallet-messaging/main.py b/python/examples/15-wallet-messaging/main.py deleted file mode 100644 index 7fb1c6a5..00000000 --- a/python/examples/15-wallet-messaging/main.py +++ /dev/null @@ -1,31 +0,0 @@ -from uagents import Agent, Bureau, Context -from uagents.wallet_messaging import WalletMessage - -ALICE_SEED = "alice dorado recovery phrase" -BOB_SEED = "bob dorado recovery phrase" - -alice = Agent(name="alice", seed=ALICE_SEED, enable_wallet_messaging=True) -bob = Agent(name="bob", seed=BOB_SEED, enable_wallet_messaging=True) - - -@alice.on_wallet_message() -async def reply(ctx: Context, msg: WalletMessage): - ctx.logger.info(f"Got wallet message: {msg.text}") - await ctx.send_wallet_message(msg.sender, "hey, thanks for the message") - - -@bob.on_interval(period=5) -async def send_message(ctx: Context): - ctx.logger.info("Sending message...") - await ctx.send_wallet_message(alice.address, "hello") - - -@bob.on_wallet_message() -async def wallet_reply(ctx: Context, msg: WalletMessage): - ctx.logger.info(f"Got wallet message: {msg.text}") - - -bureau = Bureau() -bureau.add(alice) -bureau.add(bob) -bureau.run() diff --git a/python/examples/README.md b/python/examples/README.md new file mode 100644 index 00000000..0b1fbf89 --- /dev/null +++ b/python/examples/README.md @@ -0,0 +1,13 @@ +# uAgents Examples + +Welcome to uAgents Examples! +The examples are divided into two categories: Agent Core and Network. + +- **Agent Core**: This category includes the main functionalities of uAgents, such as intervals, storage, protocols, and messages. +- **Network**: This category covers functionalities like bureau, mailbox, remote agents, and name service. + +For more information on these concepts, please visit our [documentation](https://fetch.ai/docs/guides/agents/create-a-uagent) + +You can also directly navigate to either the `agent-core` or `network` folder and start experimenting with uAgents. Each example includes a README file explaining the main concepts and how to run the agent. Feel free to play around with the code! + +Agent Core examples are compatible with our Agentverse Command Line tool, [AVCTL](https://fetch.ai/docs/guides/avctl/avctl), so you can deploy your local agents to [Agentverse](https://fetch.ai/docs/guides/agentverse/creating-a-hosted-agent). diff --git a/python/examples/agent-core/01-my-first-agent/README.md b/python/examples/agent-core/01-my-first-agent/README.md new file mode 100644 index 00000000..35a7963e --- /dev/null +++ b/python/examples/agent-core/01-my-first-agent/README.md @@ -0,0 +1,43 @@ +# My First Agent Example + +Welcome to My First Agent example! This guide will help you understand key concepts used in creating an agent that can perform tasks based on certain events and intervals. Before diving into the concepts, ensure you navigate to the example directory, then run the following commands to set up your environment with the necessary dependencies: + +``` +poetry install +poetry shell +``` + +## Key Concepts + +### @on_event("startup") + +- **Description**: The `@on_event("startup")` decorator is used to define a function that should be executed when the agent starts up. This is particularly useful for initialization tasks such as setting up logging, initializing storage, or performing a desired initial action. +- **Example Usage**: In our example, the `introduce_agent` function is executed at startup, where the agent logs its name and address and initializes a count in its storage. + +### @on_event("shutdown") + +- **Description**: Similarly, the `@on_event("shutdown")` decorator defines a function to be executed when the agent is shutting down. This can be used for cleanup tasks like closing database connections, saving state, or simply logging that the agent process is finished. +- **Example Usage**: The `goodbye` function logs a message indicating that the agent process has finished. + +### @on_interval() + +- **Description**: The `@on_interval` decorator is used to schedule a function to run at a fixed interval, specified by the `period` parameter (in seconds). This is useful for tasks that need to be repeated periodically, such as polling a service, updating a dashboard, or in this case, incrementing a counter. +- **Example Usage**: The `counter` function is called every 2 seconds, incrementing and logging a count stored in the agent's storage. + +### Storage set and get + +- **Description**: Storage operations like `set` and `get` allow the agent to save and retrieve data across event handlers. This persistent storage can be used to maintain state, cache results, or store configuration settings. +- **Example Usage**: In the `introduce_agent` function, the count is initialized to 0 using `ctx.storage.set("count", 0)`. The `counter` function then retrieves this count, increments it, and stores it back using `ctx.storage.get("count")` and `ctx.storage.set("count", current_count + 1)`. + +## Start the Agent + +To start the agent and see the above-mentioned functionalities in action, simply run: + +``` +python agent.py +``` + +You'll see logs corresponding to the agent's startup process, periodic counter updates, and the shutdown message if you terminate the process. This will give you a practical view of how the agent operates and responds to events and intervals as described. + + +While none of these components are strictly necessary for an agent to function, they enable the development of more complex, stateful, and responsive agents. By leveraging events, intervals, and storage, you can create agents capable of handling a wide range of tasks in an efficient and organized manner. diff --git a/python/examples/agent-core/01-my-first-agent/agent.py b/python/examples/agent-core/01-my-first-agent/agent.py new file mode 100644 index 00000000..3d8feb12 --- /dev/null +++ b/python/examples/agent-core/01-my-first-agent/agent.py @@ -0,0 +1,25 @@ +from uagents import Agent, Context + +agent = Agent(name="alice") + + +@agent.on_event("startup") +async def introduce_agent(ctx: Context): + ctx.logger.info(f"Hello, I'm an agent and my address is {agent.address}.") + ctx.storage.set("count", 0) + + +@agent.on_event("shutdown") +async def goodbye(ctx: Context): + ctx.logger.info("Agent process finished!") + + +@agent.on_interval(period=2.0) +async def counter(ctx: Context): + current_count = ctx.storage.get("count") or 0 + ctx.logger.info(f"My count is: {current_count}") + ctx.storage.set("count", current_count + 1) + + +if __name__ == "__main__": + agent.run() diff --git a/python/examples/agent-core/02-protocols/README.md b/python/examples/agent-core/02-protocols/README.md new file mode 100644 index 00000000..a399d0e0 --- /dev/null +++ b/python/examples/agent-core/02-protocols/README.md @@ -0,0 +1,52 @@ +# Protocols Example + +Welcome to the Protocols example! This guide delves into the concept of protocols within agents, demonstrating how to define and incorporate them for inter-agent communication. Before proceeding, ensure you navigate to the example directory then run the following commands to set up your environment with the necessary dependencies: + +``` +poetry install +poetry shell +``` + + +## Key Concepts + +### Protocols + +- **Description**: A protocol in this context defines a set of rules or procedures for data exchange between agents. By defining a protocol, you establish a structured way for agents to communicate, ensuring they understand each other's messages. +- **Example Usage**: In the example, the `square_protocol` is defined to handle messages related to squaring a number. It specifies the message format for requests and responses, allowing agents to communicate this specific type of information reliably. + +### Incorporating Protocols into Agents + +- **Description**: Once a protocol is defined, it can be incorporated into an agent. This makes the agent aware of the protocol and enables it to send and receive messages that conform to the protocol's definitions. +- **Example Usage**: Both Alice and Bob agents include the `square_protocol`, which means they can participate in exchanges defined by this protocol, such as sending a number to square and receiving the squared result. + +### Agent Seeds + +- **Description**: A seed can be used to generate a unique identity for an agent. This is crucial in scenarios where agents need to be distinguishable from each other, for example, in a network of agents communicating over a protocol. +- **Example Usage**: Alice and Bob are given unique seeds (`ALICE_SEED` and `BOB_SEED`), ensuring their identities are distinct in the system. + +## Running the Agents + +To observe the interaction between the agents, follow these steps: + +### 1. Start Agent Bob +- Navigate to the directory named `bob`. +- Run the command: + ``` + python agent.py + ``` +- Upon starting, agent bob can print its address using `bob.address`. Make sure to copy this address. + +### 2. Start Agent Alice +- Open the file alice/agent.py. +- Paste the copied address of agent bob into the specified location in the file to set up the communication link between Alice and Bob. +- Inside alice directory, run the command: + ``` + python agent.py + ``` +Following these instructions will initiate agent alice, which will then connect to agent bob using the provided address. You will see logs indicating their communication, you will see logs indicating that Alice is asking Bob what 7 squared is, and Bob responding with the answer. +## Experimentation + +Now that you understand how the protocol works and how it's incorporated into agents, try reversing the roles. Instead of Alice asking Bob to square a number, modify the code to have Bob ask Alice. This change will help you grasp the flexibility of protocols + +Protocols are a powerful concept in agent-based systems, enabling structured and reliable communication. By defining a protocol and incorporating it into agents, you create a foundation for complex interactions. diff --git a/python/examples/agent-core/02-protocols/alice/agent.py b/python/examples/agent-core/02-protocols/alice/agent.py new file mode 100644 index 00000000..268e9c72 --- /dev/null +++ b/python/examples/agent-core/02-protocols/alice/agent.py @@ -0,0 +1,51 @@ +from uagents import Agent, Context, Model, Protocol + +BOB_ADDRESS = "put_bob_address_here" + +ALICE_SEED = "put_alices_seed_phrase_here" + +alice = Agent( + name="alice", + port=8000, + seed=ALICE_SEED, + endpoint=["http://127.0.0.1:8000/submit"], +) + + +class Request(Model): + number: int + + +class Response(Model): + square: int + original_number: int + + +proto = Protocol(name="square_protocol", version="1.0") + + +@proto.on_message(model=Request, replies=Response) +async def request_handler(ctx, sender: str, msg: Request): + square = msg.number * msg.number + await ctx.send(sender, Response(square=square, original_number=msg.number)) + + +@proto.on_message(model=Response) +async def response_handler(ctx, sender: str, msg: Response): + ctx.logger.info( + f"agent {sender} calculated: {msg.original_number} squared is {msg.square}" + ) + + +alice.include(proto) + + +@alice.on_interval(period=10) +async def request_square(ctx: Context): + num = 7 + ctx.logger.info(f"What is {num} squared?") + await ctx.send(BOB_ADDRESS, Request(number=num)) + + +if __name__ == "__main__": + alice.run() diff --git a/python/examples/agent-core/02-protocols/bob/agent.py b/python/examples/agent-core/02-protocols/bob/agent.py new file mode 100644 index 00000000..3d27e4b3 --- /dev/null +++ b/python/examples/agent-core/02-protocols/bob/agent.py @@ -0,0 +1,41 @@ +from uagents import Agent, Model, Protocol + +BOB_SEED = "put_bobs_seed_phrase_here" + +bob = Agent( + name="bob", + port=8001, + seed=BOB_SEED, + endpoint=["http://127.0.0.1:8001/submit"], +) + + +class Request(Model): + number: int + + +class Response(Model): + square: int + original_number: int + + +proto = Protocol(name="square_protocol", version="1.0") + + +@proto.on_message(model=Request, replies=Response) +async def request_handler(ctx, sender: str, msg: Request): + square = msg.number * msg.number + await ctx.send(sender, Response(square=square, original_number=msg.number)) + + +@proto.on_message(model=Response) +async def response_handler(ctx, sender: str, msg: Response): + ctx.logger.info( + f"agent {sender} calculated: {msg.original_number} squared is {msg.square}" + ) + + +bob.include(proto) + +if __name__ == "__main__": + bob.run() diff --git a/python/examples/agent-core/03-send-tokens/README.md b/python/examples/agent-core/03-send-tokens/README.md new file mode 100644 index 00000000..be00795b --- /dev/null +++ b/python/examples/agent-core/03-send-tokens/README.md @@ -0,0 +1,52 @@ + +# Send Tokens Example + +Welcome to the Send Tokens example! This guide illustrates how agents can trade tokens on the Fetch.ai blockchain, creating economic interactions within an agent-based system. This example also emphasizes the importance of using seeds for agent identity, as each agent possesses a Fetch wallet tied to its unique identity. Before you begin, make sure to navigate to the example directory and set up your environment with the following commands: + +``` +poetry install +poetry shell +``` + +## Key Concepts + +### Trading Tokens between Agents + +- **Description**: This example demonstrates how agents can send tokens using the Fetch.ai blockchain, showcasing the potential for economic interactions in agent systems. Agents use models to define the structure of payment requests and transaction information, facilitating clear communication about token transfers. +- **Example Usage**: Alice sends a `PaymentRequest` to Bob, specifying the wallet address, amount, and denomination of tokens she requests. Bob, upon receiving this request, sends the specified amount of tokens to Alice's address and informs her of the transaction's hash. + +### Agent Uniqueness with Seeds + +- **Description**: Each agent is initialized with a unique seed phrase, which is critical for securing and distinguishing their respective Fetch wallets. This uniqueness is essential for economic transactions to ensure that tokens are sent to and from the correct entities. +- **Example Usage**: Alice and Bob are initialized with their respective `ALICE_SEED` and `BOB_SEED`, linking them to distinct wallets on the Fetch.ai blockchain. + +### Using `ctx.ledger` for Token Transactions + +- **Description**: The context (`ctx`) provides access to the `ledger` object, which agents use to interact with the blockchain. This includes functionalities like sending tokens, checking transaction statuses, and accessing wallet addresses. +- **Example Usage**: Bob uses `ctx.ledger.send_tokens` to transfer tokens to Alice's wallet in response to her payment request. Alice then uses `wait_for_tx_to_complete` with `ctx.ledger` to check the status of the transaction using the transaction hash provided by Bob. + +## Running the Agents + +To observe the interaction between the agents, follow these steps: + +### 1. Start Agent Bob +- Navigate to the directory named `bob`. +- Run the command: + ``` + python agent.py + ``` +- Upon starting, agent bob can print its address using `bob.address`. Make sure to copy this address. + +### 2. Start Agent Alice +- Open the file alice/agent.py. +- Paste the copied address of agent bob into the specified location in the file to set up the communication link between Alice and Bob. +- Inside alice directory, run the command: + ``` + python agent.py + ``` +Following these instructions will initiate agent alice, which will then connect to agent bob using the provided address. You will see them to communicate and execute token transactions as defined in the example. Observing the logs will show you the payment request from Alice, the transaction initiation by Bob, and the successful transaction confirmation. + +## Experimentation + +This example sets a foundation for exploring more economic interactions between agents. Consider modifying the amount of tokens requested, experimenting with different intervals for payment requests, or introducing more agents into the system to simulate a more dynamic economic environment. + diff --git a/python/examples/agent-core/03-send-tokens/alice/agent.py b/python/examples/agent-core/03-send-tokens/alice/agent.py new file mode 100644 index 00000000..c2756eb8 --- /dev/null +++ b/python/examples/agent-core/03-send-tokens/alice/agent.py @@ -0,0 +1,55 @@ +from uagents import Agent, Context, Model + + +class PaymentRequest(Model): + wallet_address: str + amount: int + denom: str + + +class TransactionInfo(Model): + tx_hash: str + + +AMOUNT = 100 +DENOM = "atestfet" +ALICE_SEED = "put_alices_seed_phrase_here" +BOB_ADDRESS = "put_bob_address_here" + +alice = Agent( + name="alice", + port=8000, + seed=ALICE_SEED, + endpoint=["http://127.0.0.1:8000/submit"], +) + + +@alice.on_interval(period=10.0) +async def request_funds(ctx: Context): + await ctx.send( + BOB_ADDRESS, + PaymentRequest( + wallet_address=str(alice.wallet.address()), amount=AMOUNT, denom=DENOM + ), + ) + + +@alice.on_message(model=TransactionInfo) +async def transaction_handler(ctx: Context, sender: str, msg: TransactionInfo): + ctx.logger.info(f"Received transaction info from {sender}: {msg}") + + tx_resp = ctx.ledger.query_tx(msg.tx_hash) + coin_received = tx_resp.events["coin_received"] + + if ( + coin_received["receiver"] == str(alice.wallet.address()) + and coin_received["amount"] == f"{AMOUNT}{DENOM}" + ): + ctx.logger.info(f"Transaction {msg.tx_hash} was successful: {coin_received}") + + else: + ctx.logger.info(f"Transaction {msg.tx_hash} was NOT successful") + + +if __name__ == "__main__": + alice.run() diff --git a/python/examples/agent-core/03-send-tokens/bob/agent.py b/python/examples/agent-core/03-send-tokens/bob/agent.py new file mode 100644 index 00000000..962fa414 --- /dev/null +++ b/python/examples/agent-core/03-send-tokens/bob/agent.py @@ -0,0 +1,36 @@ +from uagents import Agent, Context, Model + + +class PaymentRequest(Model): + wallet_address: str + amount: int + denom: str + + +class TransactionInfo(Model): + tx_hash: str + + +BOB_SEED = "put_bobs_seed_phrase_here" + +bob = Agent( + name="bob", + port=8001, + seed=BOB_SEED, + endpoint=["http://127.0.0.1:8001/submit"], +) + + +@bob.on_message(model=PaymentRequest, replies=TransactionInfo) +async def payment_handler(ctx: Context, sender: str, msg: PaymentRequest): + ctx.logger.info(f"Received payment request from {sender}: {msg}") + + transaction = ctx.ledger.send_tokens( + msg.wallet_address, msg.amount, msg.denom, bob.wallet + ).wait_to_complete() + + await ctx.send(sender, TransactionInfo(tx_hash=transaction.tx_hash)) + + +if __name__ == "__main__": + bob.run() diff --git a/python/examples/agent-core/04-wallet-messaging/README.md b/python/examples/agent-core/04-wallet-messaging/README.md new file mode 100644 index 00000000..f837f359 --- /dev/null +++ b/python/examples/agent-core/04-wallet-messaging/README.md @@ -0,0 +1,31 @@ +# Wallet Messaging Example + +Welcome to the Wallet Messaging example! The Wallet Alert Agent is a simple example designed to demonstrate how you can program agents to send automated alerts directly to a Fetch Wallet. This particular example is configured to send a pre-defined message about Bitcoin's price status every 5 seconds. This template can be expanded to include real-time data queries from financial APIs to send timely and relevant financial alerts. Before you begin, make sure to navigate to the example directory and set up your environment with the following commands: + +``` +poetry install --extras wallet +poetry shell +``` + +Also make sure to have an active Fetch Wallet. You can install the Fetch Wallet extension from the Chrome Web Store: [Fetch Wallet Extension](https://chromewebstore.google.com/detail/fetch-wallet/ellkdbaphhldpeajbepobaecooaoafpg?hl=en-GB&pli=1). Make sure to set it to `Dorado`testnet and copy your `Wallet Address` + +## Key Concepts + +### Sending Wallet Messages + +- **Description**: This example illustrates how agents can send wallet messages to communicate directly with wallets on the Fetch.ai network. It highlights the ability of agents to not only perform transactions but also send alerts or notifications directly to user wallets, enhancing interaction and user engagement in decentralized applications. +- **Example Usage**: In the given scenario, an agent named "alert agent" periodically sends a message "Bitcoin price is too low!" to a specified Fetch Wallet address. The message is sent using the `ctx.send_wallet_message` method, which leverages the agent's capabilities to interact directly with Fetch.ai wallets. This method requires the wallet address and the message content as parameters. + +## Running the Agent + +- Copy and paste your `Wallet Address` into agent.py + +- Run the command: + ``` + python agent.py + ``` +- Upon starting, the agent will send a message alert to your `Fetch Wallet` every 5 seconds. You can observe this in your wallet Agents chat. + +## Experimentation + +Building on the initial setup, the Wallet Alert Agent can be enhanced to deliver more complex and actionable alerts by querying real-time data from financial APIs. By integrating with these APIs, you can program the agent to analyze cryptocurrency market trends or specific stock movements, enabling it to send personalized alerts when certain thresholds are met. This approach not only makes the alerts more relevant but also allows users to respond swiftly to market changes directly from their Fetch Wallet. \ No newline at end of file diff --git a/python/examples/agent-core/04-wallet-messaging/agent.py b/python/examples/agent-core/04-wallet-messaging/agent.py new file mode 100644 index 00000000..2ba7158e --- /dev/null +++ b/python/examples/agent-core/04-wallet-messaging/agent.py @@ -0,0 +1,22 @@ +from uagents import Agent, Context + +AGENT_SEED = "put_agents_seed_phrase_here" + +WALLET_ADDRESS = "put_your_FETCH_WALLET_ADDRESS_here" + +agent = Agent( + name="alert agent", + seed=AGENT_SEED, + enable_wallet_messaging=True, +) + + +@agent.on_interval(period=5) +async def send_message(ctx: Context): + msg = "Bitcoin price is too low!" + ctx.logger.info(f"Sending message to wallet {WALLET_ADDRESS}") + await ctx.send_wallet_message(WALLET_ADDRESS, msg) + + +if __name__ == "__main__": + agent.run() diff --git a/python/examples/network/01-bureau-interaction/README.md b/python/examples/network/01-bureau-interaction/README.md new file mode 100644 index 00000000..16beca14 --- /dev/null +++ b/python/examples/network/01-bureau-interaction/README.md @@ -0,0 +1,55 @@ +# Bureau Interaction Example + +Welcome to the Bureau Interaction example! This guide demonstrates how a `Bureau` can host multiple agents, allowing them to interact and simulate economic transactions on a network. Each agent is initialized with a unique seed to secure their identity and wallet on the blockchain. This setup facilitates complex simulations with numerous agents interacting in a dynamic environment. Before proceeding, navigate to the example directory and set up your environment with: + +``` +poetry install +poetry shell +``` + + +## Key Concepts + +### Multiple Agent Hosting with Bureau + +- **Description**: This example showcases a `Bureau` that manages multiple agents. The Bureau acts as a central node where each agent is registered and managed, facilitating interactions and transactions among them. +- **Example Usage**: Agents such as Alice, Bob, Charles, Diana, Ean, and Fabian are registered in the Bureau. Each agent has unique characteristics like minimum acceptable prices for transactions. + +### Agent Uniqueness with Seeds + +- **Description**: Agents are initialized with unique seeds, which are essential for creating secure and identifiable wallets on the blockchain. This feature ensures that transactions are secure and that they occur between the correct parties. +- **Example Usage**: Each agent, is initialized with a `seed` linked to distinct identities. + +### Inter-agent Communication and Transactions + +- **Description**: Agents communicate using a defined protocol (`seller_protocol`) where they can send and respond to offers based on predefined minimum prices. +- **Example Usage**: Alice might send an offer to Bob, and if the offer meets or exceeds Bob's minimum price, Bob will accept the offer. + +## Running the Simulation + +To observe the agents' interactions within the Bureau, follow these steps: + +### 1. Start the Bureau and Agents +- Navigate to the `seller.py` directory. +- Run the command: + +``` +python sellers.py +``` +- Each agent's address is printed at startup. Copy these addresses for further interactions. + +### 2. Interact with Agents +- Open the file `buyer.py`. +- Paste the copied addresses into the specified location in the file to set up communication links between buyers and sellers. +- Inside the directory, run the command: + +``` +python buyer.py +``` + + +Following these instructions will initiate the agents, and they will start to interact based on the offers sent and received. Observing the logs will provide insight into the negotiation process and the transactions executed. + +## Experimentation + +This example lays the groundwork for more complex simulations involving multiple agents. Consider modifying the agents' minimum prices, changing the intervals of offer submissions, or adding more agents to simulate a more dynamic economic environment. diff --git a/python/examples/network/01-bureau-interaction/buyer.py b/python/examples/network/01-bureau-interaction/buyer.py new file mode 100644 index 00000000..f86a6e95 --- /dev/null +++ b/python/examples/network/01-bureau-interaction/buyer.py @@ -0,0 +1,50 @@ +import random + +from uagents import Agent, Context, Model + + +class OfferRequest(Model): + offer: int + + +class OfferResponse(Model): + accept: bool + + +BUYER_SEED = "put_buyer_seed_phrase_here" + +SELLER_ADDRESSES = ["list all seller addresses here"] + +buyer = Agent( + name="buyer", + port=8000, + seed=BUYER_SEED, + endpoint=["http://127.0.0.1:8000/submit"], +) + +offer = 50 + + +@buyer.on_event("startup") +async def start(ctx: Context): + ctx.storage.set("seller_found", False) + + +@buyer.on_interval(period=5) +async def send_offer(ctx: Context): + found = ctx.storage.get("seller_found") + if not found: + random_address = random.choice(SELLER_ADDRESSES) + await ctx.send(random_address, OfferRequest(offer=offer)) + + +@buyer.on_message(model=OfferResponse) +async def response_handler(ctx, sender: str, msg: OfferResponse): + status = "Accepted" if msg.accept else "Declined" + ctx.logger.info(f"agent {sender} : {status} offer of {offer}") + if msg.accept: + ctx.storage.set("seller_found", True) + + +if __name__ == "__main__": + buyer.run() diff --git a/python/examples/network/01-bureau-interaction/protocol/protocol.py b/python/examples/network/01-bureau-interaction/protocol/protocol.py new file mode 100644 index 00000000..d8a0d01a --- /dev/null +++ b/python/examples/network/01-bureau-interaction/protocol/protocol.py @@ -0,0 +1,19 @@ +from uagents import Model, Protocol + + +class OfferRequest(Model): + offer: int + + +class OfferResponse(Model): + accept: bool + + +proto = Protocol(name="seller_protocol", version="1.0") + + +@proto.on_message(model=OfferRequest, replies=OfferResponse) +async def request_handler(ctx, sender: str, msg: OfferRequest): + min_price = ctx.storage.get("min_price") + accept = msg.offer >= min_price + await ctx.send(sender, OfferResponse(accept=accept)) diff --git a/python/examples/network/01-bureau-interaction/sellers.py b/python/examples/network/01-bureau-interaction/sellers.py new file mode 100644 index 00000000..71e054ca --- /dev/null +++ b/python/examples/network/01-bureau-interaction/sellers.py @@ -0,0 +1,27 @@ +from protocol.protocol import proto +from uagents import Agent, Bureau + +AGENT_INFO = { + "alice": {"seed": "replace_with_alice_seed", "min_price": 45}, + "bob": {"seed": "replace_with_bob_seed", "min_price": 55}, + "charles": {"seed": "replace_with_charles_seed", "min_price": 60}, + "diana": {"seed": "replace_with_diana_seed", "min_price": 75}, + "ean": {"seed": "replace_with_ean_seed", "min_price": 85}, + "fabian": {"seed": "replace_with_fabian_seed", "min_price": 65}, +} + + +agents = [] +for name, info in AGENT_INFO.items(): + agent = Agent(name=name, seed=info["seed"]) + print(f"{agent.name} address: {agent.address}") + agent.storage.set("min_price", info["min_price"]) + agent.include(proto) + agents.append(agent) + +bureau = Bureau(port=8001, endpoint="http://localhost:8001/submit") +for agent in agents: + bureau.add(agent) + +if __name__ == "__main__": + bureau.run() diff --git a/python/examples/network/02-local-network-interaction/README.md b/python/examples/network/02-local-network-interaction/README.md new file mode 100644 index 00000000..678cf025 --- /dev/null +++ b/python/examples/network/02-local-network-interaction/README.md @@ -0,0 +1,66 @@ +# Local Network Interactions + +Welcome to the Local Network Interactions example! this document details how to set up and run two agents, Alice and Bob, for local network interactions. This example highlights the configuration of ports and endpoints to enable communication between agents running on the same machine but simulating a distributed environment. + +To set up your environment for running the examples, navigate to the example directory and execute the following commands: + +``` +poetry install +poetry shell +``` + + +## Configuration for Local Network Interaction + +### Ports and Endpoints + +- **Description**: For agents to interact over a local network, each agent must be assigned a unique port and endpoint. The port indicates where the agent is listening for messages, and the endpoint provides a URL for sending messages to the agent. +- **Example Usage**: + - Bob is configured to listen on port 8001 and has an endpoint `http://127.0.0.1:8001/submit`. + - Alice is set up to use port 8000, with her endpoint being `http://127.0.0.1:8000/submit`. + +### Running Bob and Alice Agents + +1. **Start Bob**: Run Bob's script first. This initializes Bob on his configured port and prints his address to the terminal. + +``` +python bob.py +``` + +Note Bob's address as it is printed in the terminal. This address is needed for Alice to send messages to Bob. + +2. **Configure Alice with Bob's Address**: Before running Alice's script, replace `BOB_ADDRESS` in Alice's code with the address you noted from Bob's terminal output. This step is crucial for enabling Alice to correctly send messages to Bob. + +3. **Start Alice**: Once Bob's address is configured in Alice's script, run Alice's script. This starts Alice on her configured port, allowing her to send messages to Bob and receive responses. + +``` +python alice.py +``` + + +## Communication Flow + +- Upon running both scripts with the correct configurations, Alice sends a message to Bob every 2 seconds. +- Bob, upon receiving a message from Alice, logs the message and responds with a greeting. +- Alice then receives Bob's response and logs it, demonstrating successful local network interaction between the two agents. + +## Key Points + +- Ensure that each agent has a unique port and endpoint configured for local network interactions. +- Start the receiving agent (Bob) first to ensure his address is available for configuring the sending agent (Alice). +- Update the sender's (Alice's) code with the receiver's (Bob's) address before starting the sender agent. + + + +## Sending Synchronous Messages + +The Synchronous Messages example showcases the ease of sending synchronous messages, which can be essential for applications requiring immediate message delivery and response. + +To run the synchronous message sending example, you will need to execute the sync_sender.py script. This script utilizes asyncio to send a synchronous message and wait for a response. Here is a brief explanation of what happens in the script: + +- For applications requiring immediate delivery and responses, use the sync_sender.py script. +- It utilizes asyncio to send synchronous messages and awaits responses. +- To use, replace `RECIPIENT_ADDRESS` in the script with Bob's address, and then run: +``` +python sync_sender.py +``` \ No newline at end of file diff --git a/python/examples/08-local-network-interaction/agent2.py b/python/examples/network/02-local-network-interaction/alice.py similarity index 68% rename from python/examples/08-local-network-interaction/agent2.py rename to python/examples/network/02-local-network-interaction/alice.py index f46c4bf2..f8652761 100644 --- a/python/examples/08-local-network-interaction/agent2.py +++ b/python/examples/network/02-local-network-interaction/alice.py @@ -5,21 +5,21 @@ class Message(Model): message: str -RECIPIENT_ADDRESS = ( - "test-agent://agent1q2kxet3vh0scsf0sm7y2erzz33cve6tv5uk63x64upw5g68kr0chkv7hw50" -) +BOB_ADDRESS = "put_BOB_ADDRESS_here" + +ALICE_SEED = "put_alices_seed_phrase_here" alice = Agent( name="alice", port=8000, - seed="alice secret phrase", + seed=ALICE_SEED, endpoint=["http://127.0.0.1:8000/submit"], ) @alice.on_interval(period=2.0) async def send_message(ctx: Context): - await ctx.send(RECIPIENT_ADDRESS, Message(message="Hello there bob.")) + await ctx.send(BOB_ADDRESS, Message(message="Hello there bob.")) @alice.on_message(model=Message) diff --git a/python/examples/08-local-network-interaction/agent1.py b/python/examples/network/02-local-network-interaction/bob.py similarity index 70% rename from python/examples/08-local-network-interaction/agent1.py rename to python/examples/network/02-local-network-interaction/bob.py index 209e4cff..1b02d2f7 100644 --- a/python/examples/08-local-network-interaction/agent1.py +++ b/python/examples/network/02-local-network-interaction/bob.py @@ -1,26 +1,26 @@ from uagents import Agent, Context, Model -# NOTE: Run agent1.py before running agent2.py - class Message(Model): message: str +BOB_SEED = "put_bobs_seed_phrase_here" + bob = Agent( name="bob", port=8001, - seed="bob secret phrase", + seed=BOB_SEED, endpoint=["http://127.0.0.1:8001/submit"], ) +print(f"bob's address: {bob.address}") + @bob.on_message(model=Message) async def message_handler(ctx: Context, sender: str, msg: Message): ctx.logger.info(f"Received message from {sender}: {msg.message}") - - # send the response - await ctx.send(sender, Message(message="Hello there.")) + await ctx.send(sender, Message(message="Hello there alice.")) if __name__ == "__main__": diff --git a/python/examples/08-local-network-interaction/sync_sender.py b/python/examples/network/02-local-network-interaction/sync_sender.py similarity index 76% rename from python/examples/08-local-network-interaction/sync_sender.py rename to python/examples/network/02-local-network-interaction/sync_sender.py index b44e768d..ebcac362 100644 --- a/python/examples/08-local-network-interaction/sync_sender.py +++ b/python/examples/network/02-local-network-interaction/sync_sender.py @@ -3,9 +3,7 @@ from uagents import Model from uagents.communication import send_sync_message -RECIPIENT_ADDRESS = ( - "test-agent://agent1q2kxet3vh0scsf0sm7y2erzz33cve6tv5uk63x64upw5g68kr0chkv7hw50" -) +RECIPIENT_ADDRESS = "put_RECIPIENT_ADDRESS_here" class Message(Model): diff --git a/python/examples/network/03-protocol-broadcast/README.md b/python/examples/network/03-protocol-broadcast/README.md new file mode 100644 index 00000000..b2cc8696 --- /dev/null +++ b/python/examples/network/03-protocol-broadcast/README.md @@ -0,0 +1,45 @@ +# Protocol Broadcast + +Welcome to the Protocol Broadcast example! This guide focuses on a specific example that demonstrates how to broadcast messages to agents sharing the same protocol within a distributed agent system. This capability is pivotal for scenarios where a message needs to be sent to multiple agents simultaneously, such as updates, or requests for information. + +To prepare for running the example, ensure you're in the proper directory and have configured your environment with the necessary dependencies: + +``` +poetry install +poetry shell +``` + +## Broadcasting Messages with Protocols + +### Defining a Shared Protocol + +- **Description**: A shared protocol specifies a common communication format and procedure that participating agents agree upon. It ensures that messages are understood and processed uniformly across different agents. +- **Example Usage**: The `hello_protocol` is defined with a simple `Request` and `Response` model. Agents using this protocol can send a greeting request and expect a greeting response. + +### Including Protocols in Agents + +- **Description**: For an agent to participate in protocol-based communication, it must include the protocol within its definition. This inclusion enables the agent to understand and respond to messages formatted according to the protocol. +- **Example Usage**: Alice and Bob include the `hello_protocol`, making them capable of receiving and responding to broadcast requests sent using this protocol. + +### Broadcasting Messages + +- **Description**: Broadcasting refers to sending a message to all agents that are capable of understanding it, based on the shared protocol. This is done without specifying individual recipients, allowing for efficient group communication. +- **Example Usage**: Charles periodically broadcasts a greeting using `hello_protocol`. All agents that have included this protocol (Alice and Bob) will receive and respond to the greeting. + +## Running the Example + +To observe protocol-based broadcasting in action, run: + +``` +python main.py +``` + + +This command starts the bureau, initializing all three agents. Charles periodically broadcasts a greeting to Alice and Bob, who respond to each greeting, showcasing the broadcasting functionality. + +## Key Points + +- Ensure that all agents meant to communicate share the same protocol by including it in their definitions. +- Use broadcasting for scenarios where a message needs to be sent to multiple agents without specifying each recipient. + +By following this example, you can implement efficient and scalable communication patterns in distributed agent systems, leveraging the power of protocol broadcasting. diff --git a/python/examples/network/03-protocol-broadcast/main.py b/python/examples/network/03-protocol-broadcast/main.py new file mode 100644 index 00000000..df7cb23e --- /dev/null +++ b/python/examples/network/03-protocol-broadcast/main.py @@ -0,0 +1,33 @@ +from protocol.protocol import Request, Response, proto +from uagents import Agent, Bureau, Context + +ALICE_SEED = "put_alices_seed_here" +BOB_SEED = "put_bobs_seed_here" +CHARLES_SEED = "put_charlys_seed_here" + +alice = Agent(name="alice", seed=ALICE_SEED) +bob = Agent(name="bob", seed=BOB_SEED) +charles = Agent(name="charles", seed=CHARLES_SEED) + + +alice.include(proto) +bob.include(proto) + + +@charles.on_interval(period=10) +async def say_hello(ctx: Context): + await ctx.broadcast(proto.digest, message=Request()) + + +@charles.on_message(model=Response) +async def response_handler(ctx: Context, sender: str, msg: Response): + ctx.logger.info(f"Received response from {sender}: {msg.message}") + + +bureau = Bureau(port=8000, endpoint="http://localhost:8000/submit") +bureau.add(alice) +bureau.add(bob) +bureau.add(charles) + +if __name__ == "__main__": + bureau.run() diff --git a/python/examples/network/03-protocol-broadcast/protocol/protocol.py b/python/examples/network/03-protocol-broadcast/protocol/protocol.py new file mode 100644 index 00000000..c9783269 --- /dev/null +++ b/python/examples/network/03-protocol-broadcast/protocol/protocol.py @@ -0,0 +1,17 @@ +from uagents import Model, Protocol + + +class Request(Model): + pass + + +class Response(Model): + message: str + + +proto = Protocol(name="hello_protocol", version="1.0") + + +@proto.on_message(model=Request, replies=Response) +async def request_handler(ctx, sender: str, _msg: Request): + await ctx.send(sender, Response(message=f"Hello from {ctx.agent.name}")) diff --git a/python/examples/network/04-mailbox-agents/README.md b/python/examples/network/04-mailbox-agents/README.md new file mode 100644 index 00000000..bc81f505 --- /dev/null +++ b/python/examples/network/04-mailbox-agents/README.md @@ -0,0 +1,39 @@ +# Mailbox Agents Example + +Welcome to the Mailbox Agents example! This guide explains how to set up mailbox agents for communication within the Agentverse. The Agentverse Mailroom offers a solution that allows agents to communicate with each other seamlessly, even when one or more agents are not continuously running. This is particularly useful for interactions that do not require immediate responses or for systems where agents operate intermittently. + +Before you begin, navigate to your project's directory and prepare your environment: + +``` +poetry install +poetry shell +``` + +## Key Concepts + +### Agentverse Mailroom + +- **Description**: The Agentverse Mailroom facilitates the creation of mailboxes for agents. These mailboxes enable two-way communication between local and Agentverse agents, functioning even when agents are offline. This ensures that messages are not lost and can be retrieved and processed when the agent is active. +- **Example Usage**: Both Alice and Bob agents are configured with mailboxes hosted by the Agentverse Mailroom. This setup allows them to exchange messages reliably, regardless of their operational state. + +### Setting Up Mailboxes + +- **Process**: + 1. **Obtain Agent Address**: First, determine your agent's address by running the agent script with your seed phrase (uniqueness is crucial for new mailbox creation). The address will be printed to the console. + 2. **Create Mailbox**: Visit [agentverse.ai](https://agentverse.ai) and login, click on the Mailroom section, and create a new mailbox using your agent's address. During this process, you'll receive a unique mailbox key, copy it. + 3. **Configure Script**: Insert the obtained mailbox key into your agent's script in the `mailbox` field, formatted as `AGENT_MAILBOX_KEY`. + +### Mailbox Communication + +- **Description**: Once mailboxes are configured, agents can send and receive messages through these mailboxes. This setup is particularly useful for asynchronous communication patterns, where agents do not need to respond in real-time. +- **Example Usage**: Bob periodically sends a message to Alice. Alice, through her mailbox, receives the message and can respond when active. Both agents use the `@on_message` decorator to handle incoming messages and can reply using the `ctx.send` method. + +## Running the Example + +To see mailbox communication in action, follow these steps: + +1. **Run Alice or Bob**: Start by running one of the agent scripts to obtain the agent's address. +2. **Create Mailbox**: With the agent's address, create a mailbox on the Agentverse Mailroom and obtain your mailbox key. +3. **Configure and Run the Other Agent**: Configure the other agent with the mailbox key and the first agent's address, then run the script. + +By running both agents with properly configured mailboxes, you'll observe how messages are exchanged between Alice and Bob, showcasing the mailbox functionality. \ No newline at end of file diff --git a/python/examples/network/04-mailbox-agents/alice.py b/python/examples/network/04-mailbox-agents/alice.py new file mode 100644 index 00000000..d0f15f56 --- /dev/null +++ b/python/examples/network/04-mailbox-agents/alice.py @@ -0,0 +1,28 @@ +from uagents import Agent, Context, Model + + +class Message(Model): + message: str + + +ALICE_SEED = "put_your_seed_phrase_here" + +print(f"Your agent's address is: {Agent(seed=ALICE_SEED).address}") + +AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + +agent = Agent( + name="alice", + seed=ALICE_SEED, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", +) + + +@agent.on_message(model=Message, replies={Message}) +async def message_handler(ctx: Context, sender: str, msg: Message): + ctx.logger.info(f"Received message from {sender}: {msg.message}") + await ctx.send(sender, Message(message="Hello there bob")) + + +if __name__ == "__main__": + agent.run() diff --git a/python/examples/network/04-mailbox-agents/bob.py b/python/examples/network/04-mailbox-agents/bob.py new file mode 100644 index 00000000..b63cba63 --- /dev/null +++ b/python/examples/network/04-mailbox-agents/bob.py @@ -0,0 +1,34 @@ +from uagents import Agent, Context, Model + + +class Message(Model): + message: str + + +ALICE_ADDRESS = "put_alice_address_here" +BOB_SEED = "put_your_seed_phrase_here" + +print(f"Your agent's address is: {Agent(seed=BOB_SEED).address}") + +AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + +bob = Agent( + name="bob", + seed=BOB_SEED, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", +) + + +@bob.on_interval(period=2.0) +async def send_message(ctx: Context): + ctx.logger.info("Sending message to alice") + await ctx.send(ALICE_ADDRESS, Message(message="Hello there alice")) + + +@bob.on_message(model=Message, replies=set()) +async def message_handler(ctx: Context, sender: str, msg: Message): + ctx.logger.info(f"Received message from {sender}: {msg.message}") + + +if __name__ == "__main__": + bob.run() diff --git a/python/examples/network/05-remote-agents/README.md b/python/examples/network/05-remote-agents/README.md new file mode 100644 index 00000000..b6078a53 --- /dev/null +++ b/python/examples/network/05-remote-agents/README.md @@ -0,0 +1,42 @@ +# Remote Agents Example + +Welcome to the Remote Agents example! This will guide you through setting up and running remote agents that can communicate over the internet using `ngrok`. `Ngrok` is a tool that exposes local servers behind NATs and firewalls to the public internet over secure tunnels. This example demonstrates how to use `ngrok` to expose an agent, enabling it to interact with other agents regardless of their location. + +To get started, ensure you are in the project's directory and have configured your environment correctly: + +``` +poetry install --extras remote-agents +poetry shell +``` + + +## Using `ngrok` to Expose Agents + +### Obtaining an `ngrok` Auth Token + +- **Description**: To use `ngrok`, you first need to sign up for an account on the [ngrok website](https://ngrok.com/). Once registered, you can find your auth token on the dashboard. This token allows you to authenticate with `ngrok` and create secure tunnels. +- **Example Usage**: After obtaining your auth token, paste it into the script where indicated: `ngrok.set_auth_token("put_your_NGROK_AUTH_TOKEN_here")`. + +### Configuring `ngrok` in the Script + +- **Description**: `ngrok` is integrated into the agent script to expose the agent's local server to the internet. This setup involves specifying the local port the agent server is running on and configuring `ngrok` to tunnel traffic to this port. +- **Example Usage**: The example configures `ngrok` to expose Alice's agent running on `PORT = 8000`. The public URL provided by `ngrok` is then used as the endpoint in the agent's configuration. + +### Running Remote Agents + +- **Process**: + 1. **Start the Exposed Agent**: Run the script for Alice first. This starts the agent and uses `ngrok` to expose it. Note the agent's address and the `ngrok` public URL printed in the console. + 2. **Configure and Run the Remote Agent**: In Bob's script, replace `ALICE_ADDRESS` with Alice's agent address. Running Bob's script initiates communication with Alice via her `ngrok`-exposed endpoint. + +## Communication Flow + +- Alice's agent, once exposed by `ngrok`, can receive messages from any agent that knows its public URL. +- Bob sends a message to Alice's public URL. Alice processes this message and can respond if the logic is implemented for a response. + +## Key Points + +- `ngrok` enables local agents to be accessible from the internet, facilitating remote interactions between agents. +- It is essential to secure your `ngrok` tunnels with auth tokens and to manage access to your public URLs carefully. +- This example highlights the basics of setting up remote agent communication, providing a foundation for more complex, distributed agent-based applications. + +The Remote Agents example demonstrates a practical approach to enabling agent interactions over the internet, breaking down barriers to communication in distributed systems. diff --git a/python/examples/12-remote-agents/agent1.py b/python/examples/network/05-remote-agents/alice.py similarity index 58% rename from python/examples/12-remote-agents/agent1.py rename to python/examples/network/05-remote-agents/alice.py index d95291b8..e1e83381 100644 --- a/python/examples/12-remote-agents/agent1.py +++ b/python/examples/network/05-remote-agents/alice.py @@ -1,13 +1,3 @@ -""" -Remote connection example which uses ngrok to expose the agent as an -alternative to the Fetch.ai Agentverse. (https://agentverse.ai/) - -Preparation: - - pip install pyngrok - - during the first run, the script will download the ngrok application - (no installation or registration required) -""" - from pyngrok import conf, ngrok from uagents import Agent, Context, Model @@ -18,20 +8,23 @@ class Message(Model): PORT = 8000 + +ngrok.set_auth_token("put_your_NGROK_AUTH_TOKEN_here") conf.get_default().monitor_thread = False # reduce console output http_tunnel = ngrok.connect(addr=PORT, proto="http", name="remote_agent") +ALICE_SEED = "put_your_seed_phrase_here" + alice = Agent( - name="Alice", - seed="agent1 secret phrase", + name="alice", + seed=ALICE_SEED, port=PORT, endpoint=[f"{http_tunnel.public_url}/submit"], ) @alice.on_message(model=Message) -async def act_on_message(ctx: Context, sender: str, msg: Message): - """On message handler""" +async def message_handler(ctx: Context, sender: str, msg: Message): ctx.logger.info(f"Received message from {sender[-8:]}: {msg.message}") diff --git a/python/examples/12-remote-agents/agent2.py b/python/examples/network/05-remote-agents/bob.py similarity index 57% rename from python/examples/12-remote-agents/agent2.py rename to python/examples/network/05-remote-agents/bob.py index b037e761..bad70095 100644 --- a/python/examples/12-remote-agents/agent2.py +++ b/python/examples/network/05-remote-agents/bob.py @@ -1,7 +1,3 @@ -""" -Counterpart for the remote connection example in agent1.py. -""" - from uagents import Agent, Context, Model @@ -9,19 +5,19 @@ class Message(Model): message: str +ALICE_ADDRESS = "put_alice_address_here" +BOB_SEED = "put_your_seed_phrase_here" + bob = Agent( name="bob", port=8001, - seed="agent2 secret seed phrase", + seed=BOB_SEED, endpoint=["http://127.0.0.1:8001/submit"], ) -ALICE_ADDRESS = "agent1qv2l7qzcd2g2rcv2p93tqflrcaq5dk7c2xc7fcnfq3s37zgkhxjmq5mfyvz" - @bob.on_interval(period=5.0) -async def send_to_alice(ctx: Context): - """Send a message to alice every 5 seconds.""" +async def send_message(ctx: Context): ctx.logger.info("Sending message to alice") await ctx.send(ALICE_ADDRESS, Message(message="hello there alice")) diff --git a/python/examples/network/06-name-service/README.md b/python/examples/network/06-name-service/README.md new file mode 100644 index 00000000..9f0acce5 --- /dev/null +++ b/python/examples/network/06-name-service/README.md @@ -0,0 +1,43 @@ +# Name Service Example + +Welcome to the Name Service Example! This example guides you through setting up agents to communicate using domain names registered through a Name Service Contract on the ledger. This method allows agents to reach each other not just through specific addresses or endpoints, but via human-readable domain names, enhancing the usability and configurability of agent-based systems. + +Before diving into the example, ensure your environment is ready by navigating to your project directory and running: + +``` +poetry install +poetry shell +``` + +## Using the Name Service for Agent Communication + +### Configuration and Wallet Setup + +- **Description**: To register a domain name, an agent needs a wallet with tokens. These tokens are used to perform the registration transaction on the ledger. +- **Example Usage**: Before registering his domain name, Bob uses a `LocalWallet` initialized with a seed phrase and obtains tokens from a faucet (`faucet.get_wealth(my_wallet.address())`). This setup is necessary to interact with the Name Service Contract. + +### Registering Domain Names + +- **Description**: The Name Service Contract on the ledger allows agents to register domain names that map to their ledger addresses. This setup enables other agents to send messages using these domain names instead of needing to know the precise ledger addresses. +- **Example Usage**: Bob registers the domain name `bob-0.example.agent` through the Name Service Contract using a wallet with tokens. This process involves calling `name_service_contract.register` with Bob's agent information and domain. + +### Sending Messages to Domain Names + +- **Description**: Once a domain name is registered, other agents can send messages to this name. The system resolves the domain name to the agent's ledger address, ensuring the message is delivered correctly. +- **Example Usage**: Alice sends a message to Bob using his registered domain name `bob-0.example.agent`. This allows Alice to communicate with Bob without knowing his exact ledger address. + +## Running the Example + +To see how domain name registration and communication work, follow these steps: + +1. **Run Bob's Script**: Start with Bob's agent script to register his domain name. Ensure Bob's script includes the wallet setup and the call to register the domain name via the Name Service Contract. +2. **Run Alice's Script**: After Bob's domain name is registered, run Alice's script. Alice sends a message to Bob using his domain name, demonstrating how agents can communicate through registered names. + +## Key Points + +- Domain name registration is restricted to public domains, with `.agent` being a primary example. +- Agents can use registered domain names to communicate, making it easier to address messages and interact within the agent ecosystem. +- A wallet with tokens is necessary for the registration process, as it involves a ledger transaction. +- This example illustrates a foundational use of the Name Service for agent communication, providing a pathway to more dynamic and flexible agent interactions. + +The Name Service Example demonstrates a powerful feature of modern agent-based systems, enabling more intuitive and manageable communication channels between agents. diff --git a/python/examples/13-agent-name-service/agent2.py b/python/examples/network/06-name-service/alice.py similarity index 60% rename from python/examples/13-agent-name-service/agent2.py rename to python/examples/network/06-name-service/alice.py index 8adc6507..a813d293 100644 --- a/python/examples/13-agent-name-service/agent2.py +++ b/python/examples/network/06-name-service/alice.py @@ -5,9 +5,11 @@ class Message(Model): message: str +ALICE_SEED = "put_alices_seed_phrase_here" + alice = Agent( name="alice-0", - seed="agent alice-0 secret phrase", + seed=ALICE_SEED, port=8000, endpoint=["http://localhost:8000/submit"], ) @@ -16,10 +18,9 @@ class Message(Model): @alice.on_interval(period=5) -async def alice_interval_handler(ctx: Context): +async def send_message(ctx: Context): bob_name = "bob-0" + "." + DOMAIN - ctx.logger.info(f"Sending message to {bob_name}...") - await ctx.send(bob_name, Message(message="Hello there bob.")) + await ctx.send(bob_name, Message(message="Hello there bob")) if __name__ == "__main__": diff --git a/python/examples/13-agent-name-service/agent1.py b/python/examples/network/06-name-service/bob.py similarity index 91% rename from python/examples/13-agent-name-service/agent1.py rename to python/examples/network/06-name-service/bob.py index ceb6cc09..f02459a1 100644 --- a/python/examples/13-agent-name-service/agent1.py +++ b/python/examples/network/06-name-service/bob.py @@ -2,16 +2,16 @@ from uagents import Agent, Context, Model from uagents.network import get_faucet, get_name_service_contract -# NOTE: Run agent1.py before running agent2.py - class Message(Model): message: str +BOB_SEED = "put_bobs_seed_phrase_here" + bob = Agent( name="bob-0", - seed="agent bob-0 secret phrase", + seed=BOB_SEED, port=8001, endpoint=["http://localhost:8001/submit"], ) diff --git a/python/examples/16-on-query-proxy/README.md b/python/examples/network/07-on-query-proxy/README.md similarity index 100% rename from python/examples/16-on-query-proxy/README.md rename to python/examples/network/07-on-query-proxy/README.md diff --git a/python/examples/16-on-query-proxy/agent.py b/python/examples/network/07-on-query-proxy/agent.py similarity index 100% rename from python/examples/16-on-query-proxy/agent.py rename to python/examples/network/07-on-query-proxy/agent.py diff --git a/python/examples/16-on-query-proxy/proxy.py b/python/examples/network/07-on-query-proxy/proxy.py similarity index 100% rename from python/examples/16-on-query-proxy/proxy.py rename to python/examples/network/07-on-query-proxy/proxy.py diff --git a/python/examples/17-stateful-communication/Readme.md b/python/examples/network/08-stateful-communication/Readme.md similarity index 100% rename from python/examples/17-stateful-communication/Readme.md rename to python/examples/network/08-stateful-communication/Readme.md diff --git a/python/examples/17-stateful-communication/agent1.py b/python/examples/network/08-stateful-communication/agent1.py similarity index 100% rename from python/examples/17-stateful-communication/agent1.py rename to python/examples/network/08-stateful-communication/agent1.py diff --git a/python/examples/17-stateful-communication/agent2.py b/python/examples/network/08-stateful-communication/agent2.py similarity index 100% rename from python/examples/17-stateful-communication/agent2.py rename to python/examples/network/08-stateful-communication/agent2.py diff --git a/python/examples/17-stateful-communication/agent3.py b/python/examples/network/08-stateful-communication/agent3.py similarity index 100% rename from python/examples/17-stateful-communication/agent3.py rename to python/examples/network/08-stateful-communication/agent3.py diff --git a/python/examples/17-stateful-communication/agent4.py b/python/examples/network/08-stateful-communication/agent4.py similarity index 100% rename from python/examples/17-stateful-communication/agent4.py rename to python/examples/network/08-stateful-communication/agent4.py diff --git a/python/examples/17-stateful-communication/agent5.py b/python/examples/network/08-stateful-communication/agent5.py similarity index 100% rename from python/examples/17-stateful-communication/agent5.py rename to python/examples/network/08-stateful-communication/agent5.py diff --git a/python/examples/17-stateful-communication/dialogues/agentverse_chitchat.py b/python/examples/network/08-stateful-communication/dialogues/agentverse_chitchat.py similarity index 100% rename from python/examples/17-stateful-communication/dialogues/agentverse_chitchat.py rename to python/examples/network/08-stateful-communication/dialogues/agentverse_chitchat.py diff --git a/python/examples/17-stateful-communication/dialogues/chitchat.py b/python/examples/network/08-stateful-communication/dialogues/chitchat.py similarity index 100% rename from python/examples/17-stateful-communication/dialogues/chitchat.py rename to python/examples/network/08-stateful-communication/dialogues/chitchat.py diff --git a/python/examples/17-stateful-communication/dialogues/hardcoded_chitchat.py b/python/examples/network/08-stateful-communication/dialogues/hardcoded_chitchat.py similarity index 100% rename from python/examples/17-stateful-communication/dialogues/hardcoded_chitchat.py rename to python/examples/network/08-stateful-communication/dialogues/hardcoded_chitchat.py diff --git a/python/examples/17-stateful-communication/dialogues/simple_chitchat.py b/python/examples/network/08-stateful-communication/dialogues/simple_chitchat.py similarity index 100% rename from python/examples/17-stateful-communication/dialogues/simple_chitchat.py rename to python/examples/network/08-stateful-communication/dialogues/simple_chitchat.py diff --git a/python/pyproject.toml b/python/pyproject.toml index 19a4ab2c..73557990 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -27,7 +27,7 @@ websockets = "^10.4" fetchai-babble = { version = "^0.4.1", optional = true } tortoise-orm = { version = "^0.19.2", optional = true } geopy = { version = "^2.3.0", optional = true } -pyngrok = { version = "^5.2.3", optional = true } +pyngrok = { version = "^7.1.6", optional = true } fastapi = { version = "^0.97.0", optional = true } [tool.poetry.group.dev.dependencies]