dkg 1.1.1__py3-none-any.whl → 8.0.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.
Files changed (45) hide show
  1. dkg/asset.py +589 -683
  2. dkg/constants.py +106 -45
  3. dkg/data/interfaces/AskStorage.json +366 -0
  4. dkg/data/interfaces/Chronos.json +202 -0
  5. dkg/data/interfaces/Hub.json +294 -2
  6. dkg/data/interfaces/IdentityStorage.json +400 -0
  7. dkg/data/interfaces/KnowledgeCollection.json +610 -0
  8. dkg/data/interfaces/KnowledgeCollectionStorage.json +2312 -0
  9. dkg/data/interfaces/Paranet.json +656 -135
  10. dkg/data/interfaces/ParanetIncentivesPoolFactory.json +18 -2
  11. dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json +20 -4
  12. dkg/data/interfaces/{ParanetNeurowebIncentivesPool.json → ParanetNeuroIncentivesPool.json} +7 -7
  13. dkg/data/interfaces/ParanetsRegistry.json +844 -36
  14. dkg/data/interfaces/Token.json +146 -17
  15. dkg/dataclasses.py +11 -1
  16. dkg/exceptions.py +1 -0
  17. dkg/graph.py +55 -24
  18. dkg/main.py +18 -2
  19. dkg/network.py +2 -2
  20. dkg/node.py +7 -0
  21. dkg/paranet.py +336 -33
  22. dkg/providers/blockchain.py +23 -24
  23. dkg/providers/node_http.py +11 -9
  24. dkg/services/input_service.py +183 -0
  25. dkg/services/node_service.py +164 -0
  26. dkg/types/__init__.py +15 -3
  27. dkg/types/general.py +15 -8
  28. dkg/utils/blockchain_request.py +189 -64
  29. dkg/utils/knowledge_asset_tools.py +5 -0
  30. dkg/utils/knowledge_collection_tools.py +236 -0
  31. dkg/utils/merkle.py +1 -1
  32. dkg/utils/node_request.py +33 -33
  33. dkg/utils/rdf.py +10 -6
  34. dkg/utils/string_transformations.py +1 -0
  35. {dkg-1.1.1.dist-info → dkg-8.0.0.dist-info}/METADATA +36 -26
  36. dkg-8.0.0.dist-info/RECORD +56 -0
  37. {dkg-1.1.1.dist-info → dkg-8.0.0.dist-info}/WHEEL +1 -1
  38. dkg/data/interfaces/AssertionStorage.json +0 -229
  39. dkg/data/interfaces/ContentAsset.json +0 -801
  40. dkg/data/interfaces/ContentAssetStorage.json +0 -782
  41. dkg/data/interfaces/ServiceAgreementStorageProxy.json +0 -1314
  42. dkg/data/interfaces/UnfinalizedStateStorage.json +0 -171
  43. dkg-1.1.1.dist-info/RECORD +0 -52
  44. {dkg-1.1.1.dist-info → dkg-8.0.0.dist-info}/LICENSE +0 -0
  45. {dkg-1.1.1.dist-info → dkg-8.0.0.dist-info}/NOTICE +0 -0
dkg/paranet.py CHANGED
@@ -21,7 +21,12 @@ from dataclasses import dataclass
21
21
  from web3 import Web3
22
22
  from web3.types import TxReceipt
23
23
 
24
- from dkg.dataclasses import BaseIncentivesPoolParams, ParanetIncentivizationType
24
+ from dkg.dataclasses import (
25
+ BaseIncentivesPoolParams,
26
+ ParanetIncentivizationType,
27
+ ParanetNodesAccessPolicy,
28
+ ParanetMinersAccessPolicy,
29
+ )
25
30
  from dkg.manager import DefaultRequestManager
26
31
  from dkg.method import Method
27
32
  from dkg.module import Module
@@ -57,7 +62,12 @@ class Paranet(Module):
57
62
  _register_paranet = Method(BlockchainRequest.register_paranet)
58
63
 
59
64
  def create(
60
- self, ual: UAL, name: str, description: str
65
+ self,
66
+ ual: UAL,
67
+ name: str,
68
+ description: str,
69
+ paranet_nodes_access_policy: ParanetNodesAccessPolicy,
70
+ paranet_miners_access_policy: ParanetMinersAccessPolicy,
61
71
  ) -> dict[str, str | HexStr | TxReceipt]:
62
72
  parsed_ual = parse_ual(ual)
63
73
  knowledge_asset_storage, knowledge_asset_token_id = (
@@ -70,6 +80,8 @@ class Paranet(Module):
70
80
  knowledge_asset_token_id,
71
81
  name,
72
82
  description,
83
+ paranet_nodes_access_policy,
84
+ paranet_miners_access_policy,
73
85
  )
74
86
 
75
87
  return {
@@ -83,6 +95,328 @@ class Paranet(Module):
83
95
  "operation": json.loads(Web3.to_json(receipt)),
84
96
  }
85
97
 
98
+ _add_paranet_curated_nodes = Method(BlockchainRequest.add_paranet_curated_nodes)
99
+
100
+ def add_curated_nodes(
101
+ self, paranet_ual: UAL, identity_ids: list[int]
102
+ ) -> dict[str, str | HexStr | TxReceipt]:
103
+ parsed_ual = parse_ual(paranet_ual)
104
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
105
+ parsed_ual["contract_address"],
106
+ parsed_ual["token_id"],
107
+ )
108
+
109
+ receipt = self._add_paranet_curated_nodes(
110
+ paranet_knowledge_asset_storage,
111
+ paranet_knowledge_asset_token_id,
112
+ identity_ids,
113
+ )
114
+
115
+ return {
116
+ "paranetUAL": paranet_ual,
117
+ "paranetId": Web3.to_hex(
118
+ Web3.solidity_keccak(
119
+ ["address", "uint256"],
120
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
121
+ )
122
+ ),
123
+ "operation": json.loads(Web3.to_json(receipt)),
124
+ }
125
+
126
+ _remove_paranet_curated_nodes = Method(
127
+ BlockchainRequest.remove_paranet_curated_nodes
128
+ )
129
+
130
+ def remove_curated_nodes(
131
+ self, paranet_ual: UAL, identity_ids: list[int]
132
+ ) -> dict[str, str | HexStr | TxReceipt]:
133
+ parsed_ual = parse_ual(paranet_ual)
134
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
135
+ parsed_ual["contract_address"],
136
+ parsed_ual["token_id"],
137
+ )
138
+
139
+ receipt = self._remove_paranet_curated_nodes(
140
+ paranet_knowledge_asset_storage,
141
+ paranet_knowledge_asset_token_id,
142
+ identity_ids,
143
+ )
144
+
145
+ return {
146
+ "paranetUAL": paranet_ual,
147
+ "paranetId": Web3.to_hex(
148
+ Web3.solidity_keccak(
149
+ ["address", "uint256"],
150
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
151
+ )
152
+ ),
153
+ "operation": json.loads(Web3.to_json(receipt)),
154
+ }
155
+
156
+ _request_paranet_curated_node_access = Method(
157
+ BlockchainRequest.request_paranet_curated_node_access
158
+ )
159
+
160
+ def request_curated_node_access(
161
+ self, paranet_ual: UAL
162
+ ) -> dict[str, str | HexStr | TxReceipt]:
163
+ parsed_ual = parse_ual(paranet_ual)
164
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
165
+ parsed_ual["contract_address"],
166
+ parsed_ual["token_id"],
167
+ )
168
+
169
+ receipt = self._request_paranet_curated_node_access(
170
+ paranet_knowledge_asset_storage,
171
+ paranet_knowledge_asset_token_id,
172
+ )
173
+
174
+ return {
175
+ "paranetUAL": paranet_ual,
176
+ "paranetId": Web3.to_hex(
177
+ Web3.solidity_keccak(
178
+ ["address", "uint256"],
179
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
180
+ )
181
+ ),
182
+ "operation": json.loads(Web3.to_json(receipt)),
183
+ }
184
+
185
+ _approve_curated_node = Method(BlockchainRequest.approve_curated_node)
186
+
187
+ def approve_curated_node(
188
+ self, paranet_ual: UAL, identity_id: int
189
+ ) -> dict[str, str | HexStr | TxReceipt]:
190
+ parsed_ual = parse_ual(paranet_ual)
191
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
192
+ parsed_ual["contract_address"],
193
+ parsed_ual["token_id"],
194
+ )
195
+
196
+ receipt = self._approve_curated_node(
197
+ paranet_knowledge_asset_storage,
198
+ paranet_knowledge_asset_token_id,
199
+ identity_id,
200
+ )
201
+
202
+ return {
203
+ "paranetUAL": paranet_ual,
204
+ "paranetId": Web3.to_hex(
205
+ Web3.solidity_keccak(
206
+ ["address", "uint256"],
207
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
208
+ )
209
+ ),
210
+ "operation": json.loads(Web3.to_json(receipt)),
211
+ }
212
+
213
+ _reject_curated_node = Method(BlockchainRequest.reject_curated_node)
214
+
215
+ def reject_curated_node(
216
+ self, paranet_ual: UAL, identity_id: int
217
+ ) -> dict[str, str | HexStr | TxReceipt]:
218
+ parsed_ual = parse_ual(paranet_ual)
219
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
220
+ parsed_ual["contract_address"],
221
+ parsed_ual["token_id"],
222
+ )
223
+
224
+ receipt = self._reject_curated_node(
225
+ paranet_knowledge_asset_storage,
226
+ paranet_knowledge_asset_token_id,
227
+ identity_id,
228
+ )
229
+
230
+ return {
231
+ "paranetUAL": paranet_ual,
232
+ "paranetId": Web3.to_hex(
233
+ Web3.solidity_keccak(
234
+ ["address", "uint256"],
235
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
236
+ )
237
+ ),
238
+ "operation": json.loads(Web3.to_json(receipt)),
239
+ }
240
+
241
+ _get_curated_nodes = Method(BlockchainRequest.get_curated_nodes)
242
+
243
+ def get_curated_nodes(
244
+ self, paranet_ual: UAL
245
+ ) -> dict[str, str | HexStr | TxReceipt]:
246
+ parsed_ual = parse_ual(paranet_ual)
247
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
248
+ parsed_ual["contract_address"],
249
+ parsed_ual["token_id"],
250
+ )
251
+
252
+ paranet_id = Web3.solidity_keccak(
253
+ ["address", "uint256"],
254
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
255
+ )
256
+
257
+ return self._get_curated_nodes(paranet_id)
258
+
259
+ _add_paranet_curated_miners = Method(BlockchainRequest.add_paranet_curated_miners)
260
+
261
+ def add_curated_miners(
262
+ self, paranet_ual: UAL, miner_addresses: list[Address]
263
+ ) -> dict[str, str | HexStr | TxReceipt]:
264
+ parsed_ual = parse_ual(paranet_ual)
265
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
266
+ parsed_ual["contract_address"],
267
+ parsed_ual["token_id"],
268
+ )
269
+
270
+ receipt = self._add_paranet_curated_miners(
271
+ paranet_knowledge_asset_storage,
272
+ paranet_knowledge_asset_token_id,
273
+ miner_addresses,
274
+ )
275
+
276
+ return {
277
+ "paranetUAL": paranet_ual,
278
+ "paranetId": Web3.to_hex(
279
+ Web3.solidity_keccak(
280
+ ["address", "uint256"],
281
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
282
+ )
283
+ ),
284
+ "operation": json.loads(Web3.to_json(receipt)),
285
+ }
286
+
287
+ _remove_paranet_curated_miners = Method(
288
+ BlockchainRequest.remove_paranet_curated_miners
289
+ )
290
+
291
+ def remove_curated_miners(
292
+ self, paranet_ual: UAL, miner_addresses: list[Address]
293
+ ) -> dict[str, str | HexStr | TxReceipt]:
294
+ parsed_ual = parse_ual(paranet_ual)
295
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
296
+ parsed_ual["contract_address"],
297
+ parsed_ual["token_id"],
298
+ )
299
+
300
+ receipt = self._remove_paranet_curated_miners(
301
+ paranet_knowledge_asset_storage,
302
+ paranet_knowledge_asset_token_id,
303
+ miner_addresses,
304
+ )
305
+
306
+ return {
307
+ "paranetUAL": paranet_ual,
308
+ "paranetId": Web3.to_hex(
309
+ Web3.solidity_keccak(
310
+ ["address", "uint256"],
311
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
312
+ )
313
+ ),
314
+ "operation": json.loads(Web3.to_json(receipt)),
315
+ }
316
+
317
+ _request_paranet_curated_miner_access = Method(
318
+ BlockchainRequest.request_paranet_curated_miner_access
319
+ )
320
+
321
+ def request_curated_miner_access(
322
+ self, paranet_ual: UAL
323
+ ) -> dict[str, str | HexStr | TxReceipt]:
324
+ parsed_ual = parse_ual(paranet_ual)
325
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
326
+ parsed_ual["contract_address"],
327
+ parsed_ual["token_id"],
328
+ )
329
+
330
+ receipt = self._request_paranet_curated_miner_access(
331
+ paranet_knowledge_asset_storage,
332
+ paranet_knowledge_asset_token_id,
333
+ )
334
+
335
+ return {
336
+ "paranetUAL": paranet_ual,
337
+ "paranetId": Web3.to_hex(
338
+ Web3.solidity_keccak(
339
+ ["address", "uint256"],
340
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
341
+ )
342
+ ),
343
+ "operation": json.loads(Web3.to_json(receipt)),
344
+ }
345
+
346
+ _approve_curated_miner = Method(BlockchainRequest.approve_curated_miner)
347
+
348
+ def approve_curated_miner(
349
+ self, paranet_ual: UAL, miner_address: Address
350
+ ) -> dict[str, str | HexStr | TxReceipt]:
351
+ parsed_ual = parse_ual(paranet_ual)
352
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
353
+ parsed_ual["contract_address"],
354
+ parsed_ual["token_id"],
355
+ )
356
+
357
+ receipt = self._approve_curated_miner(
358
+ paranet_knowledge_asset_storage,
359
+ paranet_knowledge_asset_token_id,
360
+ miner_address,
361
+ )
362
+
363
+ return {
364
+ "paranetUAL": paranet_ual,
365
+ "paranetId": Web3.to_hex(
366
+ Web3.solidity_keccak(
367
+ ["address", "uint256"],
368
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
369
+ )
370
+ ),
371
+ "operation": json.loads(Web3.to_json(receipt)),
372
+ }
373
+
374
+ _reject_curated_miner = Method(BlockchainRequest.reject_curated_miner)
375
+
376
+ def reject_curated_miner(
377
+ self, paranet_ual: UAL, miner_address: Address
378
+ ) -> dict[str, str | HexStr | TxReceipt]:
379
+ parsed_ual = parse_ual(paranet_ual)
380
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
381
+ parsed_ual["contract_address"],
382
+ parsed_ual["token_id"],
383
+ )
384
+
385
+ receipt = self._reject_curated_miner(
386
+ paranet_knowledge_asset_storage,
387
+ paranet_knowledge_asset_token_id,
388
+ miner_address,
389
+ )
390
+
391
+ return {
392
+ "paranetUAL": paranet_ual,
393
+ "paranetId": Web3.to_hex(
394
+ Web3.solidity_keccak(
395
+ ["address", "uint256"],
396
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
397
+ )
398
+ ),
399
+ "operation": json.loads(Web3.to_json(receipt)),
400
+ }
401
+
402
+ _get_knowledge_miners = Method(BlockchainRequest.get_knowledge_miners)
403
+
404
+ def get_knowledge_miners(
405
+ self, paranet_ual: UAL
406
+ ) -> dict[str, str | HexStr | TxReceipt]:
407
+ parsed_ual = parse_ual(paranet_ual)
408
+ paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = (
409
+ parsed_ual["contract_address"],
410
+ parsed_ual["token_id"],
411
+ )
412
+
413
+ paranet_id = Web3.solidity_keccak(
414
+ ["address", "uint256"],
415
+ [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id],
416
+ )
417
+
418
+ return self._get_knowledge_miners(paranet_id)
419
+
86
420
  _deploy_neuro_incentives_pool = Method(
87
421
  BlockchainRequest.deploy_neuro_incentives_pool
88
422
  )
@@ -424,37 +758,6 @@ class Paranet(Module):
424
758
  _get_updating_knowledge_asset_states = Method(
425
759
  BlockchainRequest.get_updating_knowledge_asset_states
426
760
  )
427
- _process_updated_knowledge_asset_states_metadata = Method(
428
- BlockchainRequest.process_updated_knowledge_asset_states_metadata
429
- )
430
-
431
- def update_claimable_rewards(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]:
432
- parsed_ual = parse_ual(ual)
433
- knowledge_asset_storage, knowledge_asset_token_id = (
434
- parsed_ual["contract_address"],
435
- parsed_ual["token_id"],
436
- )
437
-
438
- paranet_id = Web3.solidity_keccak(
439
- ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id]
440
- )
441
-
442
- updating_states = self._get_updating_knowledge_asset_states(
443
- self.manager.blockchain_provider.account.address,
444
- paranet_id,
445
- )
446
- receipt: TxReceipt = self._process_updated_knowledge_asset_states_metadata(
447
- knowledge_asset_storage,
448
- knowledge_asset_token_id,
449
- 0,
450
- len(updating_states),
451
- )
452
-
453
- return {
454
- "paranetUAL": ual,
455
- "paranetId": paranet_id,
456
- "operation": json.loads(Web3.to_json(receipt)),
457
- }
458
761
 
459
762
  def _get_incentives_pool_contract(
460
763
  self,
@@ -17,13 +17,14 @@
17
17
 
18
18
  import json
19
19
  import os
20
+ from dotenv import load_dotenv
20
21
  from collections import namedtuple
21
22
  from functools import wraps
22
23
  from pathlib import Path
23
24
  from typing import Any, Type
24
25
 
25
26
  import requests
26
- from dkg.constants import BLOCKCHAINS, DEFAULT_GAS_PRICE_GWEI
27
+ from dkg.constants import BLOCKCHAINS
27
28
  from dkg.exceptions import (
28
29
  AccountMissing,
29
30
  EnvironmentNotSupported,
@@ -32,12 +33,13 @@ from dkg.exceptions import (
32
33
  )
33
34
  from dkg.types import URI, Address, DataHexStr, Environment, Wei
34
35
  from eth_account.signers.local import LocalAccount
36
+ from eth_typing import ABI, ABIFunction
35
37
  from web3 import Web3
36
38
  from web3.contract import Contract
37
39
  from web3.contract.contract import ContractFunction
38
40
  from web3.logs import DISCARD
39
- from web3.middleware import construct_sign_and_send_raw_middleware
40
- from web3.types import ABI, ABIFunction, TxReceipt
41
+ from web3.middleware import SignAndSendRawMiddlewareBuilder
42
+ from web3.types import TxReceipt
41
43
 
42
44
 
43
45
  class BlockchainProvider:
@@ -48,7 +50,6 @@ class BlockchainProvider:
48
50
  environment: Environment,
49
51
  blockchain_id: str,
50
52
  rpc_uri: URI | None = None,
51
- private_key: DataHexStr | None = None,
52
53
  gas_price: Wei | None = None,
53
54
  verify: bool = True,
54
55
  ):
@@ -105,11 +106,9 @@ class BlockchainProvider:
105
106
  }
106
107
  self._init_contracts()
107
108
 
108
- if (
109
- private_key is not None
110
- or (private_key_env := os.environ.get("PRIVATE_KEY", None)) is not None
111
- ):
112
- self.set_account(private_key or private_key_env)
109
+ load_dotenv()
110
+ if private_key := os.environ.get("PRIVATE_KEY"):
111
+ self.set_account(private_key)
113
112
 
114
113
  def make_json_rpc_request(self, endpoint: str, args: dict[str, Any] = {}) -> Any:
115
114
  web3_method = getattr(self.w3.eth, endpoint)
@@ -181,13 +180,15 @@ class BlockchainProvider:
181
180
  "account."
182
181
  )
183
182
 
184
- gas_price = self.gas_price or gas_price or self._get_network_gas_price()
185
-
186
183
  options = {
187
- "gasPrice": gas_price,
188
184
  "gas": gas_limit or contract_function(**args).estimate_gas(),
189
185
  }
190
186
 
187
+ gas_price = self.gas_price or gas_price or self._get_network_gas_price()
188
+
189
+ if gas_price is not None:
190
+ options["gasPrice"] = gas_price
191
+
191
192
  tx_hash = contract_function(**args).transact(options)
192
193
  tx_receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
193
194
 
@@ -204,8 +205,9 @@ class BlockchainProvider:
204
205
 
205
206
  def set_account(self, private_key: DataHexStr):
206
207
  self.account: LocalAccount = self.w3.eth.account.from_key(private_key)
207
- self.w3.middleware_onion.add(
208
- construct_sign_and_send_raw_middleware(self.account)
208
+ self.w3.middleware_onion.inject(
209
+ SignAndSendRawMiddlewareBuilder.build(private_key),
210
+ layer=0,
209
211
  )
210
212
  self.w3.eth.default_account = self.account.address
211
213
 
@@ -213,12 +215,6 @@ class BlockchainProvider:
213
215
  if self.environment == "development":
214
216
  return None
215
217
 
216
- blockchain_name, _ = self.blockchain_id.split(":")
217
-
218
- default_gas_price = self.w3.to_wei(
219
- DEFAULT_GAS_PRICE_GWEI[blockchain_name], "gwei"
220
- )
221
-
222
218
  def fetch_gas_price(oracle_url: str) -> Wei | None:
223
219
  try:
224
220
  response = requests.get(oracle_url)
@@ -244,7 +240,7 @@ class BlockchainProvider:
244
240
  if gas_price is not None:
245
241
  return gas_price
246
242
 
247
- return default_gas_price
243
+ return None
248
244
 
249
245
  def _init_contracts(self):
250
246
  for contract in self.abi.keys():
@@ -262,11 +258,14 @@ class BlockchainProvider:
262
258
  ):
263
259
  self.contracts[contract] = self.w3.eth.contract(
264
260
  address=(
265
- self.contracts["Hub"].functions.getContractAddress(contract).call()
266
- if not contract.endswith("AssetStorage")
267
- else self.contracts["Hub"]
261
+ self.contracts["Hub"]
268
262
  .functions.getAssetStorageAddress(contract)
269
263
  .call()
264
+ if contract.endswith("AssetStorage")
265
+ or contract.endswith("CollectionStorage")
266
+ else self.contracts["Hub"]
267
+ .functions.getContractAddress(contract)
268
+ .call()
270
269
  ),
271
270
  abi=self.abi[contract],
272
271
  decode_tuples=True,
@@ -25,9 +25,14 @@ from requests.exceptions import HTTPError, ConnectionError, Timeout, RequestExce
25
25
 
26
26
 
27
27
  class NodeHTTPProvider:
28
- def __init__(self, endpoint_uri: URI | str, auth_token: str | None = None):
29
- self.endpoint_uri = URI(endpoint_uri)
30
- self.auth_token = auth_token
28
+ def __init__(
29
+ self,
30
+ endpoint_uri: URI | str,
31
+ api_version: str = "v1",
32
+ auth_token: str | None = None,
33
+ ):
34
+ self.url = f"{URI(endpoint_uri)}/{api_version}"
35
+ self.headers = {"Authorization": f"Bearer {auth_token}"} if auth_token else {}
31
36
 
32
37
  def make_request(
33
38
  self,
@@ -36,16 +41,13 @@ class NodeHTTPProvider:
36
41
  params: dict[str, Any] = {},
37
42
  data: dict[str, Any] = {},
38
43
  ) -> NodeResponseDict:
39
- url = f"{self.endpoint_uri}/{path}"
40
- headers = (
41
- {"Authorization": f"Bearer {self.auth_token}"} if self.auth_token else {}
42
- )
44
+ url = f"{self.url}/{path}"
43
45
 
44
46
  try:
45
47
  if method == HTTPRequestMethod.GET:
46
- response = requests.get(url, params=params, headers=headers)
48
+ response = requests.get(url, params=params, headers=self.headers)
47
49
  elif method == HTTPRequestMethod.POST:
48
- response = requests.post(url, json=data, headers=headers)
50
+ response = requests.post(url, json=data, headers=self.headers)
49
51
  else:
50
52
  raise HTTPRequestMethodNotSupported(
51
53
  f"{method.name} method isn't supported"