mech-client 0.14.0__py3-none-any.whl → 0.15.0__py3-none-any.whl
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.
- mech_client/__init__.py +1 -1
- mech_client/cli.py +257 -11
- mech_client/configs/mechs.json +110 -110
- mech_client/interact.py +6 -1
- mech_client/marketplace_interact.py +161 -43
- mech_client/safe.py +73 -0
- mech_client/subgraph.py +0 -11
- {mech_client-0.14.0.dist-info → mech_client-0.15.0.dist-info}/METADATA +264 -219
- {mech_client-0.14.0.dist-info → mech_client-0.15.0.dist-info}/RECORD +22 -48
- scripts/deposit_native.py +48 -16
- scripts/deposit_token.py +107 -31
- scripts/nvm_subscribe.py +14 -6
- scripts/nvm_subscription/contracts/base_contract.py +9 -1
- scripts/nvm_subscription/contracts/nft_sales.py +1 -3
- scripts/nvm_subscription/contracts/subscription_provider.py +2 -4
- scripts/nvm_subscription/contracts/token.py +23 -5
- scripts/nvm_subscription/manager.py +109 -16
- scripts/utils.py +2 -2
- scripts/whitelist.py +9 -1
- mech_client/helpers/acn/README.md +0 -76
- mech_client/helpers/acn/__init__.py +0 -30
- mech_client/helpers/acn/acn.proto +0 -71
- mech_client/helpers/acn/acn_pb2.py +0 -42
- mech_client/helpers/acn/custom_types.py +0 -224
- mech_client/helpers/acn/dialogues.py +0 -126
- mech_client/helpers/acn/message.py +0 -274
- mech_client/helpers/acn/protocol.yaml +0 -24
- mech_client/helpers/acn/serialization.py +0 -149
- mech_client/helpers/acn/tests/__init__.py +0 -20
- mech_client/helpers/acn/tests/test_acn.py +0 -256
- mech_client/helpers/acn/tests/test_acn_dialogues.py +0 -53
- mech_client/helpers/acn/tests/test_acn_messages.py +0 -117
- mech_client/helpers/acn_data_share/README.md +0 -32
- mech_client/helpers/acn_data_share/__init__.py +0 -32
- mech_client/helpers/acn_data_share/acn_data_share.proto +0 -17
- mech_client/helpers/acn_data_share/acn_data_share_pb2.py +0 -29
- mech_client/helpers/acn_data_share/dialogues.py +0 -115
- mech_client/helpers/acn_data_share/message.py +0 -213
- mech_client/helpers/acn_data_share/protocol.yaml +0 -21
- mech_client/helpers/acn_data_share/serialization.py +0 -111
- mech_client/helpers/acn_data_share/tests/test_acn_data_share_dialogues.py +0 -49
- mech_client/helpers/acn_data_share/tests/test_acn_data_share_messages.py +0 -53
- mech_client/helpers/p2p_libp2p_client/README.md +0 -15
- mech_client/helpers/p2p_libp2p_client/__init__.py +0 -21
- mech_client/helpers/p2p_libp2p_client/connection.py +0 -703
- mech_client/helpers/p2p_libp2p_client/connection.yaml +0 -52
- {mech_client-0.14.0.dist-info → mech_client-0.15.0.dist-info}/LICENSE +0 -0
- {mech_client-0.14.0.dist-info → mech_client-0.15.0.dist-info}/WHEEL +0 -0
- {mech_client-0.14.0.dist-info → mech_client-0.15.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# ------------------------------------------------------------------------------
|
|
3
3
|
#
|
|
4
|
-
# Copyright 2024 Valory AG
|
|
4
|
+
# Copyright 2024-2025 Valory AG
|
|
5
5
|
#
|
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
# you may not use this file except in compliance with the License.
|
|
@@ -52,6 +52,7 @@ from mech_client.interact import (
|
|
|
52
52
|
)
|
|
53
53
|
from mech_client.mech_marketplace_tool_management import get_mech_tools
|
|
54
54
|
from mech_client.prompt_to_ipfs import push_metadata_to_ipfs
|
|
55
|
+
from mech_client.safe import EthereumClient, get_safe_nonce, send_safe_tx
|
|
55
56
|
from mech_client.wss import wait_for_receipt, watch_for_marketplace_request_ids
|
|
56
57
|
|
|
57
58
|
|
|
@@ -61,13 +62,26 @@ class PaymentType(Enum):
|
|
|
61
62
|
|
|
62
63
|
NATIVE = "ba699a34be8fe0e7725e93dcbce1701b0211a8ca61330aaeb8a05bf2ec7abed1" # nosec
|
|
63
64
|
TOKEN = "3679d66ef546e66ce9057c4a052f317b135bc8e8c509638f7966edfd4fcf45e9" # nosec
|
|
65
|
+
USDC_TOKEN = (
|
|
66
|
+
"6406bb5f31a732f898e1ce9fdd988a80a808d36ab5d9a4a4805a8be8d197d5e3" # nosec
|
|
67
|
+
)
|
|
64
68
|
NATIVE_NVM = (
|
|
65
69
|
"803dd08fe79d91027fc9024e254a0942372b92f3ccabc1bd19f4a5c2b251c316" # nosec
|
|
66
70
|
)
|
|
67
|
-
|
|
71
|
+
TOKEN_NVM_USDC = (
|
|
68
72
|
"0d6fd99afa9c4c580fab5e341922c2a5c4b61d880da60506193d7bf88944dd14" # nosec
|
|
69
73
|
)
|
|
70
74
|
|
|
75
|
+
@classmethod
|
|
76
|
+
def get_token_payment_types(cls) -> List[str]:
|
|
77
|
+
"""Get all token-based payment types that require ERC20 approval."""
|
|
78
|
+
return [cls.TOKEN.value, cls.USDC_TOKEN.value]
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def get_prepaid_supported_types(cls) -> List[str]:
|
|
82
|
+
"""Get payment types that support prepaid balances."""
|
|
83
|
+
return [cls.NATIVE.value, cls.TOKEN.value, cls.USDC_TOKEN.value]
|
|
84
|
+
|
|
71
85
|
|
|
72
86
|
IPFS_URL_TEMPLATE = "https://gateway.autonolas.tech/ipfs/f01701220{}"
|
|
73
87
|
MECH_OFFCHAIN_REQUEST_ENDPOINT = "send_signed_requests"
|
|
@@ -91,17 +105,18 @@ BALANCE_TRACKER_NVM_TOKEN_ABI_PATH = (
|
|
|
91
105
|
PAYMENT_TYPE_TO_ABI_PATH: Dict[str, Path] = {
|
|
92
106
|
PaymentType.NATIVE.value: BALANCE_TRACKER_NATIVE_ABI_PATH,
|
|
93
107
|
PaymentType.TOKEN.value: BALANCE_TRACKER_TOKEN_ABI_PATH,
|
|
108
|
+
PaymentType.USDC_TOKEN.value: BALANCE_TRACKER_TOKEN_ABI_PATH,
|
|
94
109
|
PaymentType.NATIVE_NVM.value: BALANCE_TRACKER_NVM_NATIVE_ABI_PATH,
|
|
95
|
-
PaymentType.
|
|
110
|
+
PaymentType.TOKEN_NVM_USDC.value: BALANCE_TRACKER_NVM_TOKEN_ABI_PATH,
|
|
96
111
|
}
|
|
97
112
|
|
|
98
113
|
CHAIN_TO_PRICE_TOKEN = {
|
|
99
114
|
1: "0x0001A500A6B18995B03f44bb040A5fFc28E45CB0",
|
|
100
115
|
10: "0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527",
|
|
101
116
|
100: "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f",
|
|
102
|
-
137: "
|
|
117
|
+
137: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
103
118
|
8453: "0x54330d28ca3357F294334BDC454a032e7f353416",
|
|
104
|
-
42220: "
|
|
119
|
+
42220: "0x96ffa56a963EC33e5bC7057B9002722D1884fc01",
|
|
105
120
|
}
|
|
106
121
|
|
|
107
122
|
|
|
@@ -114,6 +129,10 @@ CHAIN_TO_DEFAULT_MECH_MARKETPLACE_REQUEST_CONFIG = {
|
|
|
114
129
|
"response_timeout": 300,
|
|
115
130
|
"payment_data": "0x",
|
|
116
131
|
},
|
|
132
|
+
137: {
|
|
133
|
+
"response_timeout": 300,
|
|
134
|
+
"payment_data": "0x",
|
|
135
|
+
},
|
|
117
136
|
}
|
|
118
137
|
|
|
119
138
|
|
|
@@ -176,7 +195,6 @@ def fetch_mech_info(
|
|
|
176
195
|
payment_type_bytes
|
|
177
196
|
).call()
|
|
178
197
|
)
|
|
179
|
-
|
|
180
198
|
if payment_type not in PaymentType._value2member_map_: # pylint: disable=W0212
|
|
181
199
|
print(" - Invalid mech type detected.")
|
|
182
200
|
sys.exit(1)
|
|
@@ -189,9 +207,12 @@ def fetch_mech_info(
|
|
|
189
207
|
)
|
|
190
208
|
|
|
191
209
|
|
|
192
|
-
def approve_price_tokens(
|
|
210
|
+
def approve_price_tokens( # pylint: disable=too-many-arguments, too-many-locals
|
|
193
211
|
crypto: EthereumCrypto,
|
|
194
212
|
ledger_api: EthereumApi,
|
|
213
|
+
ethereum_client: EthereumClient,
|
|
214
|
+
agent_mode: bool,
|
|
215
|
+
safe_address: str,
|
|
195
216
|
wrapped_token: str,
|
|
196
217
|
mech_payment_balance_tracker: str,
|
|
197
218
|
price: int,
|
|
@@ -203,6 +224,12 @@ def approve_price_tokens(
|
|
|
203
224
|
:type crypto: EthereumCrypto
|
|
204
225
|
:param ledger_api: The Ethereum API used for interacting with the ledger.
|
|
205
226
|
:type ledger_api: EthereumApi
|
|
227
|
+
:param ethereum_client: The Ethereum Client used for interacting with the safe.
|
|
228
|
+
:type ethereum_client: EthereumClient
|
|
229
|
+
:param agent_mode: Specifies whether agent mode is active or not.
|
|
230
|
+
:type agent_mode: bool
|
|
231
|
+
:param safe_address: Specifies the safe address related to the configured service, empty is client mode.
|
|
232
|
+
:type safe_address: str
|
|
206
233
|
:param wrapped_token: The wrapped token contract address.
|
|
207
234
|
:type wrapped_token: str
|
|
208
235
|
:param mech_payment_balance_tracker: Requested mech's balance tracker contract address
|
|
@@ -212,7 +239,9 @@ def approve_price_tokens(
|
|
|
212
239
|
:return: The transaction digest.
|
|
213
240
|
:rtype: str
|
|
214
241
|
"""
|
|
215
|
-
|
|
242
|
+
# Tokens will be on the safe and EOA pays for gas
|
|
243
|
+
# so for agent mode, sender has to be safe
|
|
244
|
+
sender = safe_address or crypto.address
|
|
216
245
|
|
|
217
246
|
with open(ITOKEN_ABI_PATH, encoding="utf-8") as f:
|
|
218
247
|
abi = json.load(f)
|
|
@@ -230,19 +259,41 @@ def approve_price_tokens(
|
|
|
230
259
|
sys.exit(1)
|
|
231
260
|
|
|
232
261
|
tx_args = {"sender_address": sender, "value": 0, "gas": 60000}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
262
|
+
method_name = "approve"
|
|
263
|
+
method_args = {"_to": mech_payment_balance_tracker, "_value": price}
|
|
264
|
+
|
|
265
|
+
if not agent_mode:
|
|
266
|
+
raw_transaction = ledger_api.build_transaction(
|
|
267
|
+
contract_instance=token_contract,
|
|
268
|
+
method_name=method_name,
|
|
269
|
+
method_args=method_args,
|
|
270
|
+
tx_args=tx_args,
|
|
271
|
+
raise_on_try=True,
|
|
272
|
+
)
|
|
273
|
+
signed_transaction = crypto.sign_transaction(raw_transaction)
|
|
274
|
+
transaction_digest = ledger_api.send_signed_transaction(
|
|
275
|
+
signed_transaction,
|
|
276
|
+
raise_on_try=True,
|
|
277
|
+
)
|
|
278
|
+
return transaction_digest
|
|
279
|
+
|
|
280
|
+
function = token_contract.functions[method_name](**method_args)
|
|
281
|
+
transaction = function.build_transaction(
|
|
282
|
+
{
|
|
283
|
+
"chainId": int(ledger_api._chain_id), # pylint: disable=protected-access
|
|
284
|
+
"gas": 0,
|
|
285
|
+
"nonce": get_safe_nonce(ethereum_client, safe_address),
|
|
286
|
+
}
|
|
239
287
|
)
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
288
|
+
transaction_digest = send_safe_tx(
|
|
289
|
+
ethereum_client=ethereum_client,
|
|
290
|
+
tx_data=transaction["data"],
|
|
291
|
+
to_adress=token_contract.address,
|
|
292
|
+
safe_address=safe_address,
|
|
293
|
+
signer_pkey=crypto.private_key,
|
|
294
|
+
value=0,
|
|
244
295
|
)
|
|
245
|
-
return transaction_digest
|
|
296
|
+
return transaction_digest.hex()
|
|
246
297
|
|
|
247
298
|
|
|
248
299
|
def fetch_requester_nvm_subscription_balance(
|
|
@@ -300,10 +351,13 @@ def fetch_requester_nvm_subscription_balance(
|
|
|
300
351
|
def send_marketplace_request( # pylint: disable=too-many-arguments,too-many-locals
|
|
301
352
|
crypto: EthereumCrypto,
|
|
302
353
|
ledger_api: EthereumApi,
|
|
354
|
+
ethereum_client: EthereumClient,
|
|
303
355
|
marketplace_contract: Web3Contract,
|
|
304
356
|
gas_limit: int,
|
|
305
357
|
prompts: tuple,
|
|
306
358
|
tools: tuple,
|
|
359
|
+
agent_mode: bool,
|
|
360
|
+
safe_address: str,
|
|
307
361
|
method_args_data: MechMarketplaceRequestConfig,
|
|
308
362
|
extra_attributes: Optional[Dict[str, Any]] = None,
|
|
309
363
|
price: int = 10_000_000_000_000_000,
|
|
@@ -318,6 +372,8 @@ def send_marketplace_request( # pylint: disable=too-many-arguments,too-many-loc
|
|
|
318
372
|
:type crypto: EthereumCrypto
|
|
319
373
|
:param ledger_api: The Ethereum API used for interacting with the ledger.
|
|
320
374
|
:type ledger_api: EthereumApi
|
|
375
|
+
:param ethereum_client: The Ethereum Client used for interacting with the safe.
|
|
376
|
+
:type ethereum_client: EthereumClient
|
|
321
377
|
:param marketplace_contract: The mech marketplace contract instance.
|
|
322
378
|
:type marketplace_contract: Web3Contract
|
|
323
379
|
:param gas_limit: Gas limit.
|
|
@@ -326,6 +382,10 @@ def send_marketplace_request( # pylint: disable=too-many-arguments,too-many-loc
|
|
|
326
382
|
:type prompts: tuple
|
|
327
383
|
:param tools: The requested tools.
|
|
328
384
|
:type tools: tuple
|
|
385
|
+
:param agent_mode: Specifies whether agent mode is active or not.
|
|
386
|
+
:type agent_mode: bool
|
|
387
|
+
:param safe_address: Specifies the safe address related to the configured service, empty is client mode.
|
|
388
|
+
:type safe_address: str
|
|
329
389
|
:param method_args_data: Method data to use to call the marketplace contract request
|
|
330
390
|
:type method_args_data: MechMarketplaceRequestConfig
|
|
331
391
|
:param extra_attributes: Extra attributes to be included in the request metadata.
|
|
@@ -390,19 +450,40 @@ def send_marketplace_request( # pylint: disable=too-many-arguments,too-many-loc
|
|
|
390
450
|
while tries < retries and datetime.now().timestamp() < deadline:
|
|
391
451
|
tries += 1
|
|
392
452
|
try:
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
453
|
+
if not agent_mode:
|
|
454
|
+
raw_transaction = ledger_api.build_transaction(
|
|
455
|
+
contract_instance=marketplace_contract,
|
|
456
|
+
method_name=method_name,
|
|
457
|
+
method_args=method_args,
|
|
458
|
+
tx_args=tx_args,
|
|
459
|
+
raise_on_try=True,
|
|
460
|
+
)
|
|
461
|
+
signed_transaction = crypto.sign_transaction(raw_transaction)
|
|
462
|
+
transaction_digest = ledger_api.send_signed_transaction(
|
|
463
|
+
signed_transaction,
|
|
464
|
+
raise_on_try=True,
|
|
465
|
+
)
|
|
466
|
+
return transaction_digest
|
|
467
|
+
|
|
468
|
+
function = marketplace_contract.functions[method_name](**method_args)
|
|
469
|
+
transaction = function.build_transaction(
|
|
470
|
+
{
|
|
471
|
+
"chainId": int(
|
|
472
|
+
ledger_api._chain_id # pylint: disable=protected-access
|
|
473
|
+
),
|
|
474
|
+
"gas": 0,
|
|
475
|
+
"nonce": get_safe_nonce(ethereum_client, safe_address),
|
|
476
|
+
}
|
|
399
477
|
)
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
478
|
+
transaction_digest = send_safe_tx(
|
|
479
|
+
ethereum_client=ethereum_client,
|
|
480
|
+
tx_data=transaction["data"],
|
|
481
|
+
to_adress=marketplace_contract.address,
|
|
482
|
+
safe_address=safe_address,
|
|
483
|
+
signer_pkey=crypto.private_key,
|
|
484
|
+
value=price,
|
|
404
485
|
)
|
|
405
|
-
return transaction_digest
|
|
486
|
+
return transaction_digest.hex()
|
|
406
487
|
except Exception as e: # pylint: disable=broad-except
|
|
407
488
|
print(
|
|
408
489
|
f"Error occured while sending the transaction: {e}; Retrying in {sleep}"
|
|
@@ -616,9 +697,10 @@ def wait_for_offchain_marketplace_data(mech_offchain_url: str, request_id: str)
|
|
|
616
697
|
time.sleep(WAIT_SLEEP)
|
|
617
698
|
|
|
618
699
|
|
|
619
|
-
def check_prepaid_balances(
|
|
700
|
+
def check_prepaid_balances( # pylint: disable=too-many-arguments
|
|
620
701
|
crypto: Crypto,
|
|
621
702
|
ledger_api: EthereumApi,
|
|
703
|
+
safe_address: str,
|
|
622
704
|
mech_payment_balance_tracker: str,
|
|
623
705
|
payment_type: str,
|
|
624
706
|
max_delivery_rate: int,
|
|
@@ -630,6 +712,8 @@ def check_prepaid_balances(
|
|
|
630
712
|
:type crypto: Crypto
|
|
631
713
|
:param ledger_api: The Ethereum API used for interacting with the ledger.
|
|
632
714
|
:type ledger_api: EthereumApi
|
|
715
|
+
:param safe_address: Specifies the safe address related to the configured service, empty is client mode.
|
|
716
|
+
:type safe_address: str
|
|
633
717
|
:param mech_payment_balance_tracker: The mech's balance tracker contract address.
|
|
634
718
|
:type mech_payment_balance_tracker: str
|
|
635
719
|
:param payment_type: The payment type of the mech.
|
|
@@ -637,9 +721,9 @@ def check_prepaid_balances(
|
|
|
637
721
|
:param max_delivery_rate: The max_delivery_rate of the mech
|
|
638
722
|
:type max_delivery_rate: int
|
|
639
723
|
"""
|
|
640
|
-
requester = crypto.address
|
|
724
|
+
requester = safe_address or crypto.address
|
|
641
725
|
|
|
642
|
-
if payment_type in
|
|
726
|
+
if payment_type in PaymentType.get_prepaid_supported_types():
|
|
643
727
|
payment_type_name = PaymentType(payment_type).name.lower()
|
|
644
728
|
payment_type_abi_path = PAYMENT_TYPE_TO_ABI_PATH[payment_type]
|
|
645
729
|
|
|
@@ -680,7 +764,6 @@ def verify_tools(tools: tuple, service_id: int, chain_config: Optional[str]) ->
|
|
|
680
764
|
mech_tools_data = get_mech_tools(service_id=service_id, chain_config=chain_config)
|
|
681
765
|
if not mech_tools_data:
|
|
682
766
|
raise ValueError("Error while fetching mech tools data")
|
|
683
|
-
|
|
684
767
|
mech_tools = mech_tools_data.get("tools", [])
|
|
685
768
|
invalid_tools = [tool for tool in tools if tool not in mech_tools]
|
|
686
769
|
if invalid_tools:
|
|
@@ -692,12 +775,15 @@ def verify_tools(tools: tuple, service_id: int, chain_config: Optional[str]) ->
|
|
|
692
775
|
def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals, too-many-statements, too-many-return-statements
|
|
693
776
|
prompts: tuple,
|
|
694
777
|
priority_mech: str,
|
|
778
|
+
agent_mode: bool,
|
|
779
|
+
safe_address: str,
|
|
695
780
|
use_prepaid: bool = False,
|
|
696
781
|
use_offchain: bool = False,
|
|
697
782
|
mech_offchain_url: str = "",
|
|
698
783
|
tools: tuple = (),
|
|
699
784
|
extra_attributes: Optional[Dict[str, Any]] = None,
|
|
700
785
|
private_key_path: Optional[str] = None,
|
|
786
|
+
private_key_password: Optional[str] = None,
|
|
701
787
|
retries: Optional[int] = None,
|
|
702
788
|
timeout: Optional[float] = None,
|
|
703
789
|
sleep: Optional[float] = None,
|
|
@@ -708,8 +794,12 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
708
794
|
|
|
709
795
|
:param prompts: The interaction prompts.
|
|
710
796
|
:type prompts: tuple
|
|
711
|
-
:param priority_mech: Priority mech address to use
|
|
797
|
+
:param priority_mech: Priority mech address to use
|
|
712
798
|
:type priority_mech: str
|
|
799
|
+
:param agent_mode: Specifies whether agent mode is active or not.
|
|
800
|
+
:type agent_mode: bool
|
|
801
|
+
:param safe_address: Specifies the safe address related to the configured service, empty is client mode.
|
|
802
|
+
:type safe_address: str
|
|
713
803
|
:param use_prepaid: Whether to use prepaid model or not.
|
|
714
804
|
:type use_prepaid: bool
|
|
715
805
|
:param use_offchain: Whether to use offchain model or not.
|
|
@@ -722,6 +812,8 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
722
812
|
:type extra_attributes: Optional[Dict[str, Any]]
|
|
723
813
|
:param private_key_path: The path to the private key file (optional).
|
|
724
814
|
:type private_key_path: Optional[str]
|
|
815
|
+
:param private_key_password: Password to decrypt the keystore (if encrypted).
|
|
816
|
+
:type private_key_password: Optional[str]
|
|
725
817
|
:return: The data received from on-chain/off-chain.
|
|
726
818
|
:param retries: Number of retries for sending a transaction
|
|
727
819
|
:type retries: int
|
|
@@ -735,6 +827,8 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
735
827
|
"""
|
|
736
828
|
|
|
737
829
|
mech_config = get_mech_config(chain_config)
|
|
830
|
+
ledger_rpc = mech_config.ledger_config.address
|
|
831
|
+
ethereum_client = EthereumClient(ledger_rpc)
|
|
738
832
|
ledger_config = mech_config.ledger_config
|
|
739
833
|
priority_mech_address = priority_mech
|
|
740
834
|
mech_marketplace_contract = mech_config.mech_marketplace_contract
|
|
@@ -770,8 +864,9 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
770
864
|
raise FileNotFoundError(
|
|
771
865
|
f"Private key file `{private_key_path}` does not exist!"
|
|
772
866
|
)
|
|
773
|
-
|
|
774
|
-
|
|
867
|
+
crypto = EthereumCrypto(
|
|
868
|
+
private_key_path=private_key_path, password=private_key_password
|
|
869
|
+
)
|
|
775
870
|
ledger_api = EthereumApi(**asdict(ledger_config))
|
|
776
871
|
|
|
777
872
|
with open(MARKETPLACE_ABI_PATH, encoding="utf-8") as f:
|
|
@@ -801,16 +896,35 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
801
896
|
mech_deliver_event_signature = fetch_mech_deliver_event_signature(
|
|
802
897
|
ledger_api, priority_mech_address
|
|
803
898
|
)
|
|
804
|
-
|
|
805
899
|
verify_tools(tools, service_id, chain_config)
|
|
806
|
-
|
|
807
900
|
if not use_prepaid:
|
|
808
901
|
price = max_delivery_rate * num_requests
|
|
809
|
-
if payment_type == PaymentType.
|
|
810
|
-
print(
|
|
902
|
+
if payment_type == PaymentType.NATIVE.value:
|
|
903
|
+
print(
|
|
904
|
+
"Native Mech detected, fetching user native balance for price payment..."
|
|
905
|
+
)
|
|
906
|
+
sender = safe_address or crypto.address
|
|
907
|
+
balance = ledger_api.get_balance(sender)
|
|
908
|
+
if balance < price:
|
|
909
|
+
print(
|
|
910
|
+
f" - Sender Native balance low. Needed: {price}, Actual: {balance}"
|
|
911
|
+
)
|
|
912
|
+
print(f" - Sender Address: {sender}")
|
|
913
|
+
sys.exit(1)
|
|
914
|
+
if payment_type in PaymentType.get_token_payment_types():
|
|
811
915
|
price_token = CHAIN_TO_PRICE_TOKEN[chain_id]
|
|
916
|
+
print(
|
|
917
|
+
f"Token Mech detected, approving token {price_token} for price payment..."
|
|
918
|
+
)
|
|
812
919
|
approve_tx = approve_price_tokens(
|
|
813
|
-
crypto,
|
|
920
|
+
crypto,
|
|
921
|
+
ledger_api,
|
|
922
|
+
ethereum_client,
|
|
923
|
+
agent_mode,
|
|
924
|
+
safe_address,
|
|
925
|
+
price_token,
|
|
926
|
+
mech_payment_balance_tracker,
|
|
927
|
+
price,
|
|
814
928
|
)
|
|
815
929
|
if not approve_tx:
|
|
816
930
|
print("Unable to approve allowance")
|
|
@@ -832,6 +946,7 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
832
946
|
check_prepaid_balances(
|
|
833
947
|
crypto,
|
|
834
948
|
ledger_api,
|
|
949
|
+
safe_address,
|
|
835
950
|
mech_payment_balance_tracker,
|
|
836
951
|
payment_type,
|
|
837
952
|
max_delivery_rate,
|
|
@@ -839,7 +954,7 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
839
954
|
|
|
840
955
|
is_nvm_mech = payment_type in [
|
|
841
956
|
PaymentType.NATIVE_NVM.value,
|
|
842
|
-
PaymentType.
|
|
957
|
+
PaymentType.TOKEN_NVM_USDC.value,
|
|
843
958
|
]
|
|
844
959
|
if is_nvm_mech:
|
|
845
960
|
nvm_mech_type = PaymentType(payment_type).name.lower()
|
|
@@ -874,11 +989,14 @@ def marketplace_interact( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
874
989
|
transaction_digest = send_marketplace_request(
|
|
875
990
|
crypto=crypto,
|
|
876
991
|
ledger_api=ledger_api,
|
|
992
|
+
ethereum_client=ethereum_client,
|
|
877
993
|
marketplace_contract=mech_marketplace_contract,
|
|
878
994
|
gas_limit=mech_config.gas_limit,
|
|
879
995
|
price=price,
|
|
880
996
|
prompts=prompts,
|
|
881
997
|
tools=tools,
|
|
998
|
+
agent_mode=agent_mode,
|
|
999
|
+
safe_address=safe_address,
|
|
882
1000
|
method_args_data=mech_marketplace_request_config,
|
|
883
1001
|
extra_attributes=extra_attributes,
|
|
884
1002
|
retries=retries,
|
mech_client/safe.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
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
|
+
"""Mech client Safe Module."""
|
|
21
|
+
from typing import Optional
|
|
22
|
+
|
|
23
|
+
from hexbytes import HexBytes
|
|
24
|
+
from safe_eth.eth import EthereumClient # pylint:disable=import-error
|
|
25
|
+
from safe_eth.safe import Safe # pylint:disable=import-error
|
|
26
|
+
from web3.constants import ADDRESS_ZERO
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def send_safe_tx( # pylint: disable=too-many-arguments
|
|
30
|
+
ethereum_client: EthereumClient,
|
|
31
|
+
tx_data: str,
|
|
32
|
+
to_adress: str,
|
|
33
|
+
safe_address: str,
|
|
34
|
+
signer_pkey: str,
|
|
35
|
+
value: int = 0,
|
|
36
|
+
) -> Optional[HexBytes]:
|
|
37
|
+
"""Send a Safe transaction"""
|
|
38
|
+
# Get the safe
|
|
39
|
+
safe = Safe( # pylint:disable=abstract-class-instantiated
|
|
40
|
+
safe_address, ethereum_client
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
estimated_gas = safe.estimate_tx_gas_with_safe(
|
|
44
|
+
to=to_adress, value=value, data=bytes.fromhex(tx_data[2:]), operation=0
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Build, sign and send the safe transaction
|
|
48
|
+
safe_tx = safe.build_multisig_tx(
|
|
49
|
+
to=to_adress,
|
|
50
|
+
value=value,
|
|
51
|
+
data=bytes.fromhex(tx_data[2:]),
|
|
52
|
+
operation=0,
|
|
53
|
+
safe_tx_gas=estimated_gas,
|
|
54
|
+
base_gas=0,
|
|
55
|
+
gas_price=0,
|
|
56
|
+
gas_token=ADDRESS_ZERO,
|
|
57
|
+
refund_receiver=ADDRESS_ZERO,
|
|
58
|
+
)
|
|
59
|
+
safe_tx.sign(signer_pkey)
|
|
60
|
+
try:
|
|
61
|
+
tx_hash, _ = safe_tx.execute(signer_pkey)
|
|
62
|
+
return tx_hash
|
|
63
|
+
except Exception as e: # pylint: disable=broad-except
|
|
64
|
+
print(f"Exception while sending a safe transaction: {e}")
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_safe_nonce(ethereum_client: EthereumClient, safe_address: str) -> int:
|
|
69
|
+
"""Get the Safe nonce"""
|
|
70
|
+
safe = Safe( # pylint:disable=abstract-class-instantiated
|
|
71
|
+
safe_address, ethereum_client
|
|
72
|
+
)
|
|
73
|
+
return safe.retrieve_nonce()
|
mech_client/subgraph.py
CHANGED
|
@@ -35,21 +35,10 @@ AGENT_QUERY_TEMPLATE = Template(
|
|
|
35
35
|
DEFAULT_TIMEOUT = 600.0
|
|
36
36
|
CHAIN_TO_ADDRESSES = {
|
|
37
37
|
"gnosis": {
|
|
38
|
-
3: "0xFf82123dFB52ab75C417195c5fDB87630145ae81",
|
|
39
38
|
6: "0x77af31De935740567Cf4fF1986D04B2c964A786a",
|
|
40
39
|
9: "0x552cea7bc33cbbeb9f1d90c1d11d2c6daeffd053",
|
|
41
|
-
11: "0x9aDe7A78A39B39a44b7a084923E93AA0B19Fd690",
|
|
42
40
|
19: "0x45b73d649c7b982548d5a6dd3d35e1c5c48997d0",
|
|
43
41
|
},
|
|
44
|
-
"base": {
|
|
45
|
-
1: "0x37C484cc34408d0F827DB4d7B6e54b8837Bf8BDA",
|
|
46
|
-
2: "0x111D7DB1B752AB4D2cC0286983D9bd73a49bac6c",
|
|
47
|
-
3: "0x111D7DB1B752AB4D2cC0286983D9bd73a49bac6c",
|
|
48
|
-
},
|
|
49
|
-
"arbitrum": {2: "0x1FDAD3a5af5E96e5a64Fc0662B1814458F114597"},
|
|
50
|
-
"polygon": {2: "0xbF92568718982bf65ee4af4F7020205dE2331a8a"},
|
|
51
|
-
"celo": {2: "0x230eD015735c0D01EA0AaD2786Ed6Bd3C6e75912"},
|
|
52
|
-
"optimism": {2: "0xDd40E7D93c37eFD860Bd53Ab90b2b0a8D05cf71a"},
|
|
53
42
|
}
|
|
54
43
|
|
|
55
44
|
|