mech-client 0.8.1__tar.gz → 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. {mech_client-0.8.1 → mech_client-0.9.0}/PKG-INFO +11 -1
  2. {mech_client-0.8.1 → mech_client-0.9.0}/README.md +10 -0
  3. mech_client-0.9.0/mech_client/__init__.py +3 -0
  4. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/cli.py +8 -0
  5. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/marketplace_interact.py +18 -6
  6. {mech_client-0.8.1 → mech_client-0.9.0}/pyproject.toml +2 -2
  7. mech_client-0.9.0/scripts/__init__.py +1 -0
  8. mech_client-0.9.0/scripts/benchmark.sh +32 -0
  9. mech_client-0.9.0/scripts/bump.py +316 -0
  10. mech_client-0.9.0/scripts/deposit_native.py +118 -0
  11. mech_client-0.9.0/scripts/deposit_token.py +187 -0
  12. mech_client-0.9.0/scripts/nvm_subscribe.py +51 -0
  13. mech_client-0.9.0/scripts/nvm_subscription/contracts/agreement_manager.py +44 -0
  14. mech_client-0.9.0/scripts/nvm_subscription/contracts/base_contract.py +75 -0
  15. mech_client-0.9.0/scripts/nvm_subscription/contracts/did_registry.py +91 -0
  16. mech_client-0.9.0/scripts/nvm_subscription/contracts/escrow_payment.py +85 -0
  17. mech_client-0.9.0/scripts/nvm_subscription/contracts/lock_payment.py +76 -0
  18. mech_client-0.9.0/scripts/nvm_subscription/contracts/nft.py +47 -0
  19. mech_client-0.9.0/scripts/nvm_subscription/contracts/nft_sales.py +119 -0
  20. mech_client-0.9.0/scripts/nvm_subscription/contracts/subscription_provider.py +107 -0
  21. mech_client-0.9.0/scripts/nvm_subscription/contracts/token.py +87 -0
  22. mech_client-0.9.0/scripts/nvm_subscription/contracts/transfer_nft.py +81 -0
  23. mech_client-0.9.0/scripts/nvm_subscription/envs/base.env +10 -0
  24. mech_client-0.9.0/scripts/nvm_subscription/envs/gnosis.env +10 -0
  25. mech_client-0.9.0/scripts/nvm_subscription/manager.py +265 -0
  26. mech_client-0.9.0/scripts/nvm_subscription/resources/networks.json +56 -0
  27. mech_client-0.9.0/scripts/utils.py +127 -0
  28. mech_client-0.9.0/scripts/whitelist.py +5 -0
  29. mech_client-0.8.1/mech_client/__init__.py +0 -3
  30. {mech_client-0.8.1 → mech_client-0.9.0}/LICENSE +0 -0
  31. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/AgentMech.json +0 -0
  32. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/AgentRegistry.json +0 -0
  33. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/AgreementStoreManager.base.json +0 -0
  34. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/AgreementStoreManager.gnosis.json +0 -0
  35. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/BalanceTrackerFixedPriceNative.json +0 -0
  36. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/BalanceTrackerFixedPriceToken.json +0 -0
  37. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/BalanceTrackerNvmSubscriptionNative.json +0 -0
  38. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/BalanceTrackerNvmSubscriptionToken.json +0 -0
  39. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/ComplementaryServiceMetadata.json +0 -0
  40. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/DIDRegistry.base.json +0 -0
  41. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/DIDRegistry.gnosis.json +0 -0
  42. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/EscrowPaymentCondition.base.json +0 -0
  43. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/EscrowPaymentCondition.gnosis.json +0 -0
  44. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/IERC1155.json +0 -0
  45. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/IMech.json +0 -0
  46. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/IToken.json +0 -0
  47. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/LockPaymentCondition.base.json +0 -0
  48. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/LockPaymentCondition.gnosis.json +0 -0
  49. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/MechMarketplace.json +0 -0
  50. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/NFTSalesTemplate.base.json +0 -0
  51. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/NFTSalesTemplate.gnosis.json +0 -0
  52. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/NeverminedConfig.base.json +0 -0
  53. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/NeverminedConfig.gnosis.json +0 -0
  54. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/SubscriptionNFT.base.json +0 -0
  55. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/SubscriptionNFT.gnosis.json +0 -0
  56. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/SubscriptionProvider.base.json +0 -0
  57. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/SubscriptionProvider.gnosis.json +0 -0
  58. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/SubscriptionToken.base.json +0 -0
  59. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/TransferNFTCondition.base.json +0 -0
  60. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/abis/TransferNFTCondition.gnosis.json +0 -0
  61. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/acn.py +0 -0
  62. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/configs/mechs.json +0 -0
  63. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/fetch_ipfs_hash.py +0 -0
  64. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/__init__.py +0 -0
  65. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/README.md +0 -0
  66. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/__init__.py +0 -0
  67. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/acn.proto +0 -0
  68. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/acn_pb2.py +0 -0
  69. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/custom_types.py +0 -0
  70. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/dialogues.py +0 -0
  71. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/message.py +0 -0
  72. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/protocol.yaml +0 -0
  73. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/serialization.py +0 -0
  74. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/tests/__init__.py +0 -0
  75. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/tests/test_acn.py +0 -0
  76. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/tests/test_acn_dialogues.py +0 -0
  77. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn/tests/test_acn_messages.py +0 -0
  78. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn_data_share/README.md +0 -0
  79. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn_data_share/__init__.py +0 -0
  80. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn_data_share/acn_data_share.proto +0 -0
  81. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn_data_share/acn_data_share_pb2.py +0 -0
  82. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn_data_share/dialogues.py +0 -0
  83. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn_data_share/message.py +0 -0
  84. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn_data_share/protocol.yaml +0 -0
  85. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn_data_share/serialization.py +0 -0
  86. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn_data_share/tests/test_acn_data_share_dialogues.py +0 -0
  87. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/acn_data_share/tests/test_acn_data_share_messages.py +0 -0
  88. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/p2p_libp2p_client/README.md +0 -0
  89. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/p2p_libp2p_client/__init__.py +0 -0
  90. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/p2p_libp2p_client/connection.py +0 -0
  91. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/helpers/p2p_libp2p_client/connection.yaml +0 -0
  92. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/interact.py +0 -0
  93. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/mech_marketplace_tool_management.py +0 -0
  94. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/mech_tool_management.py +0 -0
  95. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/prompt_to_ipfs.py +0 -0
  96. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/push_to_ipfs.py +0 -0
  97. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/subgraph.py +0 -0
  98. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/to_png.py +0 -0
  99. {mech_client-0.8.1 → mech_client-0.9.0}/mech_client/wss.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mech-client
3
- Version: 0.8.1
3
+ Version: 0.9.0
4
4
  Summary: Basic client to interact with a mech
5
5
  License: Apache-2.0
6
6
  Author: David Minarsch
@@ -237,6 +237,16 @@ Additionally to other options which are the same as for legacy Mechs, this usage
237
237
 
238
238
  `--use-prepaid <bool>`: use the prepaid method to send requests to a Mech via the Mech Marketplace. Defaults to False. <br>
239
239
  `--use-offchain <bool>`: use the off-chain method to send requests to a Mech via the Mech Marketplace. Defaults to False.
240
+ > To use offchain requests using `--use-offchain` flag, export the `MECHX_MECH_OFFCHAIN_URL` env variable before sending requests. For example if you want to connect to a mech running locally, you can do the following
241
+ ```bash
242
+ export MECHX_MECH_OFFCHAIN_URL="http://localhost:8000/"
243
+ ```
244
+ If you want to use a Valory mech for offchain requests, below is the list of mechs and their address and offchain urls.
245
+
246
+ | Service ID | Priority Mech Address | Offchain URL |
247
+ | :---: | :---: | :---: |
248
+ | 2182 | 0xB3C6319962484602b00d5587e965946890b82101 | https://d19715222af5b940.agent.propel.autonolas.tech/ |
249
+
240
250
 
241
251
  The Mech Client can also be used to send batch requests. There are couple of different ways to achieve this:
242
252
 
@@ -214,6 +214,16 @@ Additionally to other options which are the same as for legacy Mechs, this usage
214
214
 
215
215
  `--use-prepaid <bool>`: use the prepaid method to send requests to a Mech via the Mech Marketplace. Defaults to False. <br>
216
216
  `--use-offchain <bool>`: use the off-chain method to send requests to a Mech via the Mech Marketplace. Defaults to False.
217
+ > To use offchain requests using `--use-offchain` flag, export the `MECHX_MECH_OFFCHAIN_URL` env variable before sending requests. For example if you want to connect to a mech running locally, you can do the following
218
+ ```bash
219
+ export MECHX_MECH_OFFCHAIN_URL="http://localhost:8000/"
220
+ ```
221
+ If you want to use a Valory mech for offchain requests, below is the list of mechs and their address and offchain urls.
222
+
223
+ | Service ID | Priority Mech Address | Offchain URL |
224
+ | :---: | :---: | :---: |
225
+ | 2182 | 0xB3C6319962484602b00d5587e965946890b82101 | https://d19715222af5b940.agent.propel.autonolas.tech/ |
226
+
217
227
 
218
228
  The Mech Client can also be used to send batch requests. There are couple of different ways to achieve this:
219
229
 
@@ -0,0 +1,3 @@
1
+ """Mech client."""
2
+
3
+ __version__ = "0.9.0"
@@ -19,6 +19,7 @@
19
19
 
20
20
  """Mech client CLI module."""
21
21
  import json
22
+ import os
22
23
  from typing import Any, Dict, List, Optional, Tuple
23
24
 
24
25
  import click
@@ -156,6 +157,12 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals
156
157
  use_offchain = use_offchain or False
157
158
  use_prepaid = use_prepaid or use_offchain
158
159
 
160
+ mech_offchain_url = os.getenv("MECHX_MECH_OFFCHAIN_URL")
161
+ if use_offchain and not mech_offchain_url:
162
+ raise Exception(
163
+ "To use offchain requests, please set MECHX_MECH_OFFCHAIN_URL"
164
+ )
165
+
159
166
  if agent_id is None:
160
167
  if len(prompts) != len(tools):
161
168
  raise ClickException(
@@ -167,6 +174,7 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals
167
174
  priority_mech=priority_mech,
168
175
  use_prepaid=use_prepaid,
169
176
  use_offchain=use_offchain,
177
+ mech_offchain_url=mech_offchain_url,
170
178
  private_key_path=key,
171
179
  tools=tools,
172
180
  extra_attributes=extra_attributes_dict,
@@ -74,6 +74,8 @@ class PaymentType(Enum):
74
74
 
75
75
 
76
76
  IPFS_URL_TEMPLATE = "https://gateway.autonolas.tech/ipfs/f01701220{}"
77
+ MECH_OFFCHAIN_REQUEST_ENDPOINT = "send_signed_requests"
78
+ MECH_OFFCHAIN_DELIVER_ENDPOINT = "fetch_offchain_info"
77
79
  ABI_DIR_PATH = Path(__file__).parent / "abis"
78
80
  IMECH_ABI_PATH = ABI_DIR_PATH / "IMech.json"
79
81
  ITOKEN_ABI_PATH = ABI_DIR_PATH / "IToken.json"
@@ -389,6 +391,7 @@ def send_marketplace_request( # pylint: disable=too-many-arguments,too-many-loc
389
391
  def send_offchain_marketplace_request( # pylint: disable=too-many-arguments,too-many-locals
390
392
  crypto: EthereumCrypto,
391
393
  marketplace_contract: Web3Contract,
394
+ mech_offchain_url: str,
392
395
  prompt: str,
393
396
  tool: str,
394
397
  method_args_data: MechMarketplaceRequestConfig,
@@ -405,6 +408,8 @@ def send_offchain_marketplace_request( # pylint: disable=too-many-arguments,too
405
408
  :type crypto: EthereumCrypto
406
409
  :param marketplace_contract: The mech marketplace contract instance.
407
410
  :type marketplace_contract: Web3Contract
411
+ :param mech_offchain_url: mech url to connect to.
412
+ :type mech_offchain_url: str
408
413
  :param prompt: The request prompt.
409
414
  :type prompt: str
410
415
  :param tool: The requested tool.
@@ -469,9 +474,9 @@ def send_offchain_marketplace_request( # pylint: disable=too-many-arguments,too
469
474
  "nonce": nonce,
470
475
  "ipfs_data": ipfs_data,
471
476
  }
472
- # @todo changed hardcoded url
477
+ url = mech_offchain_url + MECH_OFFCHAIN_REQUEST_ENDPOINT
473
478
  response = requests.post(
474
- "http://localhost:8000/send_signed_requests",
479
+ url=url,
475
480
  data=payload,
476
481
  headers={"Content-Type": "application/json"},
477
482
  ).json()
@@ -562,10 +567,12 @@ def wait_for_marketplace_data_url( # pylint: disable=too-many-arguments, unused
562
567
  return result
563
568
 
564
569
 
565
- def wait_for_offchain_marketplace_data(request_id: str) -> Any:
570
+ def wait_for_offchain_marketplace_data(mech_offchain_url: str, request_id: str) -> Any:
566
571
  """
567
572
  Watches for data off-chain on mech.
568
573
 
574
+ :param mech_offchain_url: mech url to connect to.
575
+ :type mech_offchain_url: str
569
576
  :param request_id: The ID of the request.
570
577
  :type request_id: str
571
578
  :return: The data returned by the mech.
@@ -573,15 +580,15 @@ def wait_for_offchain_marketplace_data(request_id: str) -> Any:
573
580
  """
574
581
  while True:
575
582
  try:
576
- # @todo change hardcoded url
583
+ url = mech_offchain_url + MECH_OFFCHAIN_DELIVER_ENDPOINT
577
584
  response = requests.get(
578
- "http://localhost:8000/fetch_offchain_info",
585
+ url=url,
579
586
  data={"request_id": request_id},
580
587
  ).json()
581
588
  if response:
582
589
  return response
583
590
  except Exception: # pylint: disable=broad-except
584
- time.sleep(1)
591
+ time.sleep(WAIT_SLEEP)
585
592
 
586
593
 
587
594
  def check_prepaid_balances(
@@ -638,6 +645,7 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
638
645
  priority_mech: str,
639
646
  use_prepaid: bool = False,
640
647
  use_offchain: bool = False,
648
+ mech_offchain_url: str = "",
641
649
  tools: tuple = (),
642
650
  extra_attributes: Optional[Dict[str, Any]] = None,
643
651
  private_key_path: Optional[str] = None,
@@ -658,6 +666,8 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
658
666
  :type use_prepaid: bool
659
667
  :param use_offchain: Whether to use offchain model or not.
660
668
  :type use_offchain: bool
669
+ :param mech_offchain_url: mech url to connect to.
670
+ :type mech_offchain_url: str
661
671
  :param tools: The tools to interact with (optional).
662
672
  :type tools: tuple
663
673
  :param extra_attributes: Extra attributes to be included in the request metadata (optional).
@@ -882,6 +892,7 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
882
892
  response = send_offchain_marketplace_request(
883
893
  crypto=crypto,
884
894
  marketplace_contract=mech_marketplace_contract,
895
+ mech_offchain_url=mech_offchain_url,
885
896
  prompt=prompts[0],
886
897
  tool=tools[0],
887
898
  method_args_data=mech_marketplace_request_config,
@@ -910,6 +921,7 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
910
921
 
911
922
  for request_id in request_ids:
912
923
  data = wait_for_offchain_marketplace_data(
924
+ mech_offchain_url=mech_offchain_url,
913
925
  request_id=request_id,
914
926
  )
915
927
 
@@ -1,10 +1,10 @@
1
1
  [tool.poetry]
2
2
  name = "mech-client"
3
- version = "0.8.1"
3
+ version = "0.9.0"
4
4
  description = "Basic client to interact with a mech"
5
5
  authors = ["David Minarsch <david.minarsch@googlemail.com>"]
6
6
  readme = "README.md"
7
- packages = [{include = "mech_client"}]
7
+ packages = [{include = "mech_client"}, {include = "scripts"}]
8
8
  license = "Apache-2.0"
9
9
  include = [
10
10
  "mech_client/helpers/acn/*",
@@ -0,0 +1 @@
1
+ """Mech client scripts"""
@@ -0,0 +1,32 @@
1
+ #!/bin/bash
2
+
3
+ export MANUAL_GAS_LIMIT=150000
4
+ export WEBSOCKET_ENDPOINT=wss://rpc.eu-central-2.gateway.fm/ws/v4/gnosis/non-archival/mainnet
5
+ iterations=2
6
+
7
+ mechx --version
8
+
9
+ echo $WEBSOCKET_ENDPOINT
10
+
11
+ start_time=$(date +%s.%N)
12
+
13
+ # Execute the command for the specified number of iterations
14
+ for ((i=1; i<=$iterations; i++)); do
15
+ echo "- Iteration $i"
16
+
17
+ prompt="($i) Will arsenal win the Premier League in 2024"
18
+ mechx interact "$prompt" 6 --tool prediction-offline --confirm on-chain --extra-attribute key1=value1 --extra-attribute key2=value2
19
+
20
+ if [ $? -ne 0 ]; then
21
+ echo "Error: Command execution failed."
22
+ exit 1
23
+ fi
24
+
25
+ echo ""
26
+ done
27
+
28
+ end_time=$(date +%s.%N)
29
+ elapsed_time=$(echo "$end_time - $start_time" | bc)
30
+ seconds_per_iteration=$(echo "$elapsed_time / $iterations" | bc)
31
+
32
+ echo "Overall execution time for $iterations iterations: $elapsed_time seconds (rate of $seconds_per_iteration seconds/iteration)."
@@ -0,0 +1,316 @@
1
+ # -*- coding: utf-8 -*-
2
+ # ------------------------------------------------------------------------------
3
+ #
4
+ # Copyright 2023 Valory AG
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ # ------------------------------------------------------------------------------
19
+
20
+ """
21
+ Script for bumping core dependencies.
22
+
23
+ This script
24
+
25
+ - Fetches the latest core dependency versions from github
26
+ - Updates the tox.ini, packages and Pipfile/pyproject.toml files
27
+ - Performs the packages sync
28
+ """
29
+
30
+ import os
31
+ import re
32
+ import typing as t
33
+ from pathlib import Path
34
+
35
+ import click
36
+ import requests
37
+ from aea.cli.utils.click_utils import PackagesSource, PyPiDependency
38
+ from aea.configurations.constants import PACKAGES, PACKAGE_TYPE_TO_CONFIG_FILE
39
+ from aea.configurations.data_types import Dependency
40
+ from aea.helpers.logging import setup_logger
41
+ from aea.helpers.yaml_utils import yaml_dump, yaml_dump_all, yaml_load, yaml_load_all
42
+ from aea.package_manager.v1 import PackageManagerV1
43
+
44
+ from autonomy.cli.helpers.ipfs_hash import load_configuration
45
+
46
+
47
+ BUMP_BRANCH = "chore/bump"
48
+ PIPFILE = Path.cwd() / "Pipfile"
49
+ PYPROJECT_TOML = Path.cwd() / "pyproject.toml"
50
+ TOX_INI = Path.cwd() / "tox.ini"
51
+
52
+ TAGS_URL = "https://api.github.com/repos/{repo}/tags"
53
+ FILE_URL = "https://raw.githubusercontent.com/{repo}/{tag}/{file}"
54
+
55
+ VERISON_RE = re.compile(r"(__version__|version)( )?=( )?\"(?P<version>[0-9a-z\.]+)\"")
56
+
57
+ OPEN_AEA_REPO = "valory-xyz/open-aea"
58
+ OPEN_AUTONOMY_REPO = "valory-xyz/open-autonomy"
59
+
60
+ DEPENDENCY_SPECS = {
61
+ "open-aea": {
62
+ "repo": OPEN_AEA_REPO,
63
+ "file": "aea/__version__.py",
64
+ },
65
+ "open-aea-ledger-ethereum": {
66
+ "repo": OPEN_AEA_REPO,
67
+ "file": "plugins/aea-ledger-ethereum/setup.py",
68
+ },
69
+ "open-aea-ledger-ethereum-flashbots": {
70
+ "repo": OPEN_AEA_REPO,
71
+ "file": "plugins/aea-ledger-ethereum-flashbots/setup.py",
72
+ },
73
+ "open-aea-ledger-ethereum-hwi": {
74
+ "repo": OPEN_AEA_REPO,
75
+ "file": "plugins/aea-ledger-ethereum-hwi/setup.py",
76
+ },
77
+ "open-aea-ledger-cosmos": {
78
+ "repo": OPEN_AEA_REPO,
79
+ "file": "plugins/aea-ledger-cosmos/setup.py",
80
+ },
81
+ "open-aea-ledger-solana": {
82
+ "repo": OPEN_AEA_REPO,
83
+ "file": "plugins/aea-ledger-solana/setup.py",
84
+ },
85
+ "open-aea-cli-ipfs": {
86
+ "repo": OPEN_AEA_REPO,
87
+ "file": "plugins/aea-cli-ipfs/setup.py",
88
+ },
89
+ "open-autonomy": {
90
+ "repo": OPEN_AUTONOMY_REPO,
91
+ "file": "autonomy/__version__.py",
92
+ },
93
+ "open-aea-test-autonomy": {
94
+ "repo": OPEN_AUTONOMY_REPO,
95
+ "file": "plugins/aea-test-autonomy/setup.py",
96
+ },
97
+ }
98
+
99
+ _cache_file = Path.home() / ".aea" / ".gitcache"
100
+ _version_cache = {}
101
+ _logger = setup_logger("bump")
102
+
103
+
104
+ def load_git_cache() -> None:
105
+ """Load versions cache."""
106
+ if not _cache_file.exists():
107
+ return
108
+ with _cache_file.open("r", encoding="utf-8") as stream:
109
+ _version_cache.update(yaml_load(stream=stream))
110
+
111
+
112
+ def dump_git_cache() -> None:
113
+ """Dump versions cache."""
114
+ with _cache_file.open("w", encoding="utf-8") as stream:
115
+ yaml_dump(data=_version_cache, stream=stream)
116
+
117
+
118
+ def make_git_request(url: str) -> requests.Response:
119
+ """Make git request"""
120
+ auth = os.environ.get("GITHUB_AUTH")
121
+ if auth is None:
122
+ return requests.get(url=url)
123
+ return requests.get(url=url, headers={"Authorization": f"Bearer {auth}"})
124
+
125
+
126
+ def get_latest_tag(repo: str) -> str:
127
+ """Fetch latest git tag."""
128
+ if repo in _version_cache:
129
+ return _version_cache[repo]
130
+
131
+ response = make_git_request(url=TAGS_URL.format(repo=repo))
132
+ if response.status_code != 200:
133
+ raise ValueError(
134
+ f"Fetching tags from `{repo}` failed with message '"
135
+ + response.json()["message"]
136
+ + "'"
137
+ )
138
+ latest_tag_data, *_ = response.json()
139
+ _version_cache[repo] = latest_tag_data["name"]
140
+ return _version_cache[repo]
141
+
142
+
143
+ def get_dependency_version(repo: str, file: str) -> str:
144
+ """Get version spec ."""
145
+ response = make_git_request(
146
+ FILE_URL.format(
147
+ repo=repo,
148
+ tag=get_latest_tag(repo=repo),
149
+ file=file,
150
+ )
151
+ )
152
+ if response.status_code != 200:
153
+ raise ValueError(
154
+ f"Fetching packages from `{repo}` failed with message '"
155
+ + response.text
156
+ + "'"
157
+ )
158
+ ((*_, version),) = VERISON_RE.findall(response.content.decode())
159
+ return f"=={version}"
160
+
161
+
162
+ def get_dependencies() -> t.Dict:
163
+ """Get dependency->version mapping."""
164
+ dependencies = {}
165
+ for dependency, specs in DEPENDENCY_SPECS.items():
166
+ version = _version_cache.get(
167
+ dependency,
168
+ get_dependency_version(
169
+ repo=specs["repo"],
170
+ file=specs["file"],
171
+ ),
172
+ )
173
+ dependencies[dependency] = version
174
+ _version_cache.update(dependencies)
175
+ return dependencies
176
+
177
+
178
+ def bump_pipfile_or_pyproject(file: Path, dependencies: t.Dict[str, str]) -> None:
179
+ """Bump Pipfile."""
180
+ if not file.exists():
181
+ return
182
+
183
+ _logger.info(f"Updating {file.name}")
184
+ updated = ""
185
+ content = file.read_text(encoding="utf-8")
186
+ for line in content.split("\n"):
187
+ try:
188
+ spec = Dependency.from_pipfile_string(line)
189
+ update = dependencies.get(spec.name)
190
+ if update is None:
191
+ updated += line + "\n"
192
+ continue
193
+ spec = Dependency(
194
+ name=spec.name,
195
+ version=update,
196
+ extras=spec.extras,
197
+ )
198
+ updated += spec.to_pipfile_string() + "\n"
199
+ except ValueError:
200
+ updated += line + "\n"
201
+ file.write_text(updated[:-1], encoding="utf-8")
202
+
203
+
204
+ def bump_tox(dependencies: t.Dict[str, str]) -> None:
205
+ """Bump tox file."""
206
+ if not TOX_INI.exists():
207
+ return
208
+
209
+ _logger.info("Updating tox.ini")
210
+ updated = ""
211
+ content = TOX_INI.read_text(encoding="utf-8")
212
+ for line in content.split("\n"):
213
+ try:
214
+ spec = Dependency.from_string(line.lstrip().rstrip())
215
+ update = dependencies.get(spec.name)
216
+ if update is None:
217
+ updated += line + "\n"
218
+ continue
219
+ spec = Dependency(
220
+ name=spec.name,
221
+ version=update,
222
+ extras=spec.extras,
223
+ )
224
+ updated += " " + spec.to_pip_string() + "\n"
225
+ except ValueError:
226
+ updated += line + "\n"
227
+ TOX_INI.write_text(updated[:-1], encoding="utf-8")
228
+
229
+
230
+ def bump_packages(dependencies: t.Dict[str, str]) -> None:
231
+ """Bump packages."""
232
+ _logger.info("Updating packages")
233
+ manager = PackageManagerV1.from_dir(Path(PACKAGES))
234
+ for package_id in manager.dev_packages:
235
+ path = (
236
+ manager.package_path_from_package_id(
237
+ package_id=package_id,
238
+ )
239
+ / PACKAGE_TYPE_TO_CONFIG_FILE[package_id.package_type.value]
240
+ )
241
+ with path.open("r", encoding="utf-8") as stream:
242
+ config, *extra = yaml_load_all(stream=stream)
243
+
244
+ for name in config.get("dependencies", {}):
245
+ update = dependencies.get(name)
246
+ if update is None:
247
+ continue
248
+ config["dependencies"][name]["version"] = update
249
+
250
+ with path.open("w", encoding="utf-8") as stream:
251
+ yaml_dump_all([config, *extra], stream=stream)
252
+
253
+
254
+ @click.command(name="bump")
255
+ @click.option(
256
+ "-d",
257
+ "--dependency",
258
+ "extra",
259
+ type=PyPiDependency(),
260
+ multiple=True,
261
+ help="Specify extra dependency.",
262
+ )
263
+ @click.option(
264
+ "-s",
265
+ "--source",
266
+ "sources",
267
+ type=PackagesSource(),
268
+ multiple=True,
269
+ help="Specify extra sources.",
270
+ )
271
+ @click.option("--sync", is_flag=True, help="Perform sync.")
272
+ @click.option(
273
+ "--no-cache",
274
+ is_flag=True,
275
+ default=False,
276
+ help="Avoid using cache to bump.",
277
+ )
278
+ def main(
279
+ extra: t.Tuple[Dependency, ...],
280
+ sources: t.Tuple[str, ...],
281
+ sync: bool,
282
+ no_cache: bool,
283
+ ) -> None:
284
+ """Run the bump script."""
285
+
286
+ if not no_cache:
287
+ load_git_cache()
288
+
289
+ dependencies = {}
290
+ dependencies.update(get_dependencies())
291
+ dependencies.update({dep.name: dep.version for dep in extra or []})
292
+
293
+ bump_pipfile_or_pyproject(PIPFILE, dependencies=dependencies)
294
+ bump_pipfile_or_pyproject(PYPROJECT_TOML, dependencies=dependencies)
295
+ bump_tox(dependencies=dependencies)
296
+ bump_packages(dependencies=dependencies)
297
+ dump_git_cache()
298
+
299
+ if sync:
300
+ pm = PackageManagerV1.from_dir(
301
+ Path.cwd() / PACKAGES, config_loader=load_configuration
302
+ )
303
+ pm.sync(
304
+ sources=[
305
+ f"{OPEN_AEA_REPO}:{_version_cache[OPEN_AEA_REPO]}",
306
+ f"{OPEN_AUTONOMY_REPO}:{_version_cache[OPEN_AUTONOMY_REPO]}",
307
+ *sources,
308
+ ],
309
+ update_packages=True,
310
+ )
311
+ pm.update_package_hashes()
312
+ pm.dump()
313
+
314
+
315
+ if __name__ == "__main__":
316
+ main() # pylint: disable=no-value-for-parameter
@@ -0,0 +1,118 @@
1
+ # -*- coding: utf-8 -*-
2
+ # ------------------------------------------------------------------------------
3
+ #
4
+ # Copyright 2025 Valory AG
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ # ------------------------------------------------------------------------------
19
+
20
+
21
+ import sys
22
+ from pathlib import Path
23
+ from typing import Optional
24
+ from aea_ledger_ethereum import EthereumApi, EthereumCrypto
25
+ from dataclasses import asdict
26
+
27
+ from mech_client.interact import get_mech_config, PRIVATE_KEY_FILE_PATH
28
+ from .utils import (
29
+ print_title,
30
+ CHAIN_TO_NATIVE_BALANCE_TRACKER,
31
+ )
32
+ from mech_client.wss import wait_for_receipt
33
+
34
+
35
+ def deposit(
36
+ ledger_api: EthereumApi,
37
+ crypto: EthereumCrypto,
38
+ to: str,
39
+ amount: int,
40
+ ) -> str:
41
+ sender = crypto.address
42
+
43
+ try:
44
+ print("Fetching user balance")
45
+ user_balance = ledger_api.get_balance(address=sender)
46
+ if user_balance < amount:
47
+ formatted_user_balance = user_balance / 1e18
48
+ formatted_amount = amount / 1e18
49
+ print("User balance low!!")
50
+ print(f"Balance: {formatted_user_balance}")
51
+ print(f"Want to Deposit: {formatted_amount}")
52
+ sys.exit(1)
53
+ except Exception as e:
54
+ print(f"Error occured while fetching user balance: {e}")
55
+ return str(e)
56
+
57
+ try:
58
+ print("Sending deposit tx")
59
+ raw_transaction = ledger_api.get_transfer_transaction(
60
+ sender_address=sender,
61
+ destination_address=to,
62
+ amount=amount,
63
+ tx_fee=50000,
64
+ tx_nonce="0x",
65
+ )
66
+ signed_transaction = crypto.sign_transaction(raw_transaction)
67
+ transaction_digest = ledger_api.send_signed_transaction(
68
+ signed_transaction,
69
+ raise_on_try=True,
70
+ )
71
+ return transaction_digest
72
+ except Exception as e: # pylint: disable=broad-except
73
+ print(f"Error occured while sending the transaction: {e}")
74
+ return str(e)
75
+
76
+
77
+ def main(
78
+ amount: str,
79
+ private_key_path: Optional[str] = None,
80
+ chain_config: Optional[str] = None,
81
+ ) -> None:
82
+ """Runs the deposit functionality for the native mech type"""
83
+ print_title("Native Deposit")
84
+ print("This script will assist you in depositing native balance for mech requests.")
85
+ print()
86
+
87
+ amount_to_deposit = int(float(amount) * 10**18)
88
+ private_key_path = private_key_path or PRIVATE_KEY_FILE_PATH
89
+
90
+ mech_config = get_mech_config(chain_config)
91
+ ledger_config = mech_config.ledger_config
92
+ ledger_api = EthereumApi(**asdict(ledger_config))
93
+
94
+ if not Path(private_key_path).exists():
95
+ raise FileNotFoundError(
96
+ f"Private key file `{private_key_path}` does not exist!"
97
+ )
98
+ crypto = EthereumCrypto(private_key_path=private_key_path)
99
+
100
+ print(f"Sender address: {crypto.address}")
101
+
102
+ chain_id = mech_config.ledger_config.chain_id
103
+ to = CHAIN_TO_NATIVE_BALANCE_TRACKER[chain_id]
104
+
105
+ deposit_tx = deposit(ledger_api, crypto, to, amount_to_deposit)
106
+ if not deposit_tx:
107
+ print("Unable to deposit")
108
+ sys.exit(1)
109
+
110
+ transaction_url_formatted = mech_config.transaction_url.format(
111
+ transaction_digest=deposit_tx
112
+ )
113
+ print(f" - Transaction sent: {transaction_url_formatted}")
114
+ print(" - Waiting for transaction receipt...")
115
+ wait_for_receipt(deposit_tx, ledger_api)
116
+
117
+ print("")
118
+ print("Deposit Successful")