From 41cd68480802f8390be504d8fe5980e7202cdb23 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Fri, 4 Oct 2024 17:21:40 +0700 Subject: [PATCH 001/146] Changed config to support V8 envs --- dkg/constants.py | 41 +++-------------------------------------- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 39 deletions(-) diff --git a/dkg/constants.py b/dkg/constants.py index 170d0dd..7bd0dff 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -31,53 +31,18 @@ }, }, "devnet": { - "otp:2160": { - "hub": "0x833048F6e6BEa78E0AAdedeCd2Dc2231dda443FB", - "rpc": "https://lofar-tm-rpc.origin-trail.network", - }, - "gnosis:10200": { - "hub": "0xD2bA102A0b11944d00180eE8136208ccF87bC39A", - "rpc": "https://rpc.chiadochain.net", - "gas_price_oracle": "https://blockscout.chiadochain.net/api/v1/gas-price-oracle", - }, "base:84532": { - "hub": "0x6C861Cb69300C34DfeF674F7C00E734e840C29C0", + "hub": "0xaA849CAC4FA86f6b7484503f3c7a314772AED6d4", "rpc": "https://sepolia.base.org", } }, "testnet": { - "otp:20430": { - "hub": "0xBbfF7Ea6b2Addc1f38A0798329e12C08f03750A6", - "rpc": "https://lofar-testnet.origin-trail.network", - }, - "gnosis:10200": { - "hub": "0xC06210312C9217A0EdF67453618F5eB96668679A", - "rpc": "https://rpc.chiadochain.net", - "gas_price_oracle": "https://blockscout.chiadochain.net/api/v1/gas-price-oracle", - }, "base:84532": { - "hub": "0x144eDa5cbf8926327cb2cceef168A121F0E4A299", + "hub": "0xCca0eA14540588A09c85cD6A6Fc53eA3A7010692", "rpc": "https://sepolia.base.org", } }, - "mainnet": { - "otp:2043": { - "hub": "0x5fA7916c48Fe6D5F1738d12Ad234b78c90B4cAdA", - "rpc": "https://astrosat-parachain-rpc.origin-trail.network", - }, - "gnosis:100": { - "hub": "0xbEF14fc04F870c2dD65c13Df4faB6ba01A9c746b", - "rpc": "https://rpc.gnosischain.com/", - "gas_price_oracle": [ - "https://api.gnosisscan.io/api?module=proxy&action=eth_gasPrice", - "https://blockscout.com/xdai/mainnet/api/v1/gas-price-oracle", - ], - }, - "base:8453": { - "hub": "0xaBfcf2ad1718828E7D3ec20435b0d0b5EAfbDf2c", - "rpc": "https://mainnet.base.org", - }, - }, + "mainnet": {}, } DEFAULT_GAS_PRICE_GWEI = { diff --git a/pyproject.toml b/pyproject.toml index c5ca5c2..c6c3de9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "1.1.1" +version = "8.0.0a0" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar "] license = "Apache-2.0" From 18fcaafe6176bc850464b8ea8f8f60355a952630 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Fri, 4 Oct 2024 18:05:45 +0700 Subject: [PATCH 002/146] Deprecated Updated --- dkg/asset.py | 198 +-------------------------------------------------- 1 file changed, 3 insertions(+), 195 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index ff7de13..bb946b9 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -418,143 +418,6 @@ def transfer( "operation": json.loads(Web3.to_json(receipt)), } - _update = Method(NodeRequest.update) - - _get_block = Method(BlockchainRequest.get_block) - - _get_service_agreement_data = Method(BlockchainRequest.get_service_agreement_data) - _update_asset_state = Method(BlockchainRequest.update_asset_state) - - def update( - self, - ual: UAL, - content: dict[Literal["public", "private"], JSONLD], - token_amount: Wei | None = None, - content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - ) -> dict[str, UAL | HexStr | dict[str, str]]: - parsed_ual = parse_ual(ual) - blockchain_id, content_asset_storage_address, token_id = ( - parsed_ual["blockchain"], - parsed_ual["contract_address"], - parsed_ual["token_id"], - ) - - assertions = format_content(content, content_type) - - public_assertion_id = MerkleTree( - hash_assertion_with_indexes(assertions["public"]), - sort_pairs=True, - ).root - public_assertion_metadata = generate_assertion_metadata(assertions["public"]) - - if token_amount is None: - agreement_id = self.get_agreement_id( - content_asset_storage_address, token_id - ) - # TODO: Dynamic types for namedtuples? - agreement_data: Type[AgreementData] = self._get_service_agreement_data( - agreement_id - ) - - timestamp_now = self._get_block("latest")["timestamp"] - current_epoch = math.floor( - (timestamp_now - agreement_data.startTime) / agreement_data.epochLength - ) - epochs_left = agreement_data.epochsNumber - current_epoch - - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - epochs_left, - public_assertion_metadata["size"], - content_asset_storage_address, - public_assertion_id, - DEFAULT_HASH_FUNCTION_ID, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] - ) - - token_amount -= agreement_data.tokens[0] - token_amount = token_amount if token_amount > 0 else 0 - - current_allowance = self.get_current_allowance() - if is_allowance_increased := current_allowance < token_amount: - self.increase_allowance(token_amount) - - try: - self._update_asset_state( - token_id=token_id, - assertion_id=public_assertion_id, - size=public_assertion_metadata["size"], - triples_number=public_assertion_metadata["triples_number"], - chunks_number=public_assertion_metadata["chunks_number"], - update_token_amount=token_amount, - ) - except ContractLogicError as err: - if is_allowance_increased: - self.decrease_allowance(token_amount) - raise err - - assertions_list = [ - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": public_assertion_id, - "assertion": assertions["public"], - "storeType": StoreTypes.PENDING, - } - ] - - if content.get("private", None): - assertions_list.append( - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": MerkleTree( - hash_assertion_with_indexes(assertions["private"]), - sort_pairs=True, - ).root, - "assertion": assertions["private"], - "storeType": StoreTypes.PENDING, - } - ) - - operation_id = self._local_store(assertions_list)["operationId"] - self.get_operation_result(operation_id, "local-store") - - operation_id = self._update( - public_assertion_id, - assertions["public"], - blockchain_id, - content_asset_storage_address, - token_id, - DEFAULT_HASH_FUNCTION_ID, - )["operationId"] - operation_result = self.get_operation_result(operation_id, "update") - - return { - "UAL": ual, - "publicAssertionId": public_assertion_id, - "operation": { - "operationId": operation_id, - "status": operation_result["status"], - }, - } - - _cancel_update = Method(BlockchainRequest.cancel_asset_state_update) - - def cancel_update(self, ual: UAL) -> dict[str, UAL | TxReceipt]: - token_id = parse_ual(ual)["token_id"] - - receipt: TxReceipt = self._cancel_update(token_id) - - return { - "UAL": ual, - "operation": json.loads(Web3.to_json(receipt)), - } - _burn_asset = Method(BlockchainRequest.burn_asset) def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: @@ -838,7 +701,10 @@ def extend_storing_period( "UAL": ual, "operation": json.loads(Web3.to_json(receipt)), } + + _get_block = Method(BlockchainRequest.get_block) + _get_service_agreement_data = Method(BlockchainRequest.get_service_agreement_data) _get_assertion_size = Method(BlockchainRequest.get_assertion_size) _add_tokens = Method(BlockchainRequest.increase_asset_token_amount) @@ -900,64 +766,6 @@ def add_tokens( "operation": json.loads(Web3.to_json(receipt)), } - _add_update_tokens = Method(BlockchainRequest.increase_asset_update_token_amount) - - def add_update_tokens( - self, - ual: UAL, - token_amount: Wei | None = None, - ) -> dict[str, UAL | TxReceipt]: - parsed_ual = parse_ual(ual) - blockchain_id, content_asset_storage_address, token_id = ( - parsed_ual["blockchain"], - parsed_ual["contract_address"], - parsed_ual["token_id"], - ) - - if token_amount is None: - agreement_id = self.get_agreement_id( - content_asset_storage_address, token_id - ) - # TODO: Dynamic types for namedtuples? - agreement_data: Type[AgreementData] = self._get_service_agreement_data( - agreement_id - ) - - timestamp_now = self._get_block("latest")["timestamp"] - current_epoch = math.floor( - (timestamp_now - agreement_data.startTime) / agreement_data.epochLength - ) - epochs_left = agreement_data.epochsNumber - current_epoch - - unfinalized_state = self._get_latest_assertion_id(token_id) - unfinalized_state_size = self._get_assertion_size(unfinalized_state) - - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - epochs_left, - unfinalized_state_size, - content_asset_storage_address, - unfinalized_state, - DEFAULT_HASH_FUNCTION_ID, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] - ) - sum(agreement_data.tokensInfo) - - if token_amount <= 0: - raise InvalidTokenAmount( - "Token amount is bigger than default suggested amount, " - "please specify exact token_amount if you still want to add " - "more update tokens!" - ) - - receipt: TxReceipt = self._add_update_tokens(token_id, token_amount) - - return { - "UAL": ual, - "operation": json.loads(Web3.to_json(receipt)), - } - def get_owner(self, ual: UAL) -> Address: token_id = parse_ual(ual)["token_id"] From 8bec6d6e5f8a1124b2fe7adf0eb8209c54d8b0d3 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Fri, 4 Oct 2024 18:11:39 +0700 Subject: [PATCH 003/146] Removed Update related functions --- .../interfaces/UnfinalizedStateStorage.json | 171 ------------------ dkg/paranet.py | 31 ---- dkg/utils/blockchain_request.py | 32 ---- dkg/utils/node_request.py | 24 --- examples/demo.py | 27 --- examples/paranets_demo.py | 36 ---- 6 files changed, 321 deletions(-) delete mode 100644 dkg/data/interfaces/UnfinalizedStateStorage.json diff --git a/dkg/data/interfaces/UnfinalizedStateStorage.json b/dkg/data/interfaces/UnfinalizedStateStorage.json deleted file mode 100644 index bf02306..0000000 --- a/dkg/data/interfaces/UnfinalizedStateStorage.json +++ /dev/null @@ -1,171 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "hubAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "deleteIssuer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "deleteUnfinalizedState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getIssuer", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getUnfinalizedState", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "hasPendingUpdate", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hub", - "outputs": [ - { - "internalType": "contract Hub", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "issuer", - "type": "address" - } - ], - "name": "setIssuer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "state", - "type": "bytes32" - } - ], - "name": "setUnfinalizedState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/dkg/paranet.py b/dkg/paranet.py index 474f255..cd25cf1 100644 --- a/dkg/paranet.py +++ b/dkg/paranet.py @@ -424,37 +424,6 @@ def claim_voter_reward( _get_updating_knowledge_asset_states = Method( BlockchainRequest.get_updating_knowledge_asset_states ) - _process_updated_knowledge_asset_states_metadata = Method( - BlockchainRequest.process_updated_knowledge_asset_states_metadata - ) - - def update_claimable_rewards(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( - parsed_ual["contract_address"], - parsed_ual["token_id"], - ) - - paranet_id = Web3.solidity_keccak( - ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id] - ) - - updating_states = self._get_updating_knowledge_asset_states( - self.manager.blockchain_provider.account.address, - paranet_id, - ) - receipt: TxReceipt = self._process_updated_knowledge_asset_states_metadata( - knowledge_asset_storage, - knowledge_asset_token_id, - 0, - len(updating_states), - ) - - return { - "paranetUAL": ual, - "paranetId": paranet_id, - "operation": json.loads(Web3.to_json(receipt)), - } def _get_incentives_pool_contract( self, diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index b684b9b..37c7180 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -93,23 +93,6 @@ class BlockchainRequest: function="burnAsset", args={"tokenId": int}, ) - update_asset_state = ContractTransaction( - contract="ContentAsset", - function="updateAssetState", - args={ - "tokenId": int, - "assertionId": bytes | HexStr, - "size": int, - "triplesNumber": int, - "chunksNumber": int, - "updateTokenAmount": int, - }, - ) - cancel_asset_state_update = ContractTransaction( - contract="ContentAsset", - function="cancelAssetStateUpdate", - args={"tokenId": int}, - ) extend_asset_storing_period = ContractTransaction( contract="ContentAsset", function="extendAssetStoringPeriod", @@ -120,11 +103,6 @@ class BlockchainRequest: function="increaseAssetTokenAmount", args={"tokenId": int, "tokenAmount": int}, ) - increase_asset_update_token_amount = ContractTransaction( - contract="ContentAsset", - function="increaseAssetUpdateTokenAmount", - args={"tokenId": int, "tokenAmount": int}, - ) transfer_asset = ContractTransaction( contract="ContentAssetStorage", @@ -249,16 +227,6 @@ class BlockchainRequest: "paranetId": HexStr, }, ) - process_updated_knowledge_asset_states_metadata = ContractTransaction( - contract="Paranet", - function="processUpdatedKnowledgeAssetStatesMetadata", - args={ - "paranetKAStorageContract": Address, - "paranetKATokenId": int, - "start": int, - "end": int, - }, - ) is_knowledge_miner_registered = ContractCall( contract="ParanetsRegistry", diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 0b07991..34c7374 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -69,18 +69,6 @@ class NodeRequest: "hashFunctionId": int, }, ) - update = NodeCall( - method=HTTPRequestMethod.POST, - path="update", - data={ - "assertionId": str, - "assertion": NQuads, - "blockchain": str, - "contract": Address, - "tokenId": int, - "hashFunctionId": int, - }, - ) get = NodeCall( method=HTTPRequestMethod.POST, path="get", @@ -115,17 +103,6 @@ class PublishOperationStatus(Enum): PUBLISH_END = auto() -class UpdateOperationStatus(AutoStrEnumUpperCase): - UPDATE_START = auto() - UPDATE_INIT_START = auto() - UPDATE_INIT_END = auto() - UPDATE_REPLICATE_START = auto() - UPDATE_REPLICATE_END = auto() - VALIDATING_UPDATE_ASSERTION_REMOTE_START = auto() - VALIDATING_UPDATE_ASSERTION_REMOTE_END = auto() - UPDATE_END = auto() - - class StoreTypes(AutoStrEnumUpperCase): TRIPLE = auto() PENDING = auto() @@ -171,7 +148,6 @@ class OperationStatus(AutoStrEnumUpperCase): DIAL_PROTOCOL_END = auto() LOCAL_STORE = LocalStoreOperationStatus PUBLISH = PublishOperationStatus - UPDATE = UpdateOperationStatus GET = GetOperationStatus QUERY = QueryOperationStatus diff --git a/examples/demo.py b/examples/demo.py index cdf60d1..73d5510 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -154,26 +154,6 @@ def print_json(json_dict: dict): print_json(get_asset_result) divider() -update_asset_result = dkg.asset.update( - create_asset_result["UAL"], - { - "private": { - "@context": ["https://schema.org"], - "@graph": [ - { - "@id": "uuid:user:1", - "name": "Adam", - "lastname": "Smith", - "identifier": f"{math.floor(random.random() * 1e10)}", - }, - ], - }, - }, -) -print("======================== ASSET UPDATED") -print_json(update_asset_result) -divider() - get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") print("======================== ASSET LATEST RESOLVED") print_json(get_latest_asset_result) @@ -206,13 +186,6 @@ def print_json(json_dict: dict): print_json(get_first_state_by_hash) divider() -get_second_state_by_hash = dkg.asset.get( - create_asset_result["UAL"], update_asset_result["publicAssertionId"], "all" -) -print("======================== ASSET SECOND STATE (GET BY STATE HASH) RESOLVED") -print_json(get_second_state_by_hash) -divider() - query_result = dkg.graph.query( "construct { ?s ?p ?o } where { ?s ?p ?o . ?p ?o }", "privateCurrent" ) diff --git a/examples/paranets_demo.py b/examples/paranets_demo.py index 6f79faf..266fe4e 100644 --- a/examples/paranets_demo.py +++ b/examples/paranets_demo.py @@ -307,39 +307,3 @@ def print_reward_stats(is_voter: bool = False): divider() print_reward_stats() - -divider() - -update_asset_result = dkg.asset.update( - create_submit_ka1_result["UAL"], - { - "private": { - "@context": ["https://schema.org"], - "@graph": [ - { - "@id": "uuid:user:1", - "name": "Adam", - "lastname": "Smith", - }, - ], - }, - }, - 100000000000000000000 -) - -print("======================== KA1 UPDATED") -print_json(update_asset_result) - -print("Waiting 30 seconds for the update finalization...") -time.sleep(30) - -divider() - -update_claimable_rewards_result = dkg.paranet.update_claimable_rewards(paranet_ual) - -print("======================== UPDATED CLAIMABLE REWARDS") -print_json(update_claimable_rewards_result) - -divider() - -print_reward_stats() From 6548763529e2040eaaf0d308af200bbf556025b3 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Mon, 7 Oct 2024 16:00:01 +0700 Subject: [PATCH 004/146] Removed default gas price --- dkg/constants.py | 6 ------ dkg/providers/blockchain.py | 18 +++++++----------- pyproject.toml | 2 +- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/dkg/constants.py b/dkg/constants.py index 7bd0dff..e9a48d5 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -45,12 +45,6 @@ "mainnet": {}, } -DEFAULT_GAS_PRICE_GWEI = { - "otp": 1, - "gnosis": 20, - "base": 20, -} - DEFAULT_HASH_FUNCTION_ID = 1 DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS = { "development": { diff --git a/dkg/providers/blockchain.py b/dkg/providers/blockchain.py index 7217d15..095d492 100644 --- a/dkg/providers/blockchain.py +++ b/dkg/providers/blockchain.py @@ -23,7 +23,7 @@ from typing import Any, Type import requests -from dkg.constants import BLOCKCHAINS, DEFAULT_GAS_PRICE_GWEI +from dkg.constants import BLOCKCHAINS from dkg.exceptions import ( AccountMissing, EnvironmentNotSupported, @@ -181,13 +181,15 @@ def call_function( "account." ) - gas_price = self.gas_price or gas_price or self._get_network_gas_price() - options = { - "gasPrice": gas_price, "gas": gas_limit or contract_function(**args).estimate_gas(), } + gas_price = self.gas_price or gas_price or self._get_network_gas_price() + + if gas_price is not None: + options["gasPrice"] = gas_price + tx_hash = contract_function(**args).transact(options) tx_receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash) @@ -213,12 +215,6 @@ def _get_network_gas_price(self) -> Wei | None: if self.environment == "development": return None - blockchain_name, _ = self.blockchain_id.split(":") - - default_gas_price = self.w3.to_wei( - DEFAULT_GAS_PRICE_GWEI[blockchain_name], "gwei" - ) - def fetch_gas_price(oracle_url: str) -> Wei | None: try: response = requests.get(oracle_url) @@ -244,7 +240,7 @@ def fetch_gas_price(oracle_url: str) -> Wei | None: if gas_price is not None: return gas_price - return default_gas_price + return None def _init_contracts(self): for contract in self.abi.keys(): diff --git a/pyproject.toml b/pyproject.toml index c6c3de9..c143af4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.0a0" +version = "8.0.0a1" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar "] license = "Apache-2.0" From 909d7d068a98da83fad72f4e8cccda7240aac46b Mon Sep 17 00:00:00 2001 From: Zvonimir Sculac Date: Mon, 7 Oct 2024 15:48:06 +0200 Subject: [PATCH 005/146] Update paranet create (registerParanet) function --- dkg/data/interfaces/Paranet.json | 10 ++++++++++ dkg/paranet.py | 4 +++- dkg/utils/blockchain_request.py | 2 ++ examples/paranets_demo.py | 10 ++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/dkg/data/interfaces/Paranet.json b/dkg/data/interfaces/Paranet.json index 7eca7ac..f800b65 100644 --- a/dkg/data/interfaces/Paranet.json +++ b/dkg/data/interfaces/Paranet.json @@ -625,6 +625,16 @@ "internalType": "string", "name": "paranetDescription", "type": "string" + }, + { + "internalType": "ParanetStructs.NodesAccessPolicy", + "name": "nodesAccessPolicy", + "type": "uint8" + }, + { + "internalType": "ParanetStructs.MinersAccessPolicy", + "name": "minersAccessPolicy", + "type": "uint8" } ], "name": "registerParanet", diff --git a/dkg/paranet.py b/dkg/paranet.py index cd25cf1..adf85a0 100644 --- a/dkg/paranet.py +++ b/dkg/paranet.py @@ -57,7 +57,7 @@ def __init__(self, manager: DefaultRequestManager): _register_paranet = Method(BlockchainRequest.register_paranet) def create( - self, ual: UAL, name: str, description: str + self, ual: UAL, name: str, description: str, nodes_access_policy: int, miners_access_policy: int ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(ual) knowledge_asset_storage, knowledge_asset_token_id = ( @@ -70,6 +70,8 @@ def create( knowledge_asset_token_id, name, description, + nodes_access_policy, + miners_access_policy ) return { diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index 37c7180..8c1541b 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -157,6 +157,8 @@ class BlockchainRequest: "paranetKATokenId": int, "paranetName": str, "paranetDescription": str, + "nodesAccessPolicy": int, + "minersAccessPolicy": int, }, ) add_paranet_services = ContractTransaction( diff --git a/examples/paranets_demo.py b/examples/paranets_demo.py index 266fe4e..4931e7e 100644 --- a/examples/paranets_demo.py +++ b/examples/paranets_demo.py @@ -32,6 +32,14 @@ dkg = DKG(node_provider, blockchain_provider) +class NODES_ACCESS_POLICY: + OPEN: int = 0 + CURATED: int = 1 + +class MINERS_ACCESS_POLICY: + OPEN: int = 0 + CURATED: int = 1 + def divider(): print("==================================================") @@ -77,6 +85,8 @@ def convert_hexbytes(data): paranet_ual, "TestParanet", "TestParanetDescription", + NODES_ACCESS_POLICY.OPEN, + MINERS_ACCESS_POLICY.OPEN ) print("======================== PARANET CREATED") From 0effd75267e0a40778d89698eceb8fbd853c26d2 Mon Sep 17 00:00:00 2001 From: Zvonimir Sculac Date: Tue, 8 Oct 2024 17:00:30 +0200 Subject: [PATCH 006/146] Add logic for curated nodes and miners --- dkg/paranet.py | 266 ++++++++++++++++++++++++++++++++ dkg/utils/blockchain_request.py | 99 ++++++++++++ 2 files changed, 365 insertions(+) diff --git a/dkg/paranet.py b/dkg/paranet.py index adf85a0..bce0fb6 100644 --- a/dkg/paranet.py +++ b/dkg/paranet.py @@ -85,6 +85,272 @@ def create( "operation": json.loads(Web3.to_json(receipt)), } + _add_paranet_curated_nodes = Method(BlockchainRequest.add_paranet_curated_nodes) + + def add_curated_nodes( + self, ual: UAL, identity_ids: list[int] + ) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + self._add_paranet_curated_nodes( + knowledge_asset_storage, + knowledge_asset_token_id, + identity_ids, + ) + + return { + "paranetUAL": ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": "Add curated nodes" + } + + _remove_paranet_curated_nodes = Method(BlockchainRequest.remove_paranet_curated_nodes) + + def remove_curated_nodes( + self, ual: UAL, identity_ids: list[int] + ) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + self._remove_paranet_curated_nodes( + knowledge_asset_storage, + knowledge_asset_token_id, + identity_ids, + ) + + return { + "paranetUAL": ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": "Remove curated nodes" + } + + _request_paranet_curated_node_access = Method(BlockchainRequest.request_paranet_curated_node_access) + + def request_curated_node_access(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + self._request_paranet_curated_node_access( + knowledge_asset_storage, + knowledge_asset_token_id, + ) + + return { + "paranetUAL": ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": "Request to be included in curated paranet nodes" + } + + _approve_curated_node = Method(BlockchainRequest.approve_curated_node) + + def approve_curated_node(self, ual: UAL, identity_id: int) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + self._approve_curated_node( + knowledge_asset_storage, + knowledge_asset_token_id, + identity_id, + ) + + return { + "paranetUAL": ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": "Approve node's curated paranet access request" + } + + _reject_curated_node = Method(BlockchainRequest.reject_curated_node) + + def reject_curated_node(self, ual: UAL, identity_id: int) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + self._reject_curated_node( + knowledge_asset_storage, + knowledge_asset_token_id, + identity_id, + ) + + return { + "paranetUAL": ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": "Approve node's curated paranet access request" + } + + _add_paranet_curated_miners = Method(BlockchainRequest.add_paranet_curated_miners) + + def add_curated_miners( + self, ual: UAL, miner_addresses: list[Address] + ) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + self._add_paranet_curated_miners( + knowledge_asset_storage, + knowledge_asset_token_id, + miner_addresses, + ) + + return { + "paranetUAL": ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": "Add curated miners" + } + + _remove_paranet_curated_miners = Method(BlockchainRequest.remove_paranet_curated_miners) + + def remove_curated_miners( + self, ual: UAL, miner_addresses: list[Address] + ) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + self._remove_paranet_curated_miners( + knowledge_asset_storage, + knowledge_asset_token_id, + miner_addresses, + ) + + return { + "paranetUAL": ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": "Remove curated miners" + } + + _request_paranet_curated_miner_access = Method(BlockchainRequest.request_paranet_curated_miner_access) + + def request_curated_miner_access(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + self._request_paranet_curated_miner_access( + knowledge_asset_storage, + knowledge_asset_token_id, + ) + + return { + "paranetUAL": ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": "Request to be included in curated paranet miners" + } + + _approve_curated_miner = Method(BlockchainRequest.approve_curated_miner) + + def approve_curated_miner(self, ual: UAL, miner_address: Address) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + self._approve_curated_miner( + knowledge_asset_storage, + knowledge_asset_token_id, + miner_address, + ) + + return { + "paranetUAL": ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": "Approve miner's curated paranet access request" + } + + _reject_curated_miner = Method(BlockchainRequest.reject_curated_miner) + + def reject_curated_miner(self, ual: UAL, miner_address: Address) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + self._reject_curated_miner( + knowledge_asset_storage, + knowledge_asset_token_id, + miner_address, + ) + + return { + "paranetUAL": ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": "Reject miner's curated paranet access request" + } + _deploy_neuro_incentives_pool = Method( BlockchainRequest.deploy_neuro_incentives_pool ) diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index 8c1541b..c5751c5 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -161,6 +161,105 @@ class BlockchainRequest: "minersAccessPolicy": int, }, ) + + add_paranet_curated_nodes = ContractTransaction( + contract="Paranet", + function="addParanetCuratedNodes", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + "identityIds": list[int] + }, + ) + + remove_paranet_curated_nodes = ContractTransaction( + contract="Paranet", + function="removeParanetCuratedNodes", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + "identityIds": list[int] + }, + ) + + request_paranet_curated_node_access = ContractTransaction( + contract="Paranet", + function="requestParanetCuratedNodeAccess", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + }, + ) + + approve_curated_node = ContractTransaction( + contract="Paranet", + function="approveCuratedNode", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + "identityId": int, + }, + ) + + reject_curated_node = ContractTransaction( + contract="Paranet", + function="rejectCuratedNode", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + "identityId": int, + }, + ) + + add_paranet_curated_miners = ContractTransaction( + contract="Paranet", + function="addParanetCuratedMiners", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + "minerAddresses": list[Address] + }, + ) + + remove_paranet_curated_miners = ContractTransaction( + contract="Paranet", + function="removeParanetCuratedMiners", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + "minerAddresses": list[Address] + }, + ) + + request_paranet_curated_miner_access = ContractTransaction( + contract="Paranet", + function="requestParanetCuratedMinerAccess", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + }, + ) + + approve_curated_miner = ContractTransaction( + contract="Paranet", + function="approveCuratedMiner", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + "minerAddress": Address, + }, + ) + + reject_curated_miner = ContractTransaction( + contract="Paranet", + function="rejectCuratedMiner", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + "minerAddress": Address, + }, + ) + add_paranet_services = ContractTransaction( contract="Paranet", function="addParanetServices", From efeb747f5470d3753fc0eb5aff57d2a1ddfaf45c Mon Sep 17 00:00:00 2001 From: Zvonimir Sculac Date: Wed, 9 Oct 2024 17:15:43 +0200 Subject: [PATCH 007/146] Update dkg.py abi --- dkg/data/interfaces/ContentAsset.json | 134 +--- dkg/data/interfaces/ContentAssetStorage.json | 76 -- dkg/data/interfaces/Hub.json | 4 +- dkg/data/interfaces/Paranet.json | 731 ++++++++++++++++- dkg/data/interfaces/ParanetsRegistry.json | 804 ++++++++++++++++++- dkg/paranet.py | 36 + dkg/utils/blockchain_request.py | 12 + examples/curated_paranets_demo.py | 319 ++++++++ 8 files changed, 1868 insertions(+), 248 deletions(-) create mode 100644 examples/curated_paranets_demo.py diff --git a/dkg/data/interfaces/ContentAsset.json b/dkg/data/interfaces/ContentAsset.json index e9f9770..df9ed74 100644 --- a/dkg/data/interfaces/ContentAsset.json +++ b/dkg/data/interfaces/ContentAsset.json @@ -352,7 +352,7 @@ "type": "uint256" } ], - "name": "cancelAssetStateUpdateFromContract", + "name": "clearOldCommitsMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -421,79 +421,7 @@ } ], "name": "createAsset", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "originalSender", - "type": "address" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - } - ], - "internalType": "struct ContentAssetStructs.AssetInputArgs", - "name": "args", - "type": "tuple" - } - ], - "name": "createAssetFromContract", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -541,13 +469,7 @@ } ], "name": "createAssetWithVariables", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -592,7 +514,7 @@ "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } @@ -671,36 +593,10 @@ }, { "inputs": [], - "name": "paranetKnowledgeAssetsRegistry", - "outputs": [ - { - "internalType": "contract ParanetKnowledgeAssetsRegistry", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "paranetKnowledgeMinersRegistry", - "outputs": [ - { - "internalType": "contract ParanetKnowledgeMinersRegistry", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "paranetsRegistry", + "name": "serviceAgreementStorageProxy", "outputs": [ { - "internalType": "contract ParanetsRegistry", + "internalType": "contract ServiceAgreementStorageProxy", "name": "", "type": "address" } @@ -710,10 +606,10 @@ }, { "inputs": [], - "name": "serviceAgreementStorageProxy", + "name": "serviceAgreementV1", "outputs": [ { - "internalType": "contract ServiceAgreementStorageProxy", + "internalType": "contract ServiceAgreementV1", "name": "", "type": "address" } @@ -722,16 +618,16 @@ "type": "function" }, { - "inputs": [], - "name": "serviceAgreementV1", - "outputs": [ + "inputs": [ { - "internalType": "contract ServiceAgreementV1", - "name": "", - "type": "address" + "internalType": "bool", + "name": "_flag", + "type": "bool" } ], - "stateMutability": "view", + "name": "setOldMetadataClearingFlag", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { diff --git a/dkg/data/interfaces/ContentAssetStorage.json b/dkg/data/interfaces/ContentAssetStorage.json index 418789e..b931831 100644 --- a/dkg/data/interfaces/ContentAssetStorage.json +++ b/dkg/data/interfaces/ContentAssetStorage.json @@ -10,11 +10,6 @@ "stateMutability": "nonpayable", "type": "constructor" }, - { - "inputs": [], - "name": "NoMintedAssets", - "type": "error" - }, { "anonymous": false, "inputs": [ @@ -65,38 +60,6 @@ "name": "ApprovalForAll", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_fromTokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_toTokenId", - "type": "uint256" - } - ], - "name": "BatchMetadataUpdate", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "MetadataUpdate", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -475,19 +438,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "lastTokenId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -648,19 +598,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "string", - "name": "baseURI", - "type": "string" - } - ], - "name": "setBaseURI", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -711,19 +648,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "tokenBaseURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { diff --git a/dkg/data/interfaces/Hub.json b/dkg/data/interfaces/Hub.json index 01ee1d2..1c53f39 100644 --- a/dkg/data/interfaces/Hub.json +++ b/dkg/data/interfaces/Hub.json @@ -111,7 +111,7 @@ "type": "address" } ], - "internalType": "struct UnorderedNamedContractDynamicSetStructs.Contract[]", + "internalType": "struct UnorderedNamedContractDynamicSetLib.Contract[]", "name": "", "type": "tuple[]" } @@ -136,7 +136,7 @@ "type": "address" } ], - "internalType": "struct UnorderedNamedContractDynamicSetStructs.Contract[]", + "internalType": "struct UnorderedNamedContractDynamicSetLib.Contract[]", "name": "", "type": "tuple[]" } diff --git a/dkg/data/interfaces/Paranet.json b/dkg/data/interfaces/Paranet.json index f800b65..ba21816 100644 --- a/dkg/data/interfaces/Paranet.json +++ b/dkg/data/interfaces/Paranet.json @@ -10,6 +10,38 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [ + { + "internalType": "enum ParanetStructs.MinersAccessPolicy[]", + "name": "expectedAccessPolicies", + "type": "uint8[]" + }, + { + "internalType": "enum ParanetStructs.MinersAccessPolicy", + "name": "actualAccessPolicy", + "type": "uint8" + } + ], + "name": "InvalidParanetMinersAccessPolicy", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum ParanetStructs.NodesAccessPolicy[]", + "name": "expectedAccessPolicies", + "type": "uint8[]" + }, + { + "internalType": "enum ParanetStructs.NodesAccessPolicy", + "name": "actualAccessPolicy", + "type": "uint8" + } + ], + "name": "InvalidParanetNodesAccessPolicy", + "type": "error" + }, { "inputs": [ { @@ -31,6 +63,144 @@ "name": "KnowledgeAssetIsAPartOfOtherParanet", "type": "error" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + } + ], + "name": "ParanetCuratedMinerAccessRequestDoesntExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "ParanetCuratedMinerAccessRequestInvalidStatus", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + } + ], + "name": "ParanetCuratedMinerDoesntExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + } + ], + "name": "ParanetCuratedMinerHasAlreadyBeenAdded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "ParanetCuratedNodeDoesntExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "ParanetCuratedNodeHasAlreadyBeenAdded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "ParanetCuratedNodeJoinRequestDoesntExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "ParanetCuratedNodeJoinRequestInvalidStatus", + "type": "error" + }, { "inputs": [ { @@ -92,24 +262,291 @@ "type": "bytes32" } ], - "name": "ParanetServiceHasAlreadyBeenAdded", - "type": "error" + "name": "ParanetServiceHasAlreadyBeenAdded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "knowledgeAssetStorageAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ParanetServiceHasAlreadyBeenRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "ProfileDoesntExist", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "knowledgeAssetStorageContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "knowledgeAssetTokenId", + "type": "uint256" + } + ], + "name": "KnowledgeAssetSubmittedToParanet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "minerAddress", + "type": "address" + } + ], + "name": "ParanetCuratedMinerAccessRequestAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "minerAddress", + "type": "address" + } + ], + "name": "ParanetCuratedMinerAccessRequestCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "minerAddress", + "type": "address" + } + ], + "name": "ParanetCuratedMinerAccessRequestRejected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "minerAddress", + "type": "address" + } + ], + "name": "ParanetCuratedMinerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "minerAddress", + "type": "address" + } + ], + "name": "ParanetCuratedMinerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "ParanetCuratedNodeAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "ParanetCuratedNodeJoinRequestAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "ParanetCuratedNodeJoinRequestCreated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "knowledgeAssetStorageAddress", + "name": "paranetKAStorageContract", "type": "address" }, { + "indexed": true, "internalType": "uint256", - "name": "tokenId", + "name": "paranetKATokenId", "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "ParanetServiceHasAlreadyBeenRegistered", - "type": "error" + "name": "ParanetCuratedNodeJoinRequestRejected", + "type": "event" }, { "anonymous": false, @@ -126,20 +563,14 @@ "name": "paranetKATokenId", "type": "uint256" }, - { - "indexed": true, - "internalType": "address", - "name": "knowledgeAssetStorageContract", - "type": "address" - }, { "indexed": false, - "internalType": "uint256", - "name": "knowledgeAssetTokenId", - "type": "uint256" + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "KnowledgeAssetSubmittedToParanet", + "name": "ParanetCuratedNodeRemoved", "type": "event" }, { @@ -236,6 +667,24 @@ "internalType": "string", "name": "paranetDescription", "type": "string" + }, + { + "indexed": false, + "internalType": "enum ParanetStructs.NodesAccessPolicy", + "name": "nodesAccessPolicy", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ParanetStructs.MinersAccessPolicy", + "name": "minersAccessPolicy", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "name": "knowledgeAssetsAccessPolicy", + "type": "uint8" } ], "name": "ParanetRegistered", @@ -346,6 +795,52 @@ "name": "ParanetServiceRegistered", "type": "event" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "minerAddresses", + "type": "address[]" + } + ], + "name": "addParanetCuratedMiners", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "internalType": "uint72[]", + "name": "identityIds", + "type": "uint72[]" + } + ], + "name": "addParanetCuratedNodes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -381,6 +876,52 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "minerAddress", + "type": "address" + } + ], + "name": "approveCuratedMiner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "approveCuratedNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "contentAsset", @@ -433,6 +974,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "identityStorage", + "outputs": [ + { + "internalType": "contract IdentityStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "initialize", @@ -604,6 +1158,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "profileStorage", + "outputs": [ + { + "internalType": "contract ProfileStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -627,12 +1194,12 @@ "type": "string" }, { - "internalType": "ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetStructs.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetStructs.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" } @@ -687,6 +1254,134 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "minerAddress", + "type": "address" + } + ], + "name": "rejectCuratedMiner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "rejectCuratedNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "minerAddresses", + "type": "address[]" + } + ], + "name": "removeParanetCuratedMiners", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "internalType": "uint72[]", + "name": "identityIds", + "type": "uint72[]" + } + ], + "name": "removeParanetCuratedNodes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + } + ], + "name": "requestParanetCuratedMinerAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKAStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + } + ], + "name": "requestParanetCuratedNodeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "serviceAgreementStorageProxy", diff --git a/dkg/data/interfaces/ParanetsRegistry.json b/dkg/data/interfaces/ParanetsRegistry.json index bd66bd2..4810d44 100644 --- a/dkg/data/interfaces/ParanetsRegistry.json +++ b/dkg/data/interfaces/ParanetsRegistry.json @@ -28,6 +28,29 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes", + "name": "nodeId", + "type": "bytes" + } + ], + "name": "addCuratedNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -64,6 +87,52 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "addKnowledgeMinerAccessRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "addNodeJoinRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -145,6 +214,56 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getCuratedNodes", + "outputs": [ + { + "components": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes", + "name": "nodeId", + "type": "bytes" + } + ], + "internalType": "struct ParanetStructs.Node[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getCuratedNodesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -196,12 +315,359 @@ "type": "bytes32" } ], - "name": "getKnowledgeAssets", + "name": "getKnowledgeAssets", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getKnowledgeAssetsAccessPolicy", + "outputs": [ + { + "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getKnowledgeAssetsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "knowledgeAssetId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "getKnowledgeAssetsStartingFromKnowledgeAssetId", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "getKnowledgeAssetsWithPagination", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getKnowledgeMinerAccessRequest", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "createdAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "internalType": "struct ParanetStructs.ParanetKnowledgeMinerAccessRequest", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + } + ], + "name": "getKnowledgeMinerAccessRequests", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "createdAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "internalType": "struct ParanetStructs.ParanetKnowledgeMinerAccessRequest[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + } + ], + "name": "getKnowledgeMinerAccessRequestsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getKnowledgeMiners", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getKnowledgeMinersCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + } + ], + "name": "getLatestKnowledgeMinerAccessRequest", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "createdAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "internalType": "struct ParanetStructs.ParanetKnowledgeMinerAccessRequest", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "getLatestNodeJoinRequest", "outputs": [ { - "internalType": "bytes32[]", + "components": [ + { + "internalType": "uint256", + "name": "createdAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "internalType": "struct ParanetStructs.ParanetNodeJoinRequest", "name": "", - "type": "bytes32[]" + "type": "tuple" } ], "stateMutability": "view", @@ -215,12 +681,12 @@ "type": "bytes32" } ], - "name": "getKnowledgeAssetsCount", + "name": "getMinersAccessPolicy", "outputs": [ { - "internalType": "uint256", + "internalType": "enum ParanetStructs.MinersAccessPolicy", "name": "", - "type": "uint256" + "type": "uint8" } ], "stateMutability": "view", @@ -232,24 +698,14 @@ "internalType": "bytes32", "name": "paranetId", "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "knowledgeAssetId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "limit", - "type": "uint256" } ], - "name": "getKnowledgeAssetsStartingFromKnowledgeAssetId", + "name": "getName", "outputs": [ { - "internalType": "bytes32[]", + "internalType": "string", "name": "", - "type": "bytes32[]" + "type": "string" } ], "stateMutability": "view", @@ -263,22 +719,44 @@ "type": "bytes32" }, { - "internalType": "uint256", - "name": "offset", - "type": "uint256" + "internalType": "uint72", + "name": "identityId", + "type": "uint72" }, { "internalType": "uint256", - "name": "limit", + "name": "index", "type": "uint256" } ], - "name": "getKnowledgeAssetsWithPagination", + "name": "getNodeJoinRequest", "outputs": [ { - "internalType": "bytes32[]", + "components": [ + { + "internalType": "uint256", + "name": "createdAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "internalType": "struct ParanetStructs.ParanetNodeJoinRequest", "name": "", - "type": "bytes32[]" + "type": "tuple" } ], "stateMutability": "view", @@ -290,14 +768,41 @@ "internalType": "bytes32", "name": "paranetId", "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "getKnowledgeMiners", + "name": "getNodeJoinRequests", "outputs": [ { - "internalType": "address[]", + "components": [ + { + "internalType": "uint256", + "name": "createdAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "internalType": "struct ParanetStructs.ParanetNodeJoinRequest[]", "name": "", - "type": "address[]" + "type": "tuple[]" } ], "stateMutability": "view", @@ -309,9 +814,14 @@ "internalType": "bytes32", "name": "paranetId", "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "getKnowledgeMinersCount", + "name": "getNodeJoinRequestsCount", "outputs": [ { "internalType": "uint256", @@ -330,12 +840,12 @@ "type": "bytes32" } ], - "name": "getName", + "name": "getNodesAccessPolicy", "outputs": [ { - "internalType": "string", + "internalType": "enum ParanetStructs.NodesAccessPolicy", "name": "", - "type": "string" + "type": "uint8" } ], "stateMutability": "view", @@ -397,6 +907,21 @@ "name": "description", "type": "string" }, + { + "internalType": "enum ParanetStructs.NodesAccessPolicy", + "name": "nodesAccessPolicy", + "type": "uint8" + }, + { + "internalType": "enum ParanetStructs.MinersAccessPolicy", + "name": "minersAccessPolicy", + "type": "uint8" + }, + { + "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "name": "knowledgeAssetsAccessPolicy", + "type": "uint8" + }, { "internalType": "uint96", "name": "cumulativeKnowledgeValue", @@ -510,6 +1035,30 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "isCuratedNode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -635,6 +1184,21 @@ "internalType": "string", "name": "paranetDescription", "type": "string" + }, + { + "internalType": "enum ParanetStructs.NodesAccessPolicy", + "name": "nodesAccessPolicy", + "type": "uint8" + }, + { + "internalType": "enum ParanetStructs.MinersAccessPolicy", + "name": "minersAccessPolicy", + "type": "uint8" + }, + { + "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "name": "knowledgeAssetsAccessPolicy", + "type": "uint8" } ], "name": "registerParanet", @@ -648,6 +1212,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "removeCuratedNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -720,6 +1302,52 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "removeKnowledgeMinerAccessRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "removeNodeJoinRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -797,6 +1425,42 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "name": "knowledgeAssetsAccessPolicy", + "type": "uint8" + } + ], + "name": "setKnowledgeAssetsAccessPolicy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "enum ParanetStructs.MinersAccessPolicy", + "name": "minersAccessPolicy", + "type": "uint8" + } + ], + "name": "setMinersAccessPolicy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -815,6 +1479,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "enum ParanetStructs.NodesAccessPolicy", + "name": "nodesAccessPolicy", + "type": "uint8" + } + ], + "name": "setNodesAccessPolicy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -856,6 +1538,62 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "updateKnowledgeMinerAccessRequestStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "enum ParanetStructs.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "updateNodeJoinRequestStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "version", diff --git a/dkg/paranet.py b/dkg/paranet.py index bce0fb6..75ea421 100644 --- a/dkg/paranet.py +++ b/dkg/paranet.py @@ -218,6 +218,24 @@ def reject_curated_node(self, ual: UAL, identity_id: int) -> dict[str, str | Hex "operation": "Approve node's curated paranet access request" } + _get_curated_nodes = Method(BlockchainRequest.get_curated_nodes) + + def get_curated_nodes(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + paranet_id = Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + + return self._get_curated_nodes(paranet_id) + _add_paranet_curated_miners = Method(BlockchainRequest.add_paranet_curated_miners) def add_curated_miners( @@ -350,6 +368,24 @@ def reject_curated_miner(self, ual: UAL, miner_address: Address) -> dict[str, st ), "operation": "Reject miner's curated paranet access request" } + + _get_knowledge_miners = Method(BlockchainRequest.get_knowledge_miners) + + def get_knowledge_miners(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + paranet_id = Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + + return self._get_knowledge_miners(paranet_id) _deploy_neuro_incentives_pool = Method( BlockchainRequest.deploy_neuro_incentives_pool diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index c5751c5..9460f43 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -211,6 +211,12 @@ class BlockchainRequest: }, ) + get_curated_nodes = ContractCall( + contract="ParanetsRegistry", + function="getCuratedNodes", + args={ "paranetId": HexStr }, + ) + add_paranet_curated_miners = ContractTransaction( contract="Paranet", function="addParanetCuratedMiners", @@ -260,6 +266,12 @@ class BlockchainRequest: }, ) + get_knowledge_miners = ContractCall( + contract="ParanetsRegistry", + function="getKnowledgeMiners", + args={ "paranetId": HexStr }, + ) + add_paranet_services = ContractTransaction( contract="Paranet", function="addParanetServices", diff --git a/examples/curated_paranets_demo.py b/examples/curated_paranets_demo.py new file mode 100644 index 0000000..0aba5f5 --- /dev/null +++ b/examples/curated_paranets_demo.py @@ -0,0 +1,319 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import json +import time + +from hexbytes import HexBytes + +from dkg import DKG +from dkg.providers import BlockchainProvider, NodeHTTPProvider + +node_provider = NodeHTTPProvider("http://localhost:8900") +blockchain_provider = BlockchainProvider( + "development", + "hardhat2:31337", + private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", +) + +dkg = DKG(node_provider, blockchain_provider) + +class NODES_ACCESS_POLICY: + OPEN: int = 0 + CURATED: int = 1 + +class MINERS_ACCESS_POLICY: + OPEN: int = 0 + CURATED: int = 1 + + +def divider(): + print("==================================================") + print("==================================================") + print("==================================================") + + +def print_json(json_dict: dict): + def convert_hexbytes(data): + if isinstance(data, dict): + return {k: convert_hexbytes(v) for k, v in data.items()} + elif isinstance(data, list): + return [convert_hexbytes(i) for i in data] + elif isinstance(data, HexBytes): + return data.hex() + else: + return data + + serializable_dict = convert_hexbytes(json_dict) + print(json.dumps(serializable_dict, indent=4)) + + +divider() + +paranet_data = { + "public": { + "@context": ["http://schema.org"], + "@id": "uuid:1", + "company": "OT", + "city": {"@id": "uuid:belgrade"}, + } +} + +create_paranet_knowledge_asset_result = dkg.asset.create(paranet_data, 1) + +print("======================== PARANET KNOWLEDGE ASSET CREATED") +print_json(create_paranet_knowledge_asset_result) + +divider() + +paranet_ual = create_paranet_knowledge_asset_result["UAL"] +create_paranet_result = dkg.paranet.create( + paranet_ual, + "TestParanet", + "TestParanetDescription", + NODES_ACCESS_POLICY.OPEN, + MINERS_ACCESS_POLICY.OPEN +) + +print("======================== PARANET CREATED") +print_json(create_paranet_result) + +# divider() + +# paranet_service_data = { +# "public": { +# "@context": ["http://schema.org"], +# "@id": "uuid:2", +# "service": "AI Agent Bob", +# "model": {"@id": "uuid:gpt4"}, +# } +# } + +# create_paranet_service_knowledge_asset_result = dkg.asset.create( +# paranet_service_data, 1 +# ) + +# print("======================== PARANET SERVICE KNOWLEDGE ASSET CREATED") +# print_json(create_paranet_service_knowledge_asset_result) + +# divider() + +# paranet_service_ual = create_paranet_service_knowledge_asset_result["UAL"] +# create_paranet_service_result = dkg.paranet.create_service( +# paranet_service_ual, +# "TestParanetService", +# "TestParanetServiceDescription", +# ["0x03C094044301E082468876634F0b209E11d98452"], +# ) + +# print("======================== PARANET SERVICE CREATED") +# print_json(create_paranet_service_result) + +# divider() + +# add_services_result = dkg.paranet.add_services(paranet_ual, [paranet_service_ual]) + +# print("======================== ADDED PARANET SERVICES") +# print_json(add_services_result) + +# divider() + +# incentives_pool_params = dkg.paranet.NeuroWebIncentivesPoolParams( +# neuro_emission_multiplier=1.1, +# operator_percentage=10.5, +# voters_percentage=5.5, +# ) +# deploy_incentives_contract_result = dkg.paranet.deploy_incentives_contract( +# paranet_ual, incentives_pool_params +# ) + +# print("======================== PARANET NEURO INCENTIVES POOL DEPLOYED") +# print_json(deploy_incentives_contract_result) + +# divider() + +# incentives_pool_address = dkg.paranet.get_incentives_pool_address(paranet_ual) + +# print("======================== GOT PARANET NEURO INCENTIVES POOL ADDRESS") +# print(incentives_pool_address) + +# divider() + +# incentives_amount = blockchain_provider.w3.to_wei(100, "ether") +# tx_hash = blockchain_provider.w3.eth.send_transaction( +# { +# "from": blockchain_provider.account.address, +# "to": incentives_pool_address, +# "value": incentives_amount, +# } +# ) + +# print(f"======================== SENT {incentives_amount} TO THE INCENTIVES POOL") + +# divider() + +# is_knowledge_miner = dkg.paranet.is_knowledge_miner(paranet_ual) +# is_operator = dkg.paranet.is_operator(paranet_ual) +# is_voter = dkg.paranet.is_voter(paranet_ual) + +# print(f"Is Knowledge Miner? {str(is_knowledge_miner)}") +# print(f"Is Operator? {str(is_operator)}") +# print(f"Is Voter? {str(is_voter)}") + +# divider() + + +# def print_reward_stats(is_voter: bool = False): +# knowledge_miner_reward = dkg.paranet.calculate_claimable_miner_reward_amount( +# paranet_ual +# ) +# operator_reward = dkg.paranet.calculate_claimable_operator_reward_amount( +# paranet_ual +# ) + +# print( +# f"Claimable Knowledge Miner Reward for the Current Wallet: {knowledge_miner_reward}" +# ) +# print( +# f"Claimable Paranet Operator Reward for the Current Wallet: {operator_reward}" +# ) +# if is_voter: +# voter_rewards = dkg.paranet.calculate_claimable_voter_reward_amount(paranet_ual) +# print( +# f"Claimable Proposal Voter Reward for the Current Wallet: {voter_rewards}" +# ) + +# divider() + +# all_knowledge_miners_reward = ( +# dkg.paranet.calculate_all_claimable_miner_rewards_amount(paranet_ual) +# ) +# all_voters_reward = dkg.paranet.calculate_all_claimable_voters_reward_amount( +# paranet_ual +# ) + +# print(f"Claimable All Knowledge Miners Reward: {all_knowledge_miners_reward}") +# print(f"Claimable Paranet Operator Reward: {operator_reward}") +# print(f"Claimable All Proposal Voters Reward: {all_voters_reward}") + + +# print_reward_stats(is_voter) + +# divider() + +# ka1 = { +# "public": { +# "@context": ["http://schema.org"], +# "@id": "uuid:3", +# "company": "KA1-Company", +# "user": {"@id": "uuid:user:1"}, +# "city": {"@id": "uuid:belgrade"}, +# } +# } + +# create_submit_ka1_result = dkg.asset.create( +# ka1, +# 1, +# 100000000000000000000, +# paranet_ual=paranet_ual, +# ) + +# print( +# "======================== KNOWLEDGE ASSET #1 CREATED AND SUBMITTED TO THE PARANET" +# ) +# print_json(create_submit_ka1_result) + +# divider() + +# ka2 = { +# "public": { +# "@context": ["http://schema.org"], +# "@id": "uuid:4", +# "company": "KA2-Company", +# "user": {"@id": "uuid:user:2"}, +# "city": {"@id": "uuid:madrid"}, +# } +# } + +# create_ka2_result = dkg.asset.create(ka2, 1, 20000000000000000000) + +# print("======================== KNOWLEDGE ASSET #2 CREATED") +# print_json(create_ka2_result) + +# ka2_ual = create_ka2_result["UAL"] +# submit_ka2_result = dkg.asset.submit_to_paranet(ka2_ual, paranet_ual) + +# print("======================== KNOWLEDGE ASSET #2 SUBMITTED TO THE PARANET") +# print_json(submit_ka2_result) + +# # divider() + +# # federated_query = """ +# # PREFIX schema: +# # SELECT DISTINCT ?s ?city1 ?user1 ?s2 ?city2 ?user2 ?company1 +# # WHERE {{ +# # ?s schema:city ?city1 . +# # ?s schema:company ?company1 . +# # ?s schema:user ?user1; + +# # SERVICE <{ual}> {{ +# # ?s2 schema:city ?city2 . +# # ?s2 schema:user ?user2; +# # }} + +# # filter(contains(str(?city2), "belgrade")) +# # }} +# # """ +# # query_result = dkg.graph.query( +# # federated_query.format(ual=ka2_ual), +# # paranet_ual, +# # ) + +# # print("======================== GOT FEDERATED QUERY RESULT") +# # print(query_result) + +# divider() + +# is_knowledge_miner = dkg.paranet.is_knowledge_miner(paranet_ual) +# is_operator = dkg.paranet.is_operator(paranet_ual) +# is_voter = dkg.paranet.is_voter(paranet_ual) + +# print(f"Is Knowledge Miner? {str(is_knowledge_miner)}") +# print(f"Is Operator? {str(is_operator)}") +# print(f"Is Voter? {str(is_voter)}") + +# divider() + +# print_reward_stats(is_voter) + +# divider() + +# claim_miner_reward_result = dkg.paranet.claim_miner_reward(paranet_ual) + +# print("======================== KNOWLEDGE MINER REWARD CLAIMED") +# print_json(claim_miner_reward_result) + +# divider() + +# claim_operator_reward_result = dkg.paranet.claim_operator_reward(paranet_ual) + +# print("======================== PARANET OPERATOR REWARD CLAIMED") +# print(claim_operator_reward_result) + +# divider() + +# print_reward_stats() From 92df516ef3d777edac402a665d0dfa1e0ab902fc Mon Sep 17 00:00:00 2001 From: Zvonimir Sculac Date: Thu, 10 Oct 2024 16:44:35 +0200 Subject: [PATCH 008/146] Add curated paranet demo --- dkg/paranet.py | 36 ++-- examples/curated_paranets_demo.py | 319 +++++++++++------------------- 2 files changed, 136 insertions(+), 219 deletions(-) diff --git a/dkg/paranet.py b/dkg/paranet.py index 75ea421..74c007c 100644 --- a/dkg/paranet.py +++ b/dkg/paranet.py @@ -227,14 +227,27 @@ def get_curated_nodes(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: parsed_ual["token_id"], ) - paranet_id = Web3.to_hex( - Web3.solidity_keccak( - ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], - ) - ), + paranet_id = Web3.solidity_keccak( + ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id] + ) - return self._get_curated_nodes(paranet_id) + curated_nodes = self._get_curated_nodes(paranet_id) + + # curated_nodes is a list of ABIDecodedNamedTuple type so it needs to be converted to a dictionary + converted_results = [] + for curated_node in curated_nodes: + curated_node_dict = {} + for i, v in enumerate(curated_node): + if isinstance(v, bytes): + v = Web3.to_hex(v) + curated_node_dict[str(i)] = v + for k, v in curated_node._asdict().items(): + if isinstance(v, bytes): + v = Web3.to_hex(v) + curated_node_dict[k] = v + converted_results.append(curated_node_dict) + + return converted_results _add_paranet_curated_miners = Method(BlockchainRequest.add_paranet_curated_miners) @@ -378,12 +391,9 @@ def get_knowledge_miners(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: parsed_ual["token_id"], ) - paranet_id = Web3.to_hex( - Web3.solidity_keccak( - ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], - ) - ), + paranet_id = Web3.solidity_keccak( + ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id] + ) return self._get_knowledge_miners(paranet_id) diff --git a/examples/curated_paranets_demo.py b/examples/curated_paranets_demo.py index 0aba5f5..a8a4ac5 100644 --- a/examples/curated_paranets_demo.py +++ b/examples/curated_paranets_demo.py @@ -16,7 +16,6 @@ # under the License. import json -import time from hexbytes import HexBytes @@ -29,8 +28,36 @@ "hardhat2:31337", private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", ) +blockchain_provider2 = BlockchainProvider( + "development", + "hardhat2:31337", + private_key="0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", +) +blockchain_provider3 = BlockchainProvider( + "development", + "hardhat2:31337", + private_key="0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", +) +blockchain_provider4 = BlockchainProvider( + "development", + "hardhat2:31337", + private_key="0x9904da7fe786e5d1f8629b565b688425d78053d4325e746c5ad8ac4328248037", +) +blockchain_provider5 = BlockchainProvider( + "development", + "hardhat2:31337", + private_key="0xfb07091daf99c1d493820ae8dcbc439b48b13ca844684bb1dcae27c9e680e62b", +) dkg = DKG(node_provider, blockchain_provider) +dkg2 = DKG(node_provider, blockchain_provider2) +dkg3 = DKG(node_provider, blockchain_provider3) +dkg4 = DKG(node_provider, blockchain_provider4) +dkg5 = DKG(node_provider, blockchain_provider5) + +PUBLIC_KEY3 = '0x90F79bf6EB2c4f870365E785982E1f101E93b906' +PUBLIC_KEY4 = '0xe5beaB7853A22f054Ef287EA62aCe7A32528b3eE' +PUBLIC_KEY5 = '0x8A4673B00B04b59CaC44926ABeDa85ed181fA436' class NODES_ACCESS_POLICY: OPEN: int = 0 @@ -85,235 +112,115 @@ def convert_hexbytes(data): paranet_ual, "TestParanet", "TestParanetDescription", - NODES_ACCESS_POLICY.OPEN, - MINERS_ACCESS_POLICY.OPEN + NODES_ACCESS_POLICY.CURATED, + MINERS_ACCESS_POLICY.CURATED ) -print("======================== PARANET CREATED") +print("======================== A CURATED PARANET REGISTERED") print_json(create_paranet_result) -# divider() - -# paranet_service_data = { -# "public": { -# "@context": ["http://schema.org"], -# "@id": "uuid:2", -# "service": "AI Agent Bob", -# "model": {"@id": "uuid:gpt4"}, -# } -# } - -# create_paranet_service_knowledge_asset_result = dkg.asset.create( -# paranet_service_data, 1 -# ) - -# print("======================== PARANET SERVICE KNOWLEDGE ASSET CREATED") -# print_json(create_paranet_service_knowledge_asset_result) - -# divider() - -# paranet_service_ual = create_paranet_service_knowledge_asset_result["UAL"] -# create_paranet_service_result = dkg.paranet.create_service( -# paranet_service_ual, -# "TestParanetService", -# "TestParanetServiceDescription", -# ["0x03C094044301E082468876634F0b209E11d98452"], -# ) - -# print("======================== PARANET SERVICE CREATED") -# print_json(create_paranet_service_result) - -# divider() - -# add_services_result = dkg.paranet.add_services(paranet_ual, [paranet_service_ual]) - -# print("======================== ADDED PARANET SERVICES") -# print_json(add_services_result) - -# divider() - -# incentives_pool_params = dkg.paranet.NeuroWebIncentivesPoolParams( -# neuro_emission_multiplier=1.1, -# operator_percentage=10.5, -# voters_percentage=5.5, -# ) -# deploy_incentives_contract_result = dkg.paranet.deploy_incentives_contract( -# paranet_ual, incentives_pool_params -# ) - -# print("======================== PARANET NEURO INCENTIVES POOL DEPLOYED") -# print_json(deploy_incentives_contract_result) - -# divider() - -# incentives_pool_address = dkg.paranet.get_incentives_pool_address(paranet_ual) - -# print("======================== GOT PARANET NEURO INCENTIVES POOL ADDRESS") -# print(incentives_pool_address) - -# divider() - -# incentives_amount = blockchain_provider.w3.to_wei(100, "ether") -# tx_hash = blockchain_provider.w3.eth.send_transaction( -# { -# "from": blockchain_provider.account.address, -# "to": incentives_pool_address, -# "value": incentives_amount, -# } -# ) - -# print(f"======================== SENT {incentives_amount} TO THE INCENTIVES POOL") - -# divider() - -# is_knowledge_miner = dkg.paranet.is_knowledge_miner(paranet_ual) -# is_operator = dkg.paranet.is_operator(paranet_ual) -# is_voter = dkg.paranet.is_voter(paranet_ual) - -# print(f"Is Knowledge Miner? {str(is_knowledge_miner)}") -# print(f"Is Operator? {str(is_operator)}") -# print(f"Is Voter? {str(is_voter)}") - -# divider() - - -# def print_reward_stats(is_voter: bool = False): -# knowledge_miner_reward = dkg.paranet.calculate_claimable_miner_reward_amount( -# paranet_ual -# ) -# operator_reward = dkg.paranet.calculate_claimable_operator_reward_amount( -# paranet_ual -# ) - -# print( -# f"Claimable Knowledge Miner Reward for the Current Wallet: {knowledge_miner_reward}" -# ) -# print( -# f"Claimable Paranet Operator Reward for the Current Wallet: {operator_reward}" -# ) -# if is_voter: -# voter_rewards = dkg.paranet.calculate_claimable_voter_reward_amount(paranet_ual) -# print( -# f"Claimable Proposal Voter Reward for the Current Wallet: {voter_rewards}" -# ) +divider() -# divider() +dkg.paranet.add_curated_nodes(paranet_ual, [1, 2, 3]) +curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) +print("======================== ADDED NODES TO A CURATED PARANET") +print_json(curated_nodes) -# all_knowledge_miners_reward = ( -# dkg.paranet.calculate_all_claimable_miner_rewards_amount(paranet_ual) -# ) -# all_voters_reward = dkg.paranet.calculate_all_claimable_voters_reward_amount( -# paranet_ual -# ) +divider() -# print(f"Claimable All Knowledge Miners Reward: {all_knowledge_miners_reward}") -# print(f"Claimable Paranet Operator Reward: {operator_reward}") -# print(f"Claimable All Proposal Voters Reward: {all_voters_reward}") +dkg.paranet.remove_curated_nodes(paranet_ual, [2, 3]) +curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) +print("======================== REMOVED NODES FROM A CURATED PARANET") +print_json({ + "paranetUAL": paranet_ual, + "curatedNodes": curated_nodes +}) +divider() -# print_reward_stats(is_voter) +# dkg2.paranet.request_curated_node_access(paranet_ual) +# dkg.paranet.reject_curated_node(paranet_ual, 2) +# print("======================== REJECT A NODE'S ACCESS REQUEST TO A CURATED PARANET") +# curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) +# print_json({ +# "paranetUAL": paranet_ual, +# "curatedNodes": curated_nodes +# }) # divider() -# ka1 = { -# "public": { -# "@context": ["http://schema.org"], -# "@id": "uuid:3", -# "company": "KA1-Company", -# "user": {"@id": "uuid:user:1"}, -# "city": {"@id": "uuid:belgrade"}, -# } -# } - -# create_submit_ka1_result = dkg.asset.create( -# ka1, -# 1, -# 100000000000000000000, -# paranet_ual=paranet_ual, -# ) - -# print( -# "======================== KNOWLEDGE ASSET #1 CREATED AND SUBMITTED TO THE PARANET" -# ) -# print_json(create_submit_ka1_result) +# dkg2.paranet.request_curated_node_access(paranet_ual) +# dkg.paranet.approve_curated_node(paranet_ual, 2) +# print("======================== APPROVE A NODE'S ACCESS REQUEST TO A CURATED PARANET") +# curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) +# print_json({ +# "paranetUAL": paranet_ual, +# "curatedNodes": curated_nodes +# }) # divider() -# ka2 = { -# "public": { -# "@context": ["http://schema.org"], -# "@id": "uuid:4", -# "company": "KA2-Company", -# "user": {"@id": "uuid:user:2"}, -# "city": {"@id": "uuid:madrid"}, -# } -# } - -# create_ka2_result = dkg.asset.create(ka2, 1, 20000000000000000000) - -# print("======================== KNOWLEDGE ASSET #2 CREATED") -# print_json(create_ka2_result) - -# ka2_ual = create_ka2_result["UAL"] -# submit_ka2_result = dkg.asset.submit_to_paranet(ka2_ual, paranet_ual) - -# print("======================== KNOWLEDGE ASSET #2 SUBMITTED TO THE PARANET") -# print_json(submit_ka2_result) - -# # divider() - -# # federated_query = """ -# # PREFIX schema: -# # SELECT DISTINCT ?s ?city1 ?user1 ?s2 ?city2 ?user2 ?company1 -# # WHERE {{ -# # ?s schema:city ?city1 . -# # ?s schema:company ?company1 . -# # ?s schema:user ?user1; - -# # SERVICE <{ual}> {{ -# # ?s2 schema:city ?city2 . -# # ?s2 schema:user ?user2; -# # }} - -# # filter(contains(str(?city2), "belgrade")) -# # }} -# # """ -# # query_result = dkg.graph.query( -# # federated_query.format(ual=ka2_ual), -# # paranet_ual, -# # ) - -# # print("======================== GOT FEDERATED QUERY RESULT") -# # print(query_result) - -# divider() +dkg.paranet.add_curated_miners(paranet_ual, [PUBLIC_KEY3, PUBLIC_KEY4, PUBLIC_KEY5]) +knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) +print("======================== ADDED KNOWLEDGE MINERS TO A CURATED PARANET") +print_json(knowledge_miners) -# is_knowledge_miner = dkg.paranet.is_knowledge_miner(paranet_ual) -# is_operator = dkg.paranet.is_operator(paranet_ual) -# is_voter = dkg.paranet.is_voter(paranet_ual) +divider() -# print(f"Is Knowledge Miner? {str(is_knowledge_miner)}") -# print(f"Is Operator? {str(is_operator)}") -# print(f"Is Voter? {str(is_voter)}") +dkg.paranet.remove_curated_miners(paranet_ual, [PUBLIC_KEY4, PUBLIC_KEY5]) +knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) +print("======================== REMOVED KNOWLEDGE MINERS FROM A CURATED PARANET") +print_json({ + "paranetUAL": paranet_ual, + "curatedNodes": knowledge_miners +}) -# divider() +divider() -# print_reward_stats(is_voter) +# dkg4.paranet.request_curated_miner_access(paranet_ual) +# dkg.paranet.reject_curated_miner(paranet_ual, PUBLIC_KEY4) +# print("======================== REJECT A MINER'S ACCESS REQUEST TO A CURATED PARANET") +# knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) +# print_json({ +# "paranetUAL": paranet_ual, +# "curatedNodes": knowledge_miners +# }) # divider() -# claim_miner_reward_result = dkg.paranet.claim_miner_reward(paranet_ual) - -# print("======================== KNOWLEDGE MINER REWARD CLAIMED") -# print_json(claim_miner_reward_result) +# dkg4.paranet.request_curated_miner_access(paranet_ual) +# dkg.paranet.approve_curated_miner(paranet_ual, PUBLIC_KEY4) +# print("======================== APPROVE A MINER'S ACCESS REQUEST TO A CURATED PARANET") +# knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) +# print_json({ +# "paranetUAL": paranet_ual, +# "curatedNodes": knowledge_miners +# }) # divider() -# claim_operator_reward_result = dkg.paranet.claim_operator_reward(paranet_ual) +create_first_asset_result = dkg3.asset.create(paranet_data, 1) +approved_submit_result = dkg3.asset.submit_to_paranet(create_first_asset_result.get("UAL"), paranet_ual) +print('======================== CREATE A KA AND SUBMIT IT TO A CURATED PARANET - KNOWLEDGE MINER IS APPROVED') +print_json({ + "paranetUAL": paranet_ual, + "assetUAL": create_first_asset_result.get("UAL"), + "submitResult": approved_submit_result +}) -# print("======================== PARANET OPERATOR REWARD CLAIMED") -# print(claim_operator_reward_result) - -# divider() +divider() -# print_reward_stats() +create_second_asset_result = dkg5.asset.create(paranet_data, 1) +not_approved_submit_result = None +try: + not_approved_submit_result = dkg5.asset.submit_to_paranet(create_second_asset_result.get("UAL"), paranet_ual) +except Exception as e: + not_approved_submit_result = e.args[0] +print('======================== CREATE A KA AND SUBMIT IT TO A CURATED PARANET - KNOWLEDGE MINER IS NOT APPROVED') +print_json({ + "paranetUAL": paranet_ual, + "assetUAL": create_second_asset_result.get("UAL"), + "submitResult": not_approved_submit_result +}) + +divider() \ No newline at end of file From e98c0ce974baf256c3e67c6af29585763b50113b Mon Sep 17 00:00:00 2001 From: Zvonimir Sculac Date: Fri, 11 Oct 2024 09:55:44 +0200 Subject: [PATCH 009/146] Add ParanetNodesAccessPolicy and ParanetMinersAccessPolicy enums --- dkg/dataclasses.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dkg/dataclasses.py b/dkg/dataclasses.py index 7b49ee3..f493498 100644 --- a/dkg/dataclasses.py +++ b/dkg/dataclasses.py @@ -58,6 +58,14 @@ class KnowledgeAssetContentVisibility(AutoStrEnumUpperCase): class ParanetIncentivizationType(AutoStrEnumCapitalize): NEUROWEB = auto() +class ParanetNodesAccessPolicy(Enum): + OPEN = 0 + CURATED = 1 + +class ParanetMinersAccessPolicy(Enum): + OPEN = 0 + CURATED = 1 + @dataclass class BaseIncentivesPoolParams: From 0296fe0eebe5058f5d731440057f123f8f209b21 Mon Sep 17 00:00:00 2001 From: Zvonimir Sculac Date: Fri, 11 Oct 2024 09:56:13 +0200 Subject: [PATCH 010/146] Improve variable naming --- dkg/paranet.py | 165 +++++++++++++++++++++++++------------------------ 1 file changed, 85 insertions(+), 80 deletions(-) diff --git a/dkg/paranet.py b/dkg/paranet.py index 74c007c..5aa6fdc 100644 --- a/dkg/paranet.py +++ b/dkg/paranet.py @@ -21,7 +21,7 @@ from web3 import Web3 from web3.types import TxReceipt -from dkg.dataclasses import BaseIncentivesPoolParams, ParanetIncentivizationType +from dkg.dataclasses import BaseIncentivesPoolParams, ParanetIncentivizationType, ParanetNodesAccessPolicy, ParanetMinersAccessPolicy from dkg.manager import DefaultRequestManager from dkg.method import Method from dkg.module import Module @@ -57,7 +57,12 @@ def __init__(self, manager: DefaultRequestManager): _register_paranet = Method(BlockchainRequest.register_paranet) def create( - self, ual: UAL, name: str, description: str, nodes_access_policy: int, miners_access_policy: int + self, + ual: UAL, + name: str, + description: str, + nodes_access_policy: ParanetNodesAccessPolicy, + miners_access_policy: ParanetMinersAccessPolicy ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(ual) knowledge_asset_storage, knowledge_asset_token_id = ( @@ -88,26 +93,26 @@ def create( _add_paranet_curated_nodes = Method(BlockchainRequest.add_paranet_curated_nodes) def add_curated_nodes( - self, ual: UAL, identity_ids: list[int] + self, paranet_ual: UAL, identity_ids: list[int] ) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._add_paranet_curated_nodes( - knowledge_asset_storage, - knowledge_asset_token_id, + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id , identity_ids, ) return { - "paranetUAL": ual, + "paranetUAL": paranet_ual, "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id ], ) ), "operation": "Add curated nodes" @@ -116,26 +121,26 @@ def add_curated_nodes( _remove_paranet_curated_nodes = Method(BlockchainRequest.remove_paranet_curated_nodes) def remove_curated_nodes( - self, ual: UAL, identity_ids: list[int] + self, paranet_ual: UAL, identity_ids: list[int] ) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._remove_paranet_curated_nodes( - knowledge_asset_storage, - knowledge_asset_token_id, + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, identity_ids, ) return { - "paranetUAL": ual, + "paranetUAL": paranet_ual, "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), "operation": "Remove curated nodes" @@ -143,24 +148,24 @@ def remove_curated_nodes( _request_paranet_curated_node_access = Method(BlockchainRequest.request_paranet_curated_node_access) - def request_curated_node_access(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + def request_curated_node_access(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._request_paranet_curated_node_access( - knowledge_asset_storage, - knowledge_asset_token_id, + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, ) return { - "paranetUAL": ual, + "paranetUAL": paranet_ual, "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), "operation": "Request to be included in curated paranet nodes" @@ -168,25 +173,25 @@ def request_curated_node_access(self, ual: UAL) -> dict[str, str | HexStr | TxRe _approve_curated_node = Method(BlockchainRequest.approve_curated_node) - def approve_curated_node(self, ual: UAL, identity_id: int) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + def approve_curated_node(self, paranet_ual: UAL, identity_id: int) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._approve_curated_node( - knowledge_asset_storage, - knowledge_asset_token_id, + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, identity_id, ) return { - "paranetUAL": ual, + "paranetUAL": paranet_ual, "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), "operation": "Approve node's curated paranet access request" @@ -194,25 +199,25 @@ def approve_curated_node(self, ual: UAL, identity_id: int) -> dict[str, str | He _reject_curated_node = Method(BlockchainRequest.reject_curated_node) - def reject_curated_node(self, ual: UAL, identity_id: int) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + def reject_curated_node(self, paranet_ual: UAL, identity_id: int) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._reject_curated_node( - knowledge_asset_storage, - knowledge_asset_token_id, + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, identity_id, ) return { - "paranetUAL": ual, + "paranetUAL": paranet_ual, "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), "operation": "Approve node's curated paranet access request" @@ -220,15 +225,15 @@ def reject_curated_node(self, ual: UAL, identity_id: int) -> dict[str, str | Hex _get_curated_nodes = Method(BlockchainRequest.get_curated_nodes) - def get_curated_nodes(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + def get_curated_nodes(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) paranet_id = Web3.solidity_keccak( - ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id] + ["address", "uint256"], [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id] ) curated_nodes = self._get_curated_nodes(paranet_id) @@ -252,26 +257,26 @@ def get_curated_nodes(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: _add_paranet_curated_miners = Method(BlockchainRequest.add_paranet_curated_miners) def add_curated_miners( - self, ual: UAL, miner_addresses: list[Address] + self, paranet_ual: UAL, miner_addresses: list[Address] ) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._add_paranet_curated_miners( - knowledge_asset_storage, - knowledge_asset_token_id, + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, miner_addresses, ) return { - "paranetUAL": ual, + "paranetUAL": paranet_ual, "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), "operation": "Add curated miners" @@ -280,26 +285,26 @@ def add_curated_miners( _remove_paranet_curated_miners = Method(BlockchainRequest.remove_paranet_curated_miners) def remove_curated_miners( - self, ual: UAL, miner_addresses: list[Address] + self, paranet_ual: UAL, miner_addresses: list[Address] ) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._remove_paranet_curated_miners( - knowledge_asset_storage, - knowledge_asset_token_id, + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, miner_addresses, ) return { - "paranetUAL": ual, + "paranetUAL": paranet_ual, "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), "operation": "Remove curated miners" @@ -307,24 +312,24 @@ def remove_curated_miners( _request_paranet_curated_miner_access = Method(BlockchainRequest.request_paranet_curated_miner_access) - def request_curated_miner_access(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + def request_curated_miner_access(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._request_paranet_curated_miner_access( - knowledge_asset_storage, - knowledge_asset_token_id, + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, ) return { - "paranetUAL": ual, + "paranetUAL": paranet_ual, "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), "operation": "Request to be included in curated paranet miners" @@ -332,25 +337,25 @@ def request_curated_miner_access(self, ual: UAL) -> dict[str, str | HexStr | TxR _approve_curated_miner = Method(BlockchainRequest.approve_curated_miner) - def approve_curated_miner(self, ual: UAL, miner_address: Address) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + def approve_curated_miner(self, paranet_ual: UAL, miner_address: Address) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._approve_curated_miner( - knowledge_asset_storage, - knowledge_asset_token_id, + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, miner_address, ) return { - "paranetUAL": ual, + "paranetUAL": paranet_ual, "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), "operation": "Approve miner's curated paranet access request" @@ -358,25 +363,25 @@ def approve_curated_miner(self, ual: UAL, miner_address: Address) -> dict[str, s _reject_curated_miner = Method(BlockchainRequest.reject_curated_miner) - def reject_curated_miner(self, ual: UAL, miner_address: Address) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + def reject_curated_miner(self, paranet_ual: UAL, miner_address: Address) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._reject_curated_miner( - knowledge_asset_storage, - knowledge_asset_token_id, + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, miner_address, ) return { - "paranetUAL": ual, + "paranetUAL": paranet_ual, "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), "operation": "Reject miner's curated paranet access request" @@ -384,15 +389,15 @@ def reject_curated_miner(self, ual: UAL, miner_address: Address) -> dict[str, st _get_knowledge_miners = Method(BlockchainRequest.get_knowledge_miners) - def get_knowledge_miners(self, ual: UAL) -> dict[str, str | HexStr | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( + def get_knowledge_miners(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + parsed_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) paranet_id = Web3.solidity_keccak( - ["address", "uint256"], [knowledge_asset_storage, knowledge_asset_token_id] + ["address", "uint256"], [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id] ) return self._get_knowledge_miners(paranet_id) From d060ac98c4e04440ee9ff19dc808ee6ce77b5cf3 Mon Sep 17 00:00:00 2001 From: Zvonimir Sculac Date: Mon, 14 Oct 2024 11:52:47 +0200 Subject: [PATCH 011/146] Add variables to make demo clearer --- examples/curated_paranets_demo.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/curated_paranets_demo.py b/examples/curated_paranets_demo.py index a8a4ac5..70141ef 100644 --- a/examples/curated_paranets_demo.py +++ b/examples/curated_paranets_demo.py @@ -121,14 +121,16 @@ def convert_hexbytes(data): divider() -dkg.paranet.add_curated_nodes(paranet_ual, [1, 2, 3]) +identity_ids = [1, 2, 3] +dkg.paranet.add_curated_nodes(paranet_ual, identity_ids) curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) print("======================== ADDED NODES TO A CURATED PARANET") print_json(curated_nodes) divider() -dkg.paranet.remove_curated_nodes(paranet_ual, [2, 3]) +identity_ids = [2, 3] +dkg.paranet.remove_curated_nodes(paranet_ual, identity_ids) curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) print("======================== REMOVED NODES FROM A CURATED PARANET") print_json({ @@ -160,14 +162,16 @@ def convert_hexbytes(data): # divider() -dkg.paranet.add_curated_miners(paranet_ual, [PUBLIC_KEY3, PUBLIC_KEY4, PUBLIC_KEY5]) +miner_addresses = [PUBLIC_KEY3, PUBLIC_KEY4, PUBLIC_KEY5] +dkg.paranet.add_curated_miners(paranet_ual, miner_addresses) knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) print("======================== ADDED KNOWLEDGE MINERS TO A CURATED PARANET") print_json(knowledge_miners) divider() -dkg.paranet.remove_curated_miners(paranet_ual, [PUBLIC_KEY4, PUBLIC_KEY5]) +miner_addresses = [PUBLIC_KEY4, PUBLIC_KEY5] +dkg.paranet.remove_curated_miners(paranet_ual, miner_addresses) knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) print("======================== REMOVED KNOWLEDGE MINERS FROM A CURATED PARANET") print_json({ From 986816ba7a6fe4adee4f153ffa8e0ab80d40bbcc Mon Sep 17 00:00:00 2001 From: Zvonimir Sculac Date: Mon, 14 Oct 2024 12:19:11 +0200 Subject: [PATCH 012/146] Remove duplicate constants --- dkg/dataclasses.py | 6 +++--- examples/curated_paranets_demo.py | 14 +++----------- examples/paranets_demo.py | 15 +++------------ 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/dkg/dataclasses.py b/dkg/dataclasses.py index f493498..78606f4 100644 --- a/dkg/dataclasses.py +++ b/dkg/dataclasses.py @@ -16,7 +16,7 @@ # under the License. from dataclasses import dataclass -from enum import auto, Enum +from enum import auto, Enum, IntEnum import pandas as pd @@ -58,11 +58,11 @@ class KnowledgeAssetContentVisibility(AutoStrEnumUpperCase): class ParanetIncentivizationType(AutoStrEnumCapitalize): NEUROWEB = auto() -class ParanetNodesAccessPolicy(Enum): +class ParanetNodesAccessPolicy(IntEnum): OPEN = 0 CURATED = 1 -class ParanetMinersAccessPolicy(Enum): +class ParanetMinersAccessPolicy(IntEnum): OPEN = 0 CURATED = 1 diff --git a/examples/curated_paranets_demo.py b/examples/curated_paranets_demo.py index 70141ef..5a94762 100644 --- a/examples/curated_paranets_demo.py +++ b/examples/curated_paranets_demo.py @@ -21,6 +21,7 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider +from dkg.dataclasses import ParanetNodesAccessPolicy, ParanetMinersAccessPolicy node_provider = NodeHTTPProvider("http://localhost:8900") blockchain_provider = BlockchainProvider( @@ -59,15 +60,6 @@ PUBLIC_KEY4 = '0xe5beaB7853A22f054Ef287EA62aCe7A32528b3eE' PUBLIC_KEY5 = '0x8A4673B00B04b59CaC44926ABeDa85ed181fA436' -class NODES_ACCESS_POLICY: - OPEN: int = 0 - CURATED: int = 1 - -class MINERS_ACCESS_POLICY: - OPEN: int = 0 - CURATED: int = 1 - - def divider(): print("==================================================") print("==================================================") @@ -112,8 +104,8 @@ def convert_hexbytes(data): paranet_ual, "TestParanet", "TestParanetDescription", - NODES_ACCESS_POLICY.CURATED, - MINERS_ACCESS_POLICY.CURATED + ParanetNodesAccessPolicy.CURATED, + ParanetMinersAccessPolicy.CURATED ) print("======================== A CURATED PARANET REGISTERED") diff --git a/examples/paranets_demo.py b/examples/paranets_demo.py index 4931e7e..7586728 100644 --- a/examples/paranets_demo.py +++ b/examples/paranets_demo.py @@ -16,12 +16,12 @@ # under the License. import json -import time from hexbytes import HexBytes from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider +from dkg.dataclasses import ParanetNodesAccessPolicy, ParanetMinersAccessPolicy node_provider = NodeHTTPProvider("http://localhost:8900") blockchain_provider = BlockchainProvider( @@ -32,15 +32,6 @@ dkg = DKG(node_provider, blockchain_provider) -class NODES_ACCESS_POLICY: - OPEN: int = 0 - CURATED: int = 1 - -class MINERS_ACCESS_POLICY: - OPEN: int = 0 - CURATED: int = 1 - - def divider(): print("==================================================") print("==================================================") @@ -85,8 +76,8 @@ def convert_hexbytes(data): paranet_ual, "TestParanet", "TestParanetDescription", - NODES_ACCESS_POLICY.OPEN, - MINERS_ACCESS_POLICY.OPEN + ParanetNodesAccessPolicy.OPEN, + ParanetMinersAccessPolicy.OPEN ) print("======================== PARANET CREATED") From f982b016b1fdd6e6ef1ab2c9bf2fbcfba7c73eb6 Mon Sep 17 00:00:00 2001 From: Zvonimir Sculac Date: Mon, 14 Oct 2024 12:30:29 +0200 Subject: [PATCH 013/146] rename parameters for better clarity --- dkg/paranet.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dkg/paranet.py b/dkg/paranet.py index 5aa6fdc..3ab75ac 100644 --- a/dkg/paranet.py +++ b/dkg/paranet.py @@ -61,8 +61,8 @@ def create( ual: UAL, name: str, description: str, - nodes_access_policy: ParanetNodesAccessPolicy, - miners_access_policy: ParanetMinersAccessPolicy + paranet_nodes_access_policy: ParanetNodesAccessPolicy, + paranet_miners_access_policy: ParanetMinersAccessPolicy ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(ual) knowledge_asset_storage, knowledge_asset_token_id = ( @@ -75,8 +75,8 @@ def create( knowledge_asset_token_id, name, description, - nodes_access_policy, - miners_access_policy + paranet_nodes_access_policy, + paranet_miners_access_policy ) return { From fb85c5cc9847b16d647abc45b09aa410f8bf914a Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Mon, 14 Oct 2024 19:17:38 +0800 Subject: [PATCH 014/146] Code formatting --- dkg/asset.py | 2 +- dkg/constants.py | 10 +-- dkg/dataclasses.py | 2 + dkg/exceptions.py | 1 + dkg/paranet.py | 131 +++++++++++++++++----------- dkg/types/__init__.py | 18 +++- dkg/types/general.py | 23 +++-- dkg/utils/blockchain_request.py | 14 +-- dkg/utils/node_request.py | 2 +- dkg/utils/rdf.py | 4 +- dkg/utils/string_transformations.py | 1 + examples/curated_paranets_demo.py | 98 ++++++++++++--------- 12 files changed, 183 insertions(+), 123 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index bb946b9..8d4784a 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -701,7 +701,7 @@ def extend_storing_period( "UAL": ual, "operation": json.loads(Web3.to_json(receipt)), } - + _get_block = Method(BlockchainRequest.get_block) _get_service_agreement_data = Method(BlockchainRequest.get_service_agreement_data) diff --git a/dkg/constants.py b/dkg/constants.py index e9a48d5..cf50cea 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -21,11 +21,11 @@ BLOCKCHAINS = { "development": { - "hardhat1:31337": { + "hardhat1:31337": { "hub": "0x5FbDB2315678afecb367f032d93F642f64180aa3", "rpc": "http://localhost:8545", }, - "hardhat2:31337": { + "hardhat2:31337": { "hub": "0x5FbDB2315678afecb367f032d93F642f64180aa3", "rpc": "http://localhost:9545", }, @@ -47,11 +47,7 @@ DEFAULT_HASH_FUNCTION_ID = 1 DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS = { - "development": { - "hardhat1:31337": 2, - "hardhat2:31337": 2, - "otp:2043": 2 - }, + "development": {"hardhat1:31337": 2, "hardhat2:31337": 2, "otp:2043": 2}, "devnet": { "otp:2160": 2, "gnosis:10200": 2, diff --git a/dkg/dataclasses.py b/dkg/dataclasses.py index 78606f4..67c9b5f 100644 --- a/dkg/dataclasses.py +++ b/dkg/dataclasses.py @@ -58,10 +58,12 @@ class KnowledgeAssetContentVisibility(AutoStrEnumUpperCase): class ParanetIncentivizationType(AutoStrEnumCapitalize): NEUROWEB = auto() + class ParanetNodesAccessPolicy(IntEnum): OPEN = 0 CURATED = 1 + class ParanetMinersAccessPolicy(IntEnum): OPEN = 0 CURATED = 1 diff --git a/dkg/exceptions.py b/dkg/exceptions.py index 278aa90..617778d 100644 --- a/dkg/exceptions.py +++ b/dkg/exceptions.py @@ -15,6 +15,7 @@ # specific language governing permissions and limitations # under the License. + class DKGException(Exception): """ Exception mixin inherited by all exceptions of dkg.py diff --git a/dkg/paranet.py b/dkg/paranet.py index 3ab75ac..125aca9 100644 --- a/dkg/paranet.py +++ b/dkg/paranet.py @@ -21,7 +21,12 @@ from web3 import Web3 from web3.types import TxReceipt -from dkg.dataclasses import BaseIncentivesPoolParams, ParanetIncentivizationType, ParanetNodesAccessPolicy, ParanetMinersAccessPolicy +from dkg.dataclasses import ( + BaseIncentivesPoolParams, + ParanetIncentivizationType, + ParanetNodesAccessPolicy, + ParanetMinersAccessPolicy, +) from dkg.manager import DefaultRequestManager from dkg.method import Method from dkg.module import Module @@ -62,7 +67,7 @@ def create( name: str, description: str, paranet_nodes_access_policy: ParanetNodesAccessPolicy, - paranet_miners_access_policy: ParanetMinersAccessPolicy + paranet_miners_access_policy: ParanetMinersAccessPolicy, ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(ual) knowledge_asset_storage, knowledge_asset_token_id = ( @@ -76,7 +81,7 @@ def create( name, description, paranet_nodes_access_policy, - paranet_miners_access_policy + paranet_miners_access_policy, ) return { @@ -96,14 +101,14 @@ def add_curated_nodes( self, paranet_ual: UAL, identity_ids: list[int] ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(paranet_ual) - paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], parsed_ual["token_id"], ) self._add_paranet_curated_nodes( paranet_knowledge_asset_storage, - paranet_knowledge_asset_token_id , + paranet_knowledge_asset_token_id, identity_ids, ) @@ -112,13 +117,15 @@ def add_curated_nodes( "paranetId": Web3.to_hex( Web3.solidity_keccak( ["address", "uint256"], - [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id ], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), - "operation": "Add curated nodes" + "operation": "Add curated nodes", } - - _remove_paranet_curated_nodes = Method(BlockchainRequest.remove_paranet_curated_nodes) + + _remove_paranet_curated_nodes = Method( + BlockchainRequest.remove_paranet_curated_nodes + ) def remove_curated_nodes( self, paranet_ual: UAL, identity_ids: list[int] @@ -143,12 +150,16 @@ def remove_curated_nodes( [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), - "operation": "Remove curated nodes" + "operation": "Remove curated nodes", } - - _request_paranet_curated_node_access = Method(BlockchainRequest.request_paranet_curated_node_access) - - def request_curated_node_access(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + + _request_paranet_curated_node_access = Method( + BlockchainRequest.request_paranet_curated_node_access + ) + + def request_curated_node_access( + self, paranet_ual: UAL + ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(paranet_ual) paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], @@ -168,12 +179,14 @@ def request_curated_node_access(self, paranet_ual: UAL) -> dict[str, str | HexSt [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), - "operation": "Request to be included in curated paranet nodes" + "operation": "Request to be included in curated paranet nodes", } - + _approve_curated_node = Method(BlockchainRequest.approve_curated_node) - - def approve_curated_node(self, paranet_ual: UAL, identity_id: int) -> dict[str, str | HexStr | TxReceipt]: + + def approve_curated_node( + self, paranet_ual: UAL, identity_id: int + ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(paranet_ual) paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], @@ -194,12 +207,14 @@ def approve_curated_node(self, paranet_ual: UAL, identity_id: int) -> dict[str, [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), - "operation": "Approve node's curated paranet access request" + "operation": "Approve node's curated paranet access request", } - + _reject_curated_node = Method(BlockchainRequest.reject_curated_node) - - def reject_curated_node(self, paranet_ual: UAL, identity_id: int) -> dict[str, str | HexStr | TxReceipt]: + + def reject_curated_node( + self, paranet_ual: UAL, identity_id: int + ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(paranet_ual) paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], @@ -220,12 +235,14 @@ def reject_curated_node(self, paranet_ual: UAL, identity_id: int) -> dict[str, s [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), - "operation": "Approve node's curated paranet access request" + "operation": "Approve node's curated paranet access request", } - + _get_curated_nodes = Method(BlockchainRequest.get_curated_nodes) - - def get_curated_nodes(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + + def get_curated_nodes( + self, paranet_ual: UAL + ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(paranet_ual) paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], @@ -233,7 +250,8 @@ def get_curated_nodes(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxRece ) paranet_id = Web3.solidity_keccak( - ["address", "uint256"], [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id] + ["address", "uint256"], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) curated_nodes = self._get_curated_nodes(paranet_id) @@ -251,9 +269,9 @@ def get_curated_nodes(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxRece v = Web3.to_hex(v) curated_node_dict[k] = v converted_results.append(curated_node_dict) - + return converted_results - + _add_paranet_curated_miners = Method(BlockchainRequest.add_paranet_curated_miners) def add_curated_miners( @@ -279,10 +297,12 @@ def add_curated_miners( [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), - "operation": "Add curated miners" + "operation": "Add curated miners", } - - _remove_paranet_curated_miners = Method(BlockchainRequest.remove_paranet_curated_miners) + + _remove_paranet_curated_miners = Method( + BlockchainRequest.remove_paranet_curated_miners + ) def remove_curated_miners( self, paranet_ual: UAL, miner_addresses: list[Address] @@ -307,12 +327,16 @@ def remove_curated_miners( [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), - "operation": "Remove curated miners" + "operation": "Remove curated miners", } - - _request_paranet_curated_miner_access = Method(BlockchainRequest.request_paranet_curated_miner_access) - - def request_curated_miner_access(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + + _request_paranet_curated_miner_access = Method( + BlockchainRequest.request_paranet_curated_miner_access + ) + + def request_curated_miner_access( + self, paranet_ual: UAL + ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(paranet_ual) paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], @@ -332,12 +356,14 @@ def request_curated_miner_access(self, paranet_ual: UAL) -> dict[str, str | HexS [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), - "operation": "Request to be included in curated paranet miners" + "operation": "Request to be included in curated paranet miners", } - + _approve_curated_miner = Method(BlockchainRequest.approve_curated_miner) - - def approve_curated_miner(self, paranet_ual: UAL, miner_address: Address) -> dict[str, str | HexStr | TxReceipt]: + + def approve_curated_miner( + self, paranet_ual: UAL, miner_address: Address + ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(paranet_ual) paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], @@ -358,12 +384,14 @@ def approve_curated_miner(self, paranet_ual: UAL, miner_address: Address) -> dic [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), - "operation": "Approve miner's curated paranet access request" + "operation": "Approve miner's curated paranet access request", } - + _reject_curated_miner = Method(BlockchainRequest.reject_curated_miner) - - def reject_curated_miner(self, paranet_ual: UAL, miner_address: Address) -> dict[str, str | HexStr | TxReceipt]: + + def reject_curated_miner( + self, paranet_ual: UAL, miner_address: Address + ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(paranet_ual) paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], @@ -384,12 +412,14 @@ def reject_curated_miner(self, paranet_ual: UAL, miner_address: Address) -> dict [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) ), - "operation": "Reject miner's curated paranet access request" + "operation": "Reject miner's curated paranet access request", } - + _get_knowledge_miners = Method(BlockchainRequest.get_knowledge_miners) - - def get_knowledge_miners(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxReceipt]: + + def get_knowledge_miners( + self, paranet_ual: UAL + ) -> dict[str, str | HexStr | TxReceipt]: parsed_ual = parse_ual(paranet_ual) paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( parsed_ual["contract_address"], @@ -397,7 +427,8 @@ def get_knowledge_miners(self, paranet_ual: UAL) -> dict[str, str | HexStr | TxR ) paranet_id = Web3.solidity_keccak( - ["address", "uint256"], [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id] + ["address", "uint256"], + [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) return self._get_knowledge_miners(paranet_id) diff --git a/dkg/types/__init__.py b/dkg/types/__init__.py index 7cd005d..416728b 100644 --- a/dkg/types/__init__.py +++ b/dkg/types/__init__.py @@ -1,6 +1,18 @@ -from .general import AutoStrEnum, AutoStrEnumCapitalize, AutoStrEnumUpperCase # NOQA: F401 -from .blockchain import (ABI, ABIElement, ABIError, ABIEvent, # NOQA: F401 - ABIFunction, ABIParameter, AgreementData, Environment) +from .general import ( + AutoStrEnum, + AutoStrEnumCapitalize, + AutoStrEnumUpperCase, +) # NOQA: F401 +from .blockchain import ( + ABI, + ABIElement, + ABIError, + ABIEvent, # NOQA: F401 + ABIFunction, + ABIParameter, + AgreementData, + Environment, +) from .dkg_node import UAL # NOQA: F401 from .encoding import BytesLike, DataHexStr, HexStr # NOQA: F401 from .evm import Address, ChecksumAddress, Wei # NOQA: F401 diff --git a/dkg/types/general.py b/dkg/types/general.py index 7867681..6ed0c94 100644 --- a/dkg/types/general.py +++ b/dkg/types/general.py @@ -17,28 +17,35 @@ from enum import Enum + class AutoStrEnum(str, Enum): @staticmethod - def _generate_next_value_(name: str, start: int, count: int, last_values: list) -> str: + def _generate_next_value_( + name: str, start: int, count: int, last_values: list + ) -> str: return name.lower() - + def __str__(self): return str(self.value) - + class AutoStrEnumCapitalize(str, Enum): @staticmethod - def _generate_next_value_(name: str, start: int, count: int, last_values: list) -> str: + def _generate_next_value_( + name: str, start: int, count: int, last_values: list + ) -> str: return name.capitalize() - + def __str__(self): return str(self.value) class AutoStrEnumUpperCase(str, Enum): @staticmethod - def _generate_next_value_(name: str, start: int, count: int, last_values: list) -> str: + def _generate_next_value_( + name: str, start: int, count: int, last_values: list + ) -> str: return name - + def __str__(self): - return str(self.value) \ No newline at end of file + return str(self.value) diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index 9460f43..fe1a4c6 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -70,7 +70,7 @@ class BlockchainRequest: allowance = ContractCall( contract="Token", function="allowance", - args={"owner": Address, "spender": Address} + args={"owner": Address, "spender": Address}, ) increase_allowance = ContractTransaction( contract="Token", @@ -168,7 +168,7 @@ class BlockchainRequest: args={ "paranetKAStorageContract": Address, "paranetKATokenId": int, - "identityIds": list[int] + "identityIds": list[int], }, ) @@ -178,7 +178,7 @@ class BlockchainRequest: args={ "paranetKAStorageContract": Address, "paranetKATokenId": int, - "identityIds": list[int] + "identityIds": list[int], }, ) @@ -214,7 +214,7 @@ class BlockchainRequest: get_curated_nodes = ContractCall( contract="ParanetsRegistry", function="getCuratedNodes", - args={ "paranetId": HexStr }, + args={"paranetId": HexStr}, ) add_paranet_curated_miners = ContractTransaction( @@ -223,7 +223,7 @@ class BlockchainRequest: args={ "paranetKAStorageContract": Address, "paranetKATokenId": int, - "minerAddresses": list[Address] + "minerAddresses": list[Address], }, ) @@ -233,7 +233,7 @@ class BlockchainRequest: args={ "paranetKAStorageContract": Address, "paranetKATokenId": int, - "minerAddresses": list[Address] + "minerAddresses": list[Address], }, ) @@ -269,7 +269,7 @@ class BlockchainRequest: get_knowledge_miners = ContractCall( contract="ParanetsRegistry", function="getKnowledgeMiners", - args={ "paranetId": HexStr }, + args={"paranetId": HexStr}, ) add_paranet_services = ContractTransaction( diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 34c7374..fa5b720 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -21,7 +21,7 @@ from dkg.dataclasses import BidSuggestionRange, HTTPRequestMethod from dkg.exceptions import OperationFailed, OperationNotFinished -from dkg.types import AutoStrEnumUpperCase, UAL, Address, DataHexStr, NQuads +from dkg.types import AutoStrEnumUpperCase, UAL, Address, DataHexStr, NQuads @dataclass diff --git a/dkg/utils/rdf.py b/dkg/utils/rdf.py index e44348f..409a61d 100644 --- a/dkg/utils/rdf.py +++ b/dkg/utils/rdf.py @@ -77,7 +77,5 @@ def format_content( return { "public": public_assertion, - "private": private_assertion - if content.get("private", None) - else {}, + "private": private_assertion if content.get("private", None) else {}, } diff --git a/dkg/utils/string_transformations.py b/dkg/utils/string_transformations.py index fbcc791..a84a635 100644 --- a/dkg/utils/string_transformations.py +++ b/dkg/utils/string_transformations.py @@ -15,6 +15,7 @@ # specific language governing permissions and limitations # under the License. + def snake_to_camel(string: str) -> str: splitted_string = string.split("_") return splitted_string[0] + "".join( diff --git a/examples/curated_paranets_demo.py b/examples/curated_paranets_demo.py index 5a94762..cc3a7af 100644 --- a/examples/curated_paranets_demo.py +++ b/examples/curated_paranets_demo.py @@ -56,9 +56,9 @@ dkg4 = DKG(node_provider, blockchain_provider4) dkg5 = DKG(node_provider, blockchain_provider5) -PUBLIC_KEY3 = '0x90F79bf6EB2c4f870365E785982E1f101E93b906' -PUBLIC_KEY4 = '0xe5beaB7853A22f054Ef287EA62aCe7A32528b3eE' -PUBLIC_KEY5 = '0x8A4673B00B04b59CaC44926ABeDa85ed181fA436' +PUBLIC_KEY3 = "0x90F79bf6EB2c4f870365E785982E1f101E93b906" +PUBLIC_KEY4 = "0xe5beaB7853A22f054Ef287EA62aCe7A32528b3eE" +PUBLIC_KEY5 = "0x8A4673B00B04b59CaC44926ABeDa85ed181fA436" def divider(): print("==================================================") @@ -132,27 +132,27 @@ def convert_hexbytes(data): divider() -# dkg2.paranet.request_curated_node_access(paranet_ual) -# dkg.paranet.reject_curated_node(paranet_ual, 2) -# print("======================== REJECT A NODE'S ACCESS REQUEST TO A CURATED PARANET") -# curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) -# print_json({ -# "paranetUAL": paranet_ual, -# "curatedNodes": curated_nodes -# }) +dkg2.paranet.request_curated_node_access(paranet_ual) +dkg.paranet.reject_curated_node(paranet_ual, 2) +print("======================== REJECT A NODE'S ACCESS REQUEST TO A CURATED PARANET") +curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) +print_json({ + "paranetUAL": paranet_ual, + "curatedNodes": curated_nodes +}) -# divider() +divider() -# dkg2.paranet.request_curated_node_access(paranet_ual) -# dkg.paranet.approve_curated_node(paranet_ual, 2) -# print("======================== APPROVE A NODE'S ACCESS REQUEST TO A CURATED PARANET") -# curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) -# print_json({ -# "paranetUAL": paranet_ual, -# "curatedNodes": curated_nodes -# }) +dkg2.paranet.request_curated_node_access(paranet_ual) +dkg.paranet.approve_curated_node(paranet_ual, 2) +print("======================== APPROVE A NODE'S ACCESS REQUEST TO A CURATED PARANET") +curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) +print_json({ + "paranetUAL": paranet_ual, + "curatedNodes": curated_nodes +}) -# divider() +divider() miner_addresses = [PUBLIC_KEY3, PUBLIC_KEY4, PUBLIC_KEY5] dkg.paranet.add_curated_miners(paranet_ual, miner_addresses) @@ -173,31 +173,37 @@ def convert_hexbytes(data): divider() -# dkg4.paranet.request_curated_miner_access(paranet_ual) -# dkg.paranet.reject_curated_miner(paranet_ual, PUBLIC_KEY4) -# print("======================== REJECT A MINER'S ACCESS REQUEST TO A CURATED PARANET") -# knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) -# print_json({ -# "paranetUAL": paranet_ual, -# "curatedNodes": knowledge_miners -# }) +dkg4.paranet.request_curated_miner_access(paranet_ual) +dkg.paranet.reject_curated_miner(paranet_ual, PUBLIC_KEY4) +print("======================== REJECT A MINER'S ACCESS REQUEST TO A CURATED PARANET") +knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) +print_json({ + "paranetUAL": paranet_ual, + "curatedNodes": knowledge_miners +}) -# divider() +divider() -# dkg4.paranet.request_curated_miner_access(paranet_ual) -# dkg.paranet.approve_curated_miner(paranet_ual, PUBLIC_KEY4) -# print("======================== APPROVE A MINER'S ACCESS REQUEST TO A CURATED PARANET") -# knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) -# print_json({ -# "paranetUAL": paranet_ual, -# "curatedNodes": knowledge_miners -# }) +dkg4.paranet.request_curated_miner_access(paranet_ual) +dkg.paranet.approve_curated_miner(paranet_ual, PUBLIC_KEY4) +print("======================== APPROVE A MINER'S ACCESS REQUEST TO A CURATED PARANET") +knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) +print_json({ + "paranetUAL": paranet_ual, + "curatedNodes": knowledge_miners +}) -# divider() +divider() create_first_asset_result = dkg3.asset.create(paranet_data, 1) -approved_submit_result = dkg3.asset.submit_to_paranet(create_first_asset_result.get("UAL"), paranet_ual) -print('======================== CREATE A KA AND SUBMIT IT TO A CURATED PARANET - KNOWLEDGE MINER IS APPROVED') +approved_submit_result = dkg3.asset.submit_to_paranet( + create_first_asset_result.get("UAL"), + paranet_ual, +) +print( + "======================== CREATE A KA AND SUBMIT IT TO A CURATED PARANET - " + "KNOWLEDGE MINER IS APPROVED" +) print_json({ "paranetUAL": paranet_ual, "assetUAL": create_first_asset_result.get("UAL"), @@ -209,10 +215,16 @@ def convert_hexbytes(data): create_second_asset_result = dkg5.asset.create(paranet_data, 1) not_approved_submit_result = None try: - not_approved_submit_result = dkg5.asset.submit_to_paranet(create_second_asset_result.get("UAL"), paranet_ual) + not_approved_submit_result = dkg5.asset.submit_to_paranet( + create_second_asset_result.get("UAL"), + paranet_ual, + ) except Exception as e: not_approved_submit_result = e.args[0] -print('======================== CREATE A KA AND SUBMIT IT TO A CURATED PARANET - KNOWLEDGE MINER IS NOT APPROVED') +print( + "======================== CREATE A KA AND SUBMIT IT TO A CURATED PARANET - " + "KNOWLEDGE MINER IS NOT APPROVED" +) print_json({ "paranetUAL": paranet_ual, "assetUAL": create_second_asset_result.get("UAL"), From 4dcde7705e203ba5fc0dd6e1017acb7a61a2c3e2 Mon Sep 17 00:00:00 2001 From: Zvonimir Sculac Date: Wed, 16 Oct 2024 10:46:58 +0200 Subject: [PATCH 015/146] Add logic to dynamically fetch identity ids --- dkg/data/interfaces/IdentityStorage.json | 342 +++++++++++++++++++++++ dkg/node.py | 7 + dkg/utils/blockchain_request.py | 7 + examples/curated_paranets_demo.py | 14 +- 4 files changed, 366 insertions(+), 4 deletions(-) create mode 100644 dkg/data/interfaces/IdentityStorage.json diff --git a/dkg/data/interfaces/IdentityStorage.json b/dkg/data/interfaces/IdentityStorage.json new file mode 100644 index 0000000..568fde9 --- /dev/null +++ b/dkg/data/interfaces/IdentityStorage.json @@ -0,0 +1,342 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "purpose", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "keyType", + "type": "uint256" + } + ], + "name": "KeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "purpose", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "keyType", + "type": "uint256" + } + ], + "name": "KeyRemoved", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "_key", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_purpose", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_type", + "type": "uint256" + } + ], + "name": "addKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "deleteIdentity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "generateIdentityId", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operational", + "type": "address" + } + ], + "name": "getIdentityId", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "_key", + "type": "bytes32" + } + ], + "name": "getKey", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "_purpose", + "type": "uint256" + } + ], + "name": "getKeysByPurpose", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "identityIds", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "_key", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_purpose", + "type": "uint256" + } + ], + "name": "keyHasPurpose", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "_key", + "type": "bytes32" + } + ], + "name": "removeKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationalKey", + "type": "bytes32" + } + ], + "name": "removeOperationalKeyIdentityId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationalKey", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "setOperationalKeyIdentityId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/dkg/node.py b/dkg/node.py index 75ec99d..a359fdd 100644 --- a/dkg/node.py +++ b/dkg/node.py @@ -20,6 +20,8 @@ from dkg.method import Method from dkg.module import Module from dkg.utils.node_request import NodeRequest +from dkg.utils.blockchain_request import BlockchainRequest +from dkg.types import Address class Node(Module): @@ -31,3 +33,8 @@ def __init__(self, manager: DefaultRequestManager): @property def info(self) -> NodeResponseDict: return self._info() + + _get_identity_id = Method(BlockchainRequest.get_identity_id) + + def get_identity_id(self, operational: Address) -> int: + return self._get_identity_id(operational) diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index 9460f43..86a1d3a 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -148,6 +148,13 @@ class BlockchainRequest: args={"assertionId": bytes | HexStr}, ) + # Identity + get_identity_id = ContractCall( + contract="IdentityStorage", + function="getIdentityId", + args={"operational": Address}, + ) + # Paranets register_paranet = ContractTransaction( contract="Paranet", diff --git a/examples/curated_paranets_demo.py b/examples/curated_paranets_demo.py index 5a94762..800ad1c 100644 --- a/examples/curated_paranets_demo.py +++ b/examples/curated_paranets_demo.py @@ -56,10 +56,16 @@ dkg4 = DKG(node_provider, blockchain_provider4) dkg5 = DKG(node_provider, blockchain_provider5) +PUBLIC_KEY1 = '0x70997970C51812dc3A010C7d01b50e0d17dc79C8' +PUBLIC_KEY2 = '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC' PUBLIC_KEY3 = '0x90F79bf6EB2c4f870365E785982E1f101E93b906' PUBLIC_KEY4 = '0xe5beaB7853A22f054Ef287EA62aCe7A32528b3eE' PUBLIC_KEY5 = '0x8A4673B00B04b59CaC44926ABeDa85ed181fA436' +node1_identity_id = dkg.node.get_identity_id(PUBLIC_KEY1) +node2_identity_id = dkg.node.get_identity_id(PUBLIC_KEY2) +node3_identity_id = dkg.node.get_identity_id(PUBLIC_KEY3) + def divider(): print("==================================================") print("==================================================") @@ -113,7 +119,7 @@ def convert_hexbytes(data): divider() -identity_ids = [1, 2, 3] +identity_ids = [node1_identity_id, node2_identity_id, node3_identity_id] dkg.paranet.add_curated_nodes(paranet_ual, identity_ids) curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) print("======================== ADDED NODES TO A CURATED PARANET") @@ -121,7 +127,7 @@ def convert_hexbytes(data): divider() -identity_ids = [2, 3] +identity_ids = [node2_identity_id, node3_identity_id] dkg.paranet.remove_curated_nodes(paranet_ual, identity_ids) curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) print("======================== REMOVED NODES FROM A CURATED PARANET") @@ -133,7 +139,7 @@ def convert_hexbytes(data): divider() # dkg2.paranet.request_curated_node_access(paranet_ual) -# dkg.paranet.reject_curated_node(paranet_ual, 2) +# dkg.paranet.reject_curated_node(paranet_ual, node2_identity_id) # print("======================== REJECT A NODE'S ACCESS REQUEST TO A CURATED PARANET") # curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) # print_json({ @@ -144,7 +150,7 @@ def convert_hexbytes(data): # divider() # dkg2.paranet.request_curated_node_access(paranet_ual) -# dkg.paranet.approve_curated_node(paranet_ual, 2) +# dkg.paranet.approve_curated_node(paranet_ual, node2_identity_id) # print("======================== APPROVE A NODE'S ACCESS REQUEST TO A CURATED PARANET") # curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) # print_json({ From c6057380259839344fe37f283d9487d3bdafc383 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Wed, 16 Oct 2024 19:13:42 +0800 Subject: [PATCH 016/146] Fixed formatting --- dkg/asset.py | 6 +++--- dkg/node.py | 2 +- dkg/utils/merkle.py | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index ed63414..a9dc6e3 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -360,7 +360,7 @@ def create( } return result - + def mint_ownership_token( self, content: dict[Literal["public", "private"], JSONLD], @@ -469,7 +469,7 @@ def mint_ownership_token( result["operation"] = json.loads(Web3.to_json(receipt)) return result - + def publish( self, ual: UAL, @@ -538,7 +538,7 @@ def publish( } return result - + def local_store( self, ual: UAL, diff --git a/dkg/node.py b/dkg/node.py index a359fdd..c25038f 100644 --- a/dkg/node.py +++ b/dkg/node.py @@ -33,7 +33,7 @@ def __init__(self, manager: DefaultRequestManager): @property def info(self) -> NodeResponseDict: return self._info() - + _get_identity_id = Method(BlockchainRequest.get_identity_id) def get_identity_id(self, operational: Address) -> int: diff --git a/dkg/utils/merkle.py b/dkg/utils/merkle.py index c638ec3..f7a57af 100644 --- a/dkg/utils/merkle.py +++ b/dkg/utils/merkle.py @@ -34,6 +34,7 @@ def solidity_keccak256(data: HexStr) -> HexStr: return bytes_hash.to_0x_hex() + def hash_assertion_with_indexes( leaves: list[str], hash_function: str | Callable[[str], HexStr] = solidity_keccak256, From 0a0f8f52ee01bcc816d28c6ab741f3c9c4cbccd4 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Wed, 16 Oct 2024 20:34:01 +0800 Subject: [PATCH 017/146] Removed mint/local-store/publish --- dkg/asset.py | 248 --------------------------------------------------- 1 file changed, 248 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index a9dc6e3..c2ddc87 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -361,254 +361,6 @@ def create( return result - def mint_ownership_token( - self, - content: dict[Literal["public", "private"], JSONLD], - epochs_number: int, - token_amount: Wei | None = None, - immutable: bool = False, - content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - paranet_ual: UAL | None = None, - ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: - blockchain_id = self.manager.blockchain_provider.blockchain_id - assertions = format_content(content, content_type) - - public_assertion_id = MerkleTree( - hash_assertion_with_indexes(assertions["public"]), - sort_pairs=True, - ).root - public_assertion_metadata = generate_assertion_metadata(assertions["public"]) - - content_asset_storage_address = self._get_asset_storage_address( - "ContentAssetStorage" - ) - - if token_amount is None: - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - epochs_number, - public_assertion_metadata["size"], - content_asset_storage_address, - public_assertion_id, - DEFAULT_HASH_FUNCTION_ID, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] - ) - - current_allowance = self.get_current_allowance() - if is_allowance_increased := current_allowance < token_amount: - self.increase_allowance(token_amount) - - result = {"publicAssertionId": public_assertion_id, "operation": {}} - - try: - if paranet_ual is None: - receipt: TxReceipt = self._create( - { - "assertionId": Web3.to_bytes(hexstr=public_assertion_id), - "size": public_assertion_metadata["size"], - "triplesNumber": public_assertion_metadata["triples_number"], - "chunksNumber": public_assertion_metadata["chunks_number"], - "tokenAmount": token_amount, - "epochsNumber": epochs_number, - "scoreFunctionId": DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ - self.manager.blockchain_provider.environment - ][blockchain_id], - "immutable_": immutable, - } - ) - else: - parsed_paranet_ual = parse_ual(paranet_ual) - paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( - parsed_paranet_ual["contract_address"], - parsed_paranet_ual["token_id"], - ) - - receipt: TxReceipt = self._mint_paranet_knowledge_asset( - paranet_knowledge_asset_storage, - paranet_knowledge_asset_token_id, - { - "assertionId": Web3.to_bytes(hexstr=public_assertion_id), - "size": public_assertion_metadata["size"], - "triplesNumber": public_assertion_metadata["triples_number"], - "chunksNumber": public_assertion_metadata["chunks_number"], - "tokenAmount": token_amount, - "epochsNumber": epochs_number, - "scoreFunctionId": DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ - self.manager.blockchain_provider.environment - ][blockchain_id], - "immutable_": immutable, - }, - ) - - result["paranetId"] = Web3.to_hex( - Web3.solidity_keccak( - ["address", "uint256"], - [ - paranet_knowledge_asset_storage, - paranet_knowledge_asset_token_id, - ], - ) - ) - except ContractLogicError as err: - if is_allowance_increased: - self.decrease_allowance(token_amount) - raise err - - events = self.manager.blockchain_provider.decode_logs_event( - receipt, - "ContentAsset", - "AssetMinted", - ) - token_id = events[0].args["tokenId"] - - result["UAL"] = format_ual( - blockchain_id, content_asset_storage_address, token_id - ) - result["operation"] = json.loads(Web3.to_json(receipt)) - - return result - - def publish( - self, - ual: UAL, - content: dict[Literal["public", "private"], JSONLD], - content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: - blockchain_id = self.manager.blockchain_provider.blockchain_id - assertions = format_content(content, content_type) - - public_assertion_id = MerkleTree( - hash_assertion_with_indexes(assertions["public"]), - sort_pairs=True, - ).root - - content_asset_storage_address = self._get_asset_storage_address( - "ContentAssetStorage" - ) - - result = { - "UAL": ual, - "publicAssertionId": public_assertion_id, - "operation": {}, - } - - token_id = parse_ual(ual)["token_id"] - - assertions_list = [ - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": public_assertion_id, - "assertion": assertions["public"], - "storeType": StoreTypes.TRIPLE, - } - ] - - if content.get("private", None): - assertions_list.append( - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": MerkleTree( - hash_assertion_with_indexes(assertions["private"]), - sort_pairs=True, - ).root, - "assertion": assertions["private"], - "storeType": StoreTypes.TRIPLE, - } - ) - - operation_id = self._publish( - public_assertion_id, - assertions["public"], - blockchain_id, - content_asset_storage_address, - token_id, - DEFAULT_HASH_FUNCTION_ID, - )["operationId"] - operation_result = self.get_operation_result(operation_id, "publish") - - result["operation"] = { - "operationId": operation_id, - "status": operation_result["status"], - } - - return result - - def local_store( - self, - ual: UAL, - content: dict[Literal["public", "private"], JSONLD], - content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - paranet_repository: bool = False, - ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: - blockchain_id = self.manager.blockchain_provider.blockchain_id - assertions = format_content(content, content_type) - - public_assertion_id = MerkleTree( - hash_assertion_with_indexes(assertions["public"]), - sort_pairs=True, - ).root - - content_asset_storage_address = self._get_asset_storage_address( - "ContentAssetStorage" - ) - - result = { - "UAL": ual, - "publicAssertionId": public_assertion_id, - "operation": {}, - } - - token_id = parse_ual(ual)["token_id"] - - assertions_list = [ - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": public_assertion_id, - "assertion": assertions["public"], - "storeType": ( - StoreTypes.TRIPLE_PARANET - if paranet_repository - else StoreTypes.TRIPLE - ), - } - ] - - if content.get("private", None): - assertions_list.append( - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": MerkleTree( - hash_assertion_with_indexes(assertions["private"]), - sort_pairs=True, - ).root, - "assertion": assertions["private"], - "storeType": ( - StoreTypes.TRIPLE_PARANET - if paranet_repository - else StoreTypes.TRIPLE - ), - } - ) - - operation_id = self._local_store(assertions_list)["operationId"] - operation_result = self.get_operation_result(operation_id, "local-store") - - result["operation"] = { - "operationId": operation_id, - "status": operation_result["status"], - } - - return result _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) From 518d18cdc3af6475ea9803b5369f71670b7346ae Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Wed, 16 Oct 2024 21:00:12 +0800 Subject: [PATCH 018/146] Removed tuple decoding for curated nodes list getter --- dkg/paranet.py | 18 +----------------- dkg/utils/node_request.py | 1 - examples/curated_paranets_demo.py | 4 ++++ 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/dkg/paranet.py b/dkg/paranet.py index 2fe7573..c26ea5b 100644 --- a/dkg/paranet.py +++ b/dkg/paranet.py @@ -254,23 +254,7 @@ def get_curated_nodes( [paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id], ) - curated_nodes = self._get_curated_nodes(paranet_id) - - # curated_nodes is a list of ABIDecodedNamedTuple type so it needs to be converted to a dictionary - converted_results = [] - for curated_node in curated_nodes: - curated_node_dict = {} - for i, v in enumerate(curated_node): - if isinstance(v, bytes): - v = Web3.to_hex(v) - curated_node_dict[str(i)] = v - for k, v in curated_node._asdict().items(): - if isinstance(v, bytes): - v = Web3.to_hex(v) - curated_node_dict[k] = v - converted_results.append(curated_node_dict) - - return converted_results + return self._get_curated_nodes(paranet_id) _add_paranet_curated_miners = Method(BlockchainRequest.add_paranet_curated_miners) diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 977dc8e..fa5b720 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -105,7 +105,6 @@ class PublishOperationStatus(Enum): class StoreTypes(AutoStrEnumUpperCase): TRIPLE = auto() - TRIPLE_PARANET = auto() PENDING = auto() diff --git a/examples/curated_paranets_demo.py b/examples/curated_paranets_demo.py index 910dcee..4811876 100644 --- a/examples/curated_paranets_demo.py +++ b/examples/curated_paranets_demo.py @@ -73,6 +73,10 @@ def convert_hexbytes(data): return {k: convert_hexbytes(v) for k, v in data.items()} elif isinstance(data, list): return [convert_hexbytes(i) for i in data] + elif isinstance(data, tuple) and hasattr(data, '_asdict'): + return convert_hexbytes(data._asdict()) + elif isinstance(data, bytes): + return data.decode("utf-8") elif isinstance(data, HexBytes): return data.to_0x_hex() else: From 361d242fb1d15452770a9716bef7a95397adc872 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Fri, 18 Oct 2024 19:58:53 +0800 Subject: [PATCH 019/146] Added local_store for curated paranet KA --- dkg/asset.py | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/dkg/asset.py b/dkg/asset.py index c2ddc87..cc56961 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -360,6 +360,134 @@ def create( } return result + + + def local_store( + self, + content: dict[Literal["public", "private"], JSONLD], + epochs_number: int, + token_amount: Wei | None = None, + immutable: bool = False, + content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + paranet_ual: UAL | None = None, + ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: + blockchain_id = self.manager.blockchain_provider.blockchain_id + assertions = format_content(content, content_type) + + public_assertion_id = MerkleTree( + hash_assertion_with_indexes(assertions["public"]), + sort_pairs=True, + ).root + public_assertion_metadata = generate_assertion_metadata(assertions["public"]) + + content_asset_storage_address = self._get_asset_storage_address( + "ContentAssetStorage" + ) + + if token_amount is None: + token_amount = int( + self._get_bid_suggestion( + blockchain_id, + epochs_number, + public_assertion_metadata["size"], + content_asset_storage_address, + public_assertion_id, + DEFAULT_HASH_FUNCTION_ID, + token_amount or BidSuggestionRange.LOW, + )["bidSuggestion"] + ) + + current_allowance = self.get_current_allowance() + if is_allowance_increased := current_allowance < token_amount: + self.increase_allowance(token_amount) + + result = {"publicAssertionId": public_assertion_id, "operation": {}} + + try: + receipt: TxReceipt = self._create( + { + "assertionId": Web3.to_bytes(hexstr=public_assertion_id), + "size": public_assertion_metadata["size"], + "triplesNumber": public_assertion_metadata["triples_number"], + "chunksNumber": public_assertion_metadata["chunks_number"], + "tokenAmount": token_amount, + "epochsNumber": epochs_number, + "scoreFunctionId": DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ + self.manager.blockchain_provider.environment + ][blockchain_id], + "immutable_": immutable, + } + ) + except ContractLogicError as err: + if is_allowance_increased: + self.decrease_allowance(token_amount) + raise err + + events = self.manager.blockchain_provider.decode_logs_event( + receipt, + "ContentAsset", + "AssetMinted", + ) + token_id = events[0].args["tokenId"] + + result["UAL"] = format_ual( + blockchain_id, content_asset_storage_address, token_id + ) + result["operation"]["mintKnowledgeAsset"] = json.loads(Web3.to_json(receipt)) + + assertions_list = [ + { + "blockchain": blockchain_id, + "contract": content_asset_storage_address, + "tokenId": token_id, + "assertionId": public_assertion_id, + "assertion": assertions["public"], + "storeType": StoreTypes.TRIPLE_PARANET, + "paranetUAL": paranet_ual, + } + ] + + if content.get("private", None): + assertions_list.append( + { + "blockchain": blockchain_id, + "contract": content_asset_storage_address, + "tokenId": token_id, + "assertionId": MerkleTree( + hash_assertion_with_indexes(assertions["private"]), + sort_pairs=True, + ).root, + "assertion": assertions["private"], + "storeType": StoreTypes.TRIPLE_PARANET, + "paranetUAL": paranet_ual, + } + ) + + operation_id = self._local_store(assertions_list)["operationId"] + operation_result = self.get_operation_result(operation_id, "local-store") + + result["operation"]["localStore"] = { + "operationId": operation_id, + "status": operation_result["status"], + } + + if operation_result["status"] == OperationStatus.COMPLETED: + parsed_paranet_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( + parsed_paranet_ual["contract_address"], + parsed_paranet_ual["token_id"], + ) + + receipt: TxReceipt = self._submit_knowledge_asset( + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, + content_asset_storage_address, + token_id, + ) + + result["operation"]["submitToParanet"] = json.loads(Web3.to_json(receipt)) + + return result _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) From 57ac5aa85c52ba1083c8d4e9759d00f3bb6a9ac8 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Wed, 23 Oct 2024 12:57:59 +0200 Subject: [PATCH 020/146] Added missing constant, updated curated paranets demo --- dkg/utils/node_request.py | 1 + examples/curated_paranets_demo.py | 272 +++++++++++++++--------------- pyproject.toml | 2 +- 3 files changed, 135 insertions(+), 140 deletions(-) diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index fa5b720..977dc8e 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -105,6 +105,7 @@ class PublishOperationStatus(Enum): class StoreTypes(AutoStrEnumUpperCase): TRIPLE = auto() + TRIPLE_PARANET = auto() PENDING = auto() diff --git a/examples/curated_paranets_demo.py b/examples/curated_paranets_demo.py index 4811876..600059c 100644 --- a/examples/curated_paranets_demo.py +++ b/examples/curated_paranets_demo.py @@ -97,154 +97,148 @@ def convert_hexbytes(data): } } -create_paranet_knowledge_asset_result = dkg.asset.create(paranet_data, 1) - -print("======================== PARANET KNOWLEDGE ASSET CREATED") -print_json(create_paranet_knowledge_asset_result) - -divider() - -paranet_ual = create_paranet_knowledge_asset_result["UAL"] -create_paranet_result = dkg.paranet.create( - paranet_ual, - "TestParanet", - "TestParanetDescription", - ParanetNodesAccessPolicy.CURATED, - ParanetMinersAccessPolicy.CURATED -) - -print("======================== A CURATED PARANET REGISTERED") -print_json(create_paranet_result) - -divider() - -identity_ids = [node1_identity_id, node2_identity_id, node3_identity_id] -dkg.paranet.add_curated_nodes(paranet_ual, identity_ids) -curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) -print("======================== ADDED NODES TO A CURATED PARANET") -print_json(curated_nodes) - -divider() - -identity_ids = [node2_identity_id, node3_identity_id] -dkg.paranet.remove_curated_nodes(paranet_ual, identity_ids) -curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) -print("======================== REMOVED NODES FROM A CURATED PARANET") -print_json({ - "paranetUAL": paranet_ual, - "curatedNodes": curated_nodes -}) - -divider() - -dkg2.paranet.request_curated_node_access(paranet_ual) -time.sleep(5) -dkg.paranet.reject_curated_node(paranet_ual, node2_identity_id) -print("======================== REJECT A NODE'S ACCESS REQUEST TO A CURATED PARANET") -curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) -print_json({ - "paranetUAL": paranet_ual, - "curatedNodes": curated_nodes -}) - -divider() - -dkg2.paranet.request_curated_node_access(paranet_ual) -time.sleep(5) -dkg.paranet.approve_curated_node(paranet_ual, node2_identity_id) -print("======================== APPROVE A NODE'S ACCESS REQUEST TO A CURATED PARANET") -curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) -print_json({ - "paranetUAL": paranet_ual, - "curatedNodes": curated_nodes -}) - -divider() - -miner_addresses = [ - dkg3.blockchain_provider.account.address, - dkg4.blockchain_provider.account.address, - dkg5.blockchain_provider.account.address, -] -dkg.paranet.add_curated_miners(paranet_ual, miner_addresses) -knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) -print("======================== ADDED KNOWLEDGE MINERS TO A CURATED PARANET") -print_json(knowledge_miners) - -divider() - -miner_addresses = [ - dkg4.blockchain_provider.account.address, - dkg5.blockchain_provider.account.address, -] -dkg.paranet.remove_curated_miners(paranet_ual, miner_addresses) -knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) -print("======================== REMOVED KNOWLEDGE MINERS FROM A CURATED PARANET") -print_json({ - "paranetUAL": paranet_ual, - "curatedNodes": knowledge_miners -}) - -divider() - -dkg4.paranet.request_curated_miner_access(paranet_ual) -time.sleep(5) -dkg.paranet.reject_curated_miner(paranet_ual, dkg4.blockchain_provider.account.address) -print("======================== REJECT A MINER'S ACCESS REQUEST TO A CURATED PARANET") -knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) -print_json({ - "paranetUAL": paranet_ual, - "curatedNodes": knowledge_miners -}) - -divider() - -dkg4.paranet.request_curated_miner_access(paranet_ual) -time.sleep(5) -dkg.paranet.approve_curated_miner(paranet_ual, dkg4.blockchain_provider.account.address) -print("======================== APPROVE A MINER'S ACCESS REQUEST TO A CURATED PARANET") -knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) -print_json({ - "paranetUAL": paranet_ual, - "curatedNodes": knowledge_miners -}) - -divider() - -create_first_asset_result = dkg3.asset.create(paranet_data, 1) -approved_submit_result = dkg3.asset.submit_to_paranet( - create_first_asset_result.get("UAL"), - paranet_ual, +# create_paranet_knowledge_asset_result = dkg.asset.create(paranet_data, 1) + +# print("======================== PARANET KNOWLEDGE ASSET CREATED") +# print_json(create_paranet_knowledge_asset_result) + +# divider() + +# paranet_ual = create_paranet_knowledge_asset_result["UAL"] +# create_paranet_result = dkg.paranet.create( +# paranet_ual, +# "TestParanet", +# "TestParanetDescription", +# ParanetNodesAccessPolicy.CURATED, +# ParanetMinersAccessPolicy.CURATED +# ) + +# print("======================== A CURATED PARANET REGISTERED") +# print_json(create_paranet_result) + +# divider() + +# identity_ids = [node1_identity_id, node2_identity_id, node3_identity_id] +# dkg.paranet.add_curated_nodes(paranet_ual, identity_ids) +# curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) +# print("======================== ADDED NODES TO A CURATED PARANET") +# print_json(curated_nodes) + +# divider() + +# identity_ids = [node2_identity_id, node3_identity_id] +# dkg.paranet.remove_curated_nodes(paranet_ual, identity_ids) +# curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) +# print("======================== REMOVED NODES FROM A CURATED PARANET") +# print_json({ +# "paranetUAL": paranet_ual, +# "curatedNodes": curated_nodes +# }) + +# divider() + +# dkg2.paranet.request_curated_node_access(paranet_ual) +# time.sleep(5) +# dkg.paranet.reject_curated_node(paranet_ual, node2_identity_id) +# print("======================== REJECT A NODE'S ACCESS REQUEST TO A CURATED PARANET") +# curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) +# print_json({ +# "paranetUAL": paranet_ual, +# "curatedNodes": curated_nodes +# }) + +# divider() + +# dkg2.paranet.request_curated_node_access(paranet_ual) +# time.sleep(5) +# dkg.paranet.approve_curated_node(paranet_ual, node2_identity_id) +# print("======================== APPROVE A NODE'S ACCESS REQUEST TO A CURATED PARANET") +# curated_nodes = dkg.paranet.get_curated_nodes(paranet_ual) +# print_json({ +# "paranetUAL": paranet_ual, +# "curatedNodes": curated_nodes +# }) + +# divider() + +# miner_addresses = [ +# dkg3.blockchain_provider.account.address, +# dkg4.blockchain_provider.account.address, +# dkg5.blockchain_provider.account.address, +# ] +# dkg.paranet.add_curated_miners(paranet_ual, miner_addresses) +# knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) +# print("======================== ADDED KNOWLEDGE MINERS TO A CURATED PARANET") +# print_json(knowledge_miners) + +# divider() + +# miner_addresses = [ +# dkg4.blockchain_provider.account.address, +# dkg5.blockchain_provider.account.address, +# ] +# dkg.paranet.remove_curated_miners(paranet_ual, miner_addresses) +# knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) +# print("======================== REMOVED KNOWLEDGE MINERS FROM A CURATED PARANET") +# print_json({ +# "paranetUAL": paranet_ual, +# "curatedNodes": knowledge_miners +# }) + +# divider() + +# dkg4.paranet.request_curated_miner_access(paranet_ual) +# time.sleep(5) +# dkg.paranet.reject_curated_miner(paranet_ual, dkg4.blockchain_provider.account.address) +# print("======================== REJECT A MINER'S ACCESS REQUEST TO A CURATED PARANET") +# knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) +# print_json({ +# "paranetUAL": paranet_ual, +# "curatedNodes": knowledge_miners +# }) + +# divider() + +# dkg4.paranet.request_curated_miner_access(paranet_ual) +# time.sleep(5) +# dkg.paranet.approve_curated_miner(paranet_ual, dkg4.blockchain_provider.account.address) +# print("======================== APPROVE A MINER'S ACCESS REQUEST TO A CURATED PARANET") +# knowledge_miners = dkg.paranet.get_knowledge_miners(paranet_ual) +# print_json({ +# "paranetUAL": paranet_ual, +# "curatedNodes": knowledge_miners +# }) + +# divider() + +paranet_ual = 'did:dkg:hardhat2:31337/0x8aafc28174bb6c3bdc7be92f18c2f134e876c05e/1' + +local_store_first_asset_result = dkg3.asset.local_store( + paranet_data, + 1, + paranet_ual=paranet_ual, ) print( - "======================== CREATE A KA AND SUBMIT IT TO A CURATED PARANET - " - "KNOWLEDGE MINER IS APPROVED" + "======================== MINT A KA, LOCAL STORE AND SUBMIT IT TO A " + "CURATED PARANET - KNOWLEDGE MINER IS APPROVED" ) -print_json({ - "paranetUAL": paranet_ual, - "assetUAL": create_first_asset_result.get("UAL"), - "submitResult": approved_submit_result -}) +print_json(local_store_first_asset_result) divider() -create_second_asset_result = dkg5.asset.create(paranet_data, 1) -not_approved_submit_result = None +local_store_second_asset_result = None try: - not_approved_submit_result = dkg5.asset.submit_to_paranet( - create_second_asset_result.get("UAL"), - paranet_ual, + create_second_asset_result = dkg5.asset.local_store( + paranet_data, + 1, + paranet_ual=paranet_ual, ) -except Exception as e: - not_approved_submit_result = e.args[0] +except Exception as error: + local_store_second_asset_result = error print( - "======================== CREATE A KA AND SUBMIT IT TO A CURATED PARANET - " - "KNOWLEDGE MINER IS NOT APPROVED" + "======================== MINT A KA, LOCAL STORE AND SUBMIT IT TO A " + "CURATED PARANET - KNOWLEDGE MINER IS NOT APPROVED" ) -print_json({ - "paranetUAL": paranet_ual, - "assetUAL": create_second_asset_result.get("UAL"), - "submitResult": not_approved_submit_result -}) +print(local_store_second_asset_result) divider() \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index dfc7dab..03eba3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.0a2" +version = "8.0.0a3" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar "] license = "Apache-2.0" From 4d5837e09f7f69e4ed96831b3e624e5988d5d41f Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 30 Dec 2024 17:31:46 +0100 Subject: [PATCH 021/146] Add V8 query --- dkg/graph.py | 5 +- dkg/providers/node_http.py | 10 +- dkg/utils/node_request.py | 2 +- examples/demo.py | 220 ++++++++++++++++++++++--------------- 4 files changed, 146 insertions(+), 91 deletions(-) diff --git a/dkg/graph.py b/dkg/graph.py index 43cf234..025b0fb 100644 --- a/dkg/graph.py +++ b/dkg/graph.py @@ -37,12 +37,13 @@ def __init__(self, manager: DefaultRequestManager): def query( self, query: str, - repository: str, + repository: str | None = None, + paranet_ual: str | None = None, ) -> NQuads: parsed_query = parseQuery(query) query_type = parsed_query[1].name.replace("Query", "").upper() - operation_id: NodeResponseDict = self._query(query, query_type, repository)[ + operation_id: NodeResponseDict = self._query(query, query_type, repository, paranet_ual)[ "operationId" ] operation_result = self.get_operation_result(operation_id, "query") diff --git a/dkg/providers/node_http.py b/dkg/providers/node_http.py index 1286655..c096ca2 100644 --- a/dkg/providers/node_http.py +++ b/dkg/providers/node_http.py @@ -25,8 +25,14 @@ class NodeHTTPProvider: - def __init__(self, endpoint_uri: URI | str, auth_token: str | None = None): + def __init__( + self, + endpoint_uri: URI | str, + api_version: str = "v1", + auth_token: str | None = None, + ): self.endpoint_uri = URI(endpoint_uri) + self.api_version = api_version self.auth_token = auth_token def make_request( @@ -36,7 +42,7 @@ def make_request( params: dict[str, Any] = {}, data: dict[str, Any] = {}, ) -> NodeResponseDict: - url = f"{self.endpoint_uri}/{path}" + url = f"{self.endpoint_uri}/{self.api_version}/{path}" headers = ( {"Authorization": f"Bearer {self.auth_token}"} if self.auth_token else {} ) diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 977dc8e..d7faac4 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -77,7 +77,7 @@ class NodeRequest: query = NodeCall( method=HTTPRequestMethod.POST, path="query", - data={"query": str, "type": str, "repository": str}, + data={"query": str, "type": str, "repository": str | None, "paranet_ual": str | None}, ) diff --git a/examples/demo.py b/examples/demo.py index 071b216..f77492b 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -20,7 +20,7 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider -node_provider = NodeHTTPProvider("http://localhost:8900") +node_provider = NodeHTTPProvider(endpoint_uri="http://localhost:8900", api_version="v1") blockchain_provider = BlockchainProvider( "development", "hardhat2:31337", @@ -67,116 +67,164 @@ def print_json(json_dict: dict): divider() -formatted_assertions = dkg.assertion.format_graph(content) -print("======================== ASSET FORMATTED") -print_json(formatted_assertions) +# formatted_assertions = dkg.assertion.format_graph(content) +# print("======================== ASSET FORMATTED") +# print_json(formatted_assertions) -divider() +# divider() -public_assertion_id = dkg.assertion.get_public_assertion_id(content) -print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") -print(public_assertion_id) +# public_assertion_id = dkg.assertion.get_public_assertion_id(content) +# print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") +# print(public_assertion_id) -divider() +# divider() -public_assertion_size = dkg.assertion.get_size(content) -print("======================== PUBLIC ASSERTION SIZE CALCULATED") -print(public_assertion_size) +# public_assertion_size = dkg.assertion.get_size(content) +# print("======================== PUBLIC ASSERTION SIZE CALCULATED") +# print(public_assertion_size) -divider() +# divider() -public_assertion_triples_number = dkg.assertion.get_triples_number(content) -print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") -print(public_assertion_triples_number) +# public_assertion_triples_number = dkg.assertion.get_triples_number(content) +# print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") +# print(public_assertion_triples_number) -divider() +# divider() -public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) -print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") -print(public_assertion_chunks_number) +# public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) +# print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") +# print(public_assertion_chunks_number) -divider() +# divider() -bid_suggestion = dkg.network.get_bid_suggestion( - public_assertion_id, - public_assertion_size, - 2, -) -print("======================== BID SUGGESTION CALCULATED") -print(bid_suggestion) +# bid_suggestion = dkg.network.get_bid_suggestion( +# public_assertion_id, +# public_assertion_size, +# 2, +# ) +# print("======================== BID SUGGESTION CALCULATED") +# print(bid_suggestion) -divider() +# divider() -current_allowance = dkg.asset.get_current_allowance() -print("======================== GET CURRENT ALLOWANCE") -print(current_allowance) +# current_allowance = dkg.asset.get_current_allowance() +# print("======================== GET CURRENT ALLOWANCE") +# print(current_allowance) -divider() +# divider() -allowance_increase = dkg.asset.increase_allowance(bid_suggestion) -print("======================== INCREASE ALLOWANCE") -print(allowance_increase) +# allowance_increase = dkg.asset.increase_allowance(bid_suggestion) +# print("======================== INCREASE ALLOWANCE") +# print(allowance_increase) -divider() +# divider() -allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) -print("======================== DECREASE ALLOWANCE") -print(allowance_decrease) +# allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) +# print("======================== DECREASE ALLOWANCE") +# print(allowance_decrease) -divider() +# divider() -allowance_set = dkg.asset.set_allowance(bid_suggestion) -print("======================== SET ALLOWANCE") -print(allowance_set) +# allowance_set = dkg.asset.set_allowance(bid_suggestion) +# print("======================== SET ALLOWANCE") +# print(allowance_set) -divider() +# divider() -create_asset_result = dkg.asset.create(content, 2) -print("======================== ASSET CREATED") -print_json(create_asset_result) -divider() +# create_asset_result = dkg.asset.create(content, 2) +# print("======================== ASSET CREATED") +# print_json(create_asset_result) +# divider() -validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) -print("======================== VALIDATE UAL") -print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") -divider() +# validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) +# print("======================== VALIDATE UAL") +# print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") +# divider() -owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) -print("======================== GET ASSET OWNER") -print(owner_result) -divider() +# owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) +# print("======================== GET ASSET OWNER") +# print(owner_result) +# divider() -get_asset_result = dkg.asset.get(create_asset_result["UAL"]) -print("======================== ASSET RESOLVED") -print_json(get_asset_result) -divider() +# get_asset_result = dkg.asset.get(create_asset_result["UAL"]) +# print("======================== ASSET RESOLVED") +# print_json(get_asset_result) +# divider() -get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") -print("======================== ASSET LATEST RESOLVED") -print_json(get_latest_asset_result) -divider() +# get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") +# print("======================== ASSET LATEST RESOLVED") +# print_json(get_latest_asset_result) +# divider() -get_latest_finalized_asset_result = dkg.asset.get( - create_asset_result["UAL"], "latest_finalized", "all" -) -print("======================== ASSET LATEST FINALIZED RESOLVED") -print_json(get_latest_finalized_asset_result) -divider() +# get_latest_finalized_asset_result = dkg.asset.get( +# create_asset_result["UAL"], "latest_finalized", "all" +# ) +# print("======================== ASSET LATEST FINALIZED RESOLVED") +# print_json(get_latest_finalized_asset_result) +# divider() -get_first_state_by_index = dkg.asset.get(create_asset_result["UAL"], 0, "all") -print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") -print_json(get_first_state_by_index) -divider() - -get_first_state_by_hash = dkg.asset.get( - create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" +# get_first_state_by_index = dkg.asset.get(create_asset_result["UAL"], 0, "all") +# print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") +# print_json(get_first_state_by_index) +# divider() + +# get_first_state_by_hash = dkg.asset.get( +# create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" +# ) +# print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") +# print_json(get_first_state_by_hash) +# divider() + +query_operation_result = dkg.graph.query( + """ + PREFIX gs1: PREFIX schema: + + SELECT ?recipeNameRaw ?baseUal + WHERE { + ?recipe a schema:Recipe ; + GRAPH ?ual { + ?recipe schema:name ?recipeNameRaw ; + } + FILTER (STRSTARTS(STR(?ual), "did:dkg:base:84532/0x4e8ebfce9a0f4be374709f1ef2791e8ca6371ecb/")) + BIND (REPLACE(STR(?ual), "(did:dkg:base:[^/]+/[^/]+/[^/]+)(/.*)?", "$1") AS ?baseUal) + } + """ ) -print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") -print_json(get_first_state_by_hash) -divider() - -query_result = dkg.graph.query( - "construct { ?s ?p ?o } where { ?s ?p ?o . ?p ?o }", "privateCurrent" +print("======================== ASSET QUERY") +print(query_operation_result) + +divider() + +query_operation_result = dkg.graph.query( + """ + CONSTRUCT { ?s ?p ?o .} + WHERE { + GRAPH ?g { ?s ?p ?o . } + VALUES ?g { + + + } + } + """ +) +print("======================== ASSET QUERY") +print(query_operation_result) + +divider() + +query_operation_result = dkg.graph.query( + """ + CONSTRUCT { ?s ?p ?o . } + WHERE { + { + GRAPH { ?s ?p ?o . } + } + UNION + { + GRAPH { ?s ?p ?o . } + } + } + """ ) -print("======================== QUERY LOCAL CURRENT RESULT") -print(query_result) +print("======================== ASSET QUERY") +print(query_operation_result) From dae8fd5e783d5c486b9a5db37489c09f9f20a7e4 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 31 Dec 2024 09:19:53 +0100 Subject: [PATCH 022/146] format query strings in demo --- examples/demo.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/demo.py b/examples/demo.py index f77492b..d3679e0 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -177,17 +177,17 @@ def print_json(json_dict: dict): query_operation_result = dkg.graph.query( """ - PREFIX gs1: PREFIX schema: - - SELECT ?recipeNameRaw ?baseUal - WHERE { - ?recipe a schema:Recipe ; - GRAPH ?ual { - ?recipe schema:name ?recipeNameRaw ; - } - FILTER (STRSTARTS(STR(?ual), "did:dkg:base:84532/0x4e8ebfce9a0f4be374709f1ef2791e8ca6371ecb/")) - BIND (REPLACE(STR(?ual), "(did:dkg:base:[^/]+/[^/]+/[^/]+)(/.*)?", "$1") AS ?baseUal) + PREFIX gs1: + PREFIX schema: + SELECT ?recipeNameRaw ?baseUal + WHERE { + ?recipe a schema:Recipe ; + GRAPH ?ual { + ?recipe schema:name ?recipeNameRaw ; } + FILTER (STRSTARTS(STR(?ual), "did:dkg:base:84532/0x4e8ebfce9a0f4be374709f1ef2791e8ca6371ecb/")) + BIND (REPLACE(STR(?ual), "(did:dkg:base:[^/]+/[^/]+/[^/]+)(/.*)?", "$1") AS ?baseUal) + } """ ) print("======================== ASSET QUERY") From 509ad74738dddd3fcdf9b6329eb319f2c7096a5d Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 31 Dec 2024 10:01:29 +0100 Subject: [PATCH 023/146] Add ruff pre-commit hooks --- .pre-commit-config.yaml | 10 +++ poetry.lock | 175 +++++++++++++++++++++++++++++++--------- pyproject.toml | 3 +- 3 files changed, 148 insertions(+), 40 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..c6ba097 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,10 @@ +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.8.4 + hooks: + # Run the linter. + - id: ruff + args: [--fix] + # Run the formatter. + - id: ruff-format diff --git a/poetry.lock b/poetry.lock index 20ab8d4..a356006 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "aiohttp" @@ -295,6 +295,17 @@ files = [ {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, ] +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + [[package]] name = "charset-normalizer" version = "3.3.0" @@ -605,6 +616,17 @@ toolz = ">=0.8.0" [package.extras] cython = ["cython"] +[[package]] +name = "distlib" +version = "0.3.9" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, + {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, +] + [[package]] name = "eth-abi" version = "5.1.0" @@ -784,20 +806,20 @@ docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme test = ["hypothesis (>=4.43.0)", "mypy (==1.10.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] -name = "flake8" -version = "6.1.0" -description = "the modular source code checker: pep8 pyflakes and co" +name = "filelock" +version = "3.16.1" +description = "A platform independent file lock." optional = false -python-versions = ">=3.8.1" +python-versions = ">=3.8" files = [ - {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, - {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, ] -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.11.0,<2.12.0" -pyflakes = ">=3.1.0,<3.2.0" +[package.extras] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "frozendict" @@ -931,6 +953,20 @@ dev = ["build (>=0.9.0)", "bump-my-version (>=0.19.0)", "eth-utils (>=2.0.0)", " docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] test = ["eth-utils (>=2.0.0)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] +[[package]] +name = "identify" +version = "2.6.4" +description = "File identification library for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "identify-2.6.4-py2.py3-none-any.whl", hash = "sha256:993b0f01b97e0568c179bb9196391ff391bfb88a99099dbf5ce392b68f42d0af"}, + {file = "identify-2.6.4.tar.gz", hash = "sha256:285a7d27e397652e8cafe537a6cc97dd470a970f48fb2e9d979aa38eae5513ac"}, +] + +[package.extras] +license = ["ukkonen"] + [[package]] name = "idna" version = "3.4" @@ -1063,17 +1099,6 @@ html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] source = ["Cython (>=0.29.35)"] -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - [[package]] name = "multidict" version = "6.0.4" @@ -1157,6 +1182,17 @@ files = [ {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, ] +[[package]] +name = "nodeenv" +version = "1.9.1" +description = "Node.js virtual environment builder" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, + {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, +] + [[package]] name = "numpy" version = "2.1.2" @@ -1342,16 +1378,39 @@ files = [ regex = ">=2022.3.15" [[package]] -name = "pycodestyle" -version = "2.11.0" -description = "Python style guide checker" +name = "platformdirs" +version = "4.3.6" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "pycodestyle-2.11.0-py2.py3-none-any.whl", hash = "sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"}, - {file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"}, + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] + +[[package]] +name = "pre-commit" +version = "4.0.1" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.9" +files = [ + {file = "pre_commit-4.0.1-py2.py3-none-any.whl", hash = "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878"}, + {file = "pre_commit-4.0.1.tar.gz", hash = "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + [[package]] name = "pycryptodome" version = "3.19.0" @@ -1517,17 +1576,6 @@ files = [ [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" -[[package]] -name = "pyflakes" -version = "3.1.0" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, - {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, -] - [[package]] name = "pyparsing" version = "3.1.1" @@ -1584,6 +1632,8 @@ description = "Python for Window Extensions" optional = false python-versions = "*" files = [ + {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, + {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, @@ -1819,6 +1869,33 @@ docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme rust-backend = ["rusty-rlp (>=0.2.1)"] test = ["hypothesis (==5.19.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] +[[package]] +name = "ruff" +version = "0.8.4" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:58072f0c06080276804c6a4e21a9045a706584a958e644353603d36ca1eb8a60"}, + {file = "ruff-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ffb60904651c00a1e0b8df594591770018a0f04587f7deeb3838344fe3adabac"}, + {file = "ruff-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ddf5d654ac0d44389f6bf05cee4caeefc3132a64b58ea46738111d687352296"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e248b1f0fa2749edd3350a2a342b67b43a2627434c059a063418e3d375cfe643"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf197b98ed86e417412ee3b6c893f44c8864f816451441483253d5ff22c0e81e"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c41319b85faa3aadd4d30cb1cffdd9ac6b89704ff79f7664b853785b48eccdf3"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9f8402b7c4f96463f135e936d9ab77b65711fcd5d72e5d67597b543bbb43cf3f"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e56b3baa9c23d324ead112a4fdf20db9a3f8f29eeabff1355114dd96014604"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:736272574e97157f7edbbb43b1d046125fce9e7d8d583d5d65d0c9bf2c15addf"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fe710ab6061592521f902fca7ebcb9fabd27bc7c57c764298b1c1f15fff720"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:13e9ec6d6b55f6da412d59953d65d66e760d583dd3c1c72bf1f26435b5bfdbae"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:97d9aefef725348ad77d6db98b726cfdb075a40b936c7984088804dfd38268a7"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ab78e33325a6f5374e04c2ab924a3367d69a0da36f8c9cb6b894a62017506111"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8ef06f66f4a05c3ddbc9121a8b0cecccd92c5bf3dd43b5472ffe40b8ca10f0f8"}, + {file = "ruff-0.8.4-py3-none-win32.whl", hash = "sha256:552fb6d861320958ca5e15f28b20a3d071aa83b93caee33a87b471f99a6c0835"}, + {file = "ruff-0.8.4-py3-none-win_amd64.whl", hash = "sha256:f21a1143776f8656d7f364bd264a9d60f01b7f52243fbe90e7670c0dfe0cf65d"}, + {file = "ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08"}, + {file = "ruff-0.8.4.tar.gz", hash = "sha256:0d5f89f254836799af1615798caa5f80b7f935d7a670fad66c5007928e57ace8"}, +] + [[package]] name = "six" version = "1.16.0" @@ -1894,6 +1971,26 @@ secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17. socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "virtualenv" +version = "20.28.0" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.8" +files = [ + {file = "virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0"}, + {file = "virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa"}, +] + +[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,!=7.3)", "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 = "web3" version = "7.3.0" @@ -2096,4 +2193,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "d7f3646cf1136e2c75feb48e4dbee1534712b03bf17907f12704d261bef8ff90" +content-hash = "813bd256188ce10066e839eb8a7d52f34cc54270c106011fa3504e158bb807eb" diff --git a/pyproject.toml b/pyproject.toml index 03eba3c..b48f6ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,8 @@ eth-typing = "^5.0.0" [tool.poetry.group.dev.dependencies] -flake8 = "^6.0.0" +ruff = "^0.8.4" +pre-commit = "^4.0.1" [tools.setuptools] packages = ["dkg"] From f3c27e3b77ba397226b0dfff626dfdbbe4a133a7 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 31 Dec 2024 10:01:58 +0100 Subject: [PATCH 024/146] Add makefile for easier setup and common commands --- Makefile | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bb090f5 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +.PHONY: install, run-demo, ruff, help + +install: + poetry install + pre-commit install + +run-demo: + python3 examples/demo.py + +ruff: + ruff format + ruff check --fix + +help: + @echo "Available commands:" + @echo " install - Install dependencies and set up pre-commit hooks" + @echo " ruff - Format code and fix linting issues using ruff" + @echo " run-demo - Run /examples/demo.py file" From 242b33dc3a9364afcb9d9c15d30bcad589906090 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 31 Dec 2024 10:02:10 +0100 Subject: [PATCH 025/146] Update readme --- README.md | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 1a79080..14d8c04 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -___ +---
@@ -51,7 +51,7 @@ ___ -___ +---
@@ -61,6 +61,7 @@ ___ ### **What is the Decentralized Knowledge Graph?** +
@@ -70,17 +71,19 @@ ___
OriginTrail Decentralized Knowledge Graph (DKG), hosted on the OriginTrail Decentralized Network (ODN) as trusted knowledge infrastructure, is shared global Knowledge Graph of Knowledge Assets. Running on the basis of the permissionless multi-chain OriginTrail protocol, it combines blockchains and knowledge graph technology to enable trusted AI applications based on key W3C standards. +
### **The OriginTrail DKG Architecture** +
-The OriginTrail tech stack is a three layer structure, consisting of the multi-chain consensus layer (OriginTrail layer 1, running on multiple blockchains), the Decentralized Knowledge Graph layer (OriginTrail Layer 2, hosted on the ODN) and Trusted Knowledge applications in the application layer. +The OriginTrail tech stack is a three layer structure, consisting of the multi-chain consensus layer (OriginTrail layer 1, running on multiple blockchains), the Decentralized Knowledge Graph layer (OriginTrail Layer 2, hosted on the ODN) and Trusted Knowledge applications in the application layer.
DKG Architecture @@ -88,13 +91,15 @@ The OriginTrail tech stack is a three layer structure, consisting of the multi-c Further, the architecture differentiates between **the public, replicated knowledge graph** shared by all network nodes according to the protocol, and **private Knowledge graphs** hosted separately by each of the OriginTrail nodes. -**Anyone can run an OriginTrail node and become part of the ODN, contributing to the network capacity and hosting the OriginTrail DKG. The OriginTrail node is the ultimate data service for data and knowledge intensive Web3 applications and is used as the key backbone for trusted AI applications (see https://chatdkg.ai)** +**Anyone can run an OriginTrail node and become part of the ODN, contributing to the network capacity and hosting the OriginTrail DKG. The OriginTrail node is the ultimate data service for data and knowledge intensive Web3 applications and is used as the key backbone for trusted AI applications (see https://chatdkg.ai)** +
### **What is a Knowledge Asset?** +
@@ -106,15 +111,16 @@ Further, the architecture differentiates between **the public, replicated knowle **Knowledge Asset is the new, AI‑ready resource for the Internet** Knowledge Assets are verifiable containers of structured knowledge that live on the OriginTrail DKG and provide: + - **Discoverability - UAL is the new URL**. Uniform Asset Locators (UALs, based on the W3C Decentralized Identifiers) are a new Web3 knowledge identifier (extensions of the Uniform Resource Locators - URLs) which identify a specific piece of knowledge and make it easy to find and connect with other Knowledge Assets. - **Ownership - NFTs enable ownership**. Each Knowledge Asset contains an NFT token that enables ownership, knowledge asset administration and market mechanisms. - **Verifiability - On-chain information origin and verifiable trail**. The blockchain tech increases trust, security, transparency, and the traceability of information. - By their nature, Knowledge Assets are semantic resources (following the W3C Semantic Web set of standards), and through their symbolic representations inherently AI ready. See more at https://chatdkg.ai
**Discover Knowledge Assets with the DKG Explorer:** +
@@ -146,7 +152,6 @@ By their nature, Knowledge Assets are semantic resources (following the W3C Sema
-

(back to top)

@@ -154,40 +159,43 @@ By their nature, Knowledge Assets are semantic resources (following the W3C Sema ## 🚀 Getting Started -___ +--- ### Prerequisites -* python `>=3.10` -* poetry `>=1.5.1` - +- python `>=3.10` +- poetry `>=1.5.1` In order to use in the local environment, make sure to [run the local DKG network](https://github.com/OriginTrail/ot-node?tab=readme-ov-file#local-network-setup). -___ +--- +
### Installation - Create virtual environment (you can choose any existing folder this command will create configurations and virtual env for python): + ```bash python3 -m venv /path/to/folder ``` Inside of previously generated folder you will find activate script in bin folder and run it: + ```bash source /path/to/folder/bin/activate ``` Install dependencies: + ```bash -poetry install +make install ``` Now you can run a demo example file (you need to have the local DKG network running): + ```bash -python3 examples/demo.py +make run-demo ```
@@ -228,7 +236,6 @@ Don't forget to give the project a star! Thanks again! - [web3.py](https://github.com/ethereum/web3.py): Basis for this project -

(back to top)

@@ -263,4 +270,4 @@ Don't forget to give the project a star! Thanks again! -___ +--- From 3cba62b9b9f5a397e73be6329bcd7973c137cb47 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 31 Dec 2024 10:06:18 +0100 Subject: [PATCH 026/146] update pre commit config --- .pre-commit-config.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c6ba097..a4c3f8d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,6 +5,5 @@ repos: hooks: # Run the linter. - id: ruff - args: [--fix] # Run the formatter. - id: ruff-format From 40dbef063b658a31af12782a455aa6fd811a0bd7 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 31 Dec 2024 10:06:32 +0100 Subject: [PATCH 027/146] update makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bb090f5..bed936e 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ run-demo: ruff: ruff format - ruff check --fix + ruff check help: @echo "Available commands:" From 0007cceb41c90282bcd7c648c0c6414d88492a93 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 31 Dec 2024 10:13:09 +0100 Subject: [PATCH 028/146] format makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bed936e..eeff22e 100644 --- a/Makefile +++ b/Makefile @@ -14,5 +14,5 @@ ruff: help: @echo "Available commands:" @echo " install - Install dependencies and set up pre-commit hooks" - @echo " ruff - Format code and fix linting issues using ruff" + @echo " ruff - Format code and fix linting issues using ruff" @echo " run-demo - Run /examples/demo.py file" From 637b447d4ae3f34cb2f6f166da29174ed4c01bd7 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 31 Dec 2024 10:32:53 +0100 Subject: [PATCH 029/146] Add ruff github action --- .github/workflows/ruff.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/workflows/ruff.yml diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 0000000..2c327fc --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,8 @@ +name: Ruff +on: [push, pull_request] +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/ruff-action@v2 From 19a004284557ee93475fc6996184921fb0f139b0 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 3 Jan 2025 17:27:24 +0100 Subject: [PATCH 030/146] Initial v8 create --- dkg/asset.py | 387 +++-- dkg/constants.py | 31 +- dkg/data/interfaces/AssertionStorage.json | 229 --- dkg/data/interfaces/ContentAsset.json | 697 --------- dkg/data/interfaces/ContentAssetStorage.json | 706 --------- dkg/data/interfaces/Hub.json | 296 +++- dkg/data/interfaces/IdentityStorage.json | 58 + dkg/data/interfaces/Paranet.json | 244 +-- .../ParanetIncentivesPoolFactory.json | 20 +- .../ParanetKnowledgeMinersRegistry.json | 24 +- ...l.json => ParanetNeuroIncentivesPool.json} | 14 +- dkg/data/interfaces/ParanetsRegistry.json | 134 +- .../ServiceAgreementStorageProxy.json | 1314 ----------------- dkg/data/interfaces/Token.json | 163 +- dkg/providers/blockchain.py | 9 +- dkg/utils/blockchain_request.py | 6 + dkg/utils/node_request.py | 14 +- dkg/utils/rdf.py | 201 ++- examples/demo.py | 33 +- 19 files changed, 1192 insertions(+), 3388 deletions(-) delete mode 100644 dkg/data/interfaces/AssertionStorage.json delete mode 100644 dkg/data/interfaces/ContentAsset.json delete mode 100644 dkg/data/interfaces/ContentAssetStorage.json rename dkg/data/interfaces/{ParanetNeurowebIncentivesPool.json => ParanetNeuroIncentivesPool.json} (97%) delete mode 100644 dkg/data/interfaces/ServiceAgreementStorageProxy.json diff --git a/dkg/asset.py b/dkg/asset.py index cc56961..61cf419 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -18,13 +18,18 @@ import json import math import re +import hashlib from typing import Literal, Type from pyld import jsonld from web3 import Web3 -from web3.constants import ADDRESS_ZERO, HASH_ZERO +from web3.constants import ADDRESS_ZERO from web3.exceptions import ContractLogicError from web3.types import TxReceipt +from itertools import chain +from eth_abi.packed import encode_packed +from eth_account.messages import encode_defunct +from eth_account import Account from dkg.constants import ( DEFAULT_HASH_FUNCTION_ID, @@ -32,6 +37,12 @@ PRIVATE_ASSERTION_PREDICATE, PRIVATE_CURRENT_REPOSITORY, PRIVATE_HISTORICAL_REPOSITORY, + PRIVATE_RESOURCE_PREDICATE, + PRIVATE_HASH_SUBJECT_PREFIX, + CHUNK_BYTE_SIZE, + MAX_FILE_SIZE, + Operations, + DefaultParameters, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -65,7 +76,16 @@ StoreTypes, validate_operation_status, ) -from dkg.utils.rdf import format_content, normalize_dataset +from dkg.utils.rdf import ( + format_content, + normalize_dataset, + format_dataset, + generate_missing_ids_for_blank_nodes, + group_nquads_by_subject, + generate_named_node, + calculate_merkle_root, + calculate_number_of_chunks, +) from dkg.utils.ual import format_ual, parse_ual @@ -197,170 +217,260 @@ def decrease_allowance( _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) _create = Method(BlockchainRequest.create_asset) _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) _get_bid_suggestion = Method(NodeRequest.bid_suggestion) _local_store = Method(NodeRequest.local_store) _publish = Method(NodeRequest.publish) + def process_content(self, content: str) -> list: + return [line.strip() for line in content.split("\n") if line.strip() != ""] + + def solidity_packed_sha256(self, types: list[str], values: list) -> str: + # Encode the values using eth_abi's encode_packed + packed_data = encode_packed(types, values) + + # Calculate SHA256 + sha256_hash = hashlib.sha256(packed_data).hexdigest() + + return f"0x{sha256_hash}" + + def insert_triple_sorted(self, triples_list: list, new_triple: str) -> int: + # Assuming triples_list is already sorted + left = 0 + right = len(triples_list) + + while left < right: + mid = (left + right) // 2 + if triples_list[mid] < new_triple: + left = mid + 1 + else: + right = mid + + # Insert the new triple at the correct position + triples_list.insert(left, new_triple) + return left + + def get_operation_status_dict(self, operation_result, operation_id): + # Check if data exists and has errorType + operation_data = ( + {"status": operation_result.get("status"), **operation_result.get("data")} + if operation_result.get("data") + and operation_result.get("data", {}).get("errorType") + else {"status": operation_result.get("status")} + ) + + return {"operationId": operation_id, **operation_data} + + def get_message_signer_address(self, dataset_root: str, signature: dict): + message = encode_defunct(Web3.to_bytes(dataset_root)) + r, s, v = signature.get("r"), signature.get("s"), signature.get("v") + r = r[2:] if r.startswith("0x") else r + s = s[2:] if s.startswith("0x") else s + + sig = "0x" + r + s + hex(v)[2:].zfill(2) + + return Account.recover_message(message, signature=sig) + def create( self, content: dict[Literal["public", "private"], JSONLD], epochs_number: int, + minimum_number_of_finalization_confirmations: int, + minimum_number_of_node_replications: int, token_amount: Wei | None = None, - immutable: bool = False, - content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - paranet_ual: UAL | None = None, + # immutable: bool = False, + # content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + # paranet_ual: UAL | None = None, ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: blockchain_id = self.manager.blockchain_provider.blockchain_id - assertions = format_content(content, content_type) - public_assertion_id = MerkleTree( - hash_assertion_with_indexes(assertions["public"]), - sort_pairs=True, - ).root - public_assertion_metadata = generate_assertion_metadata(assertions["public"]) + dataset = {} + public_content = dataset.get("public") + private_content = dataset.get("private") + if isinstance(content, str): + dataset["public"] = self.process_content(content) + elif isinstance(public_content, str) or ( + not public_content and private_content and isinstance(private_content, str) + ): + if public_content: + dataset["public"] = self.process_content(public_content) + else: + dataset["public"] = [] - content_asset_storage_address = self._get_asset_storage_address( - "ContentAssetStorage" - ) + if private_content and isinstance(private_content, str): + dataset["private"] = self.process_content(private_content) + else: + dataset = format_dataset(content) - if token_amount is None: - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - epochs_number, - public_assertion_metadata["size"], - content_asset_storage_address, - public_assertion_id, - DEFAULT_HASH_FUNCTION_ID, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] + public_triples_grouped = [] + + # TODO: Uncomment and test this + # dataset["public"] = generate_missing_ids_for_blank_nodes(dataset.get("public")) + + if dataset.get("private") and len(dataset.get("private")): + # TODO: Uncomment and test this + # dataset["private"] = generate_missing_ids_for_blank_nodes( + # dataset.get("private") + # ) + + # Group private triples by subject and flatten + private_triples_grouped = group_nquads_by_subject( + dataset.get("private"), True ) - current_allowance = self.get_current_allowance() - if is_allowance_increased := current_allowance < token_amount: - self.increase_allowance(token_amount) + dataset["private"] = list(chain.from_iterable(private_triples_grouped)) - result = {"publicAssertionId": public_assertion_id, "operation": {}} + # Compute private root and add to public + private_root = calculate_merkle_root(dataset.get("private")) + dataset["public"].append( + f'<{generate_named_node()}> <${PRIVATE_ASSERTION_PREDICATE}> "{private_root}" .' + ) - try: - if paranet_ual is None: - receipt: TxReceipt = self._create( - { - "assertionId": Web3.to_bytes(hexstr=public_assertion_id), - "size": public_assertion_metadata["size"], - "triplesNumber": public_assertion_metadata["triples_number"], - "chunksNumber": public_assertion_metadata["chunks_number"], - "tokenAmount": token_amount, - "epochsNumber": epochs_number, - "scoreFunctionId": DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ - self.manager.blockchain_provider.environment - ][blockchain_id], - "immutable_": immutable, - } - ) - else: - parsed_paranet_ual = parse_ual(paranet_ual) - paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( - parsed_paranet_ual["contract_address"], - parsed_paranet_ual["token_id"], - ) + # Compute private root and add to public + public_triples_grouped = group_nquads_by_subject( + dataset.get("public"), True + ) + + # Create a dictionary for public subject -> index for quick lookup + public_subject_dict = {} + for i in range(len(public_triples_grouped)): + public_subject = public_triples_grouped[i][0].split(" ")[0] + public_subject_dict[public_subject] = i + + private_triple_subject_hashes_grouped_without_public_pair = [] + + # Integrate private subjects into public or store separately if no match to be appended later + for private_triples in private_triples_grouped: + private_subject = private_triples[0].split(" ")[ + 0 + ] # Extract the private subject - receipt: TxReceipt = self._mint_paranet_knowledge_asset( - paranet_knowledge_asset_storage, - paranet_knowledge_asset_token_id, - { - "assertionId": Web3.to_bytes(hexstr=public_assertion_id), - "size": public_assertion_metadata["size"], - "triplesNumber": public_assertion_metadata["triples_number"], - "chunksNumber": public_assertion_metadata["chunks_number"], - "tokenAmount": token_amount, - "epochsNumber": epochs_number, - "scoreFunctionId": DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ - self.manager.blockchain_provider.environment - ][blockchain_id], - "immutable_": immutable, - }, + private_subject_hash = self.solidity_packed_sha256( + types=["string"], + values=[private_subject[1:-1]], ) - result["paranetId"] = Web3.to_hex( - Web3.solidity_keccak( - ["address", "uint256"], - [ - paranet_knowledge_asset_storage, - paranet_knowledge_asset_token_id, - ], + if ( + private_subject in public_subject_dict + ): # Check if there's a public pair + # If there's a public pair, insert a representation in that group + # TODO: Test this + public_index = public_subject_dict.get(private_subject) + self.insert_triple_sorted( + public_triples_grouped.get(public_index), + f"{private_subject} <{PRIVATE_RESOURCE_PREDICATE}> <{generate_named_node()}> .", + ) + else: + # If no public pair, maintain separate list, inserting sorted by hash + self.insert_triple_sorted( + private_triple_subject_hashes_grouped_without_public_pair, + f"<{PRIVATE_HASH_SUBJECT_PREFIX}{private_subject_hash}> <{PRIVATE_RESOURCE_PREDICATE}> <{generate_named_node()}> .", ) - ) - except ContractLogicError as err: - if is_allowance_increased: - self.decrease_allowance(token_amount) - raise err - events = self.manager.blockchain_provider.decode_logs_event( - receipt, - "ContentAsset", - "AssetMinted", - ) - token_id = events[0].args["tokenId"] + for triple in private_triple_subject_hashes_grouped_without_public_pair: + public_triples_grouped.append([triple]) - result["UAL"] = format_ual( - blockchain_id, content_asset_storage_address, token_id + dataset["public"] = list(chain.from_iterable(public_triples_grouped)) + else: + # TODO: Test this + # No private triples, just group and flatten public + public_triples_grouped = group_nquads_by_subject( + dataset.get("public"), True + ) + dataset["public"] = list(chain.from_iterable(public_triples_grouped)) + + # Calculate the number of chunks + number_of_chunks = calculate_number_of_chunks( + dataset.get("public"), CHUNK_BYTE_SIZE ) - result["operation"]["mintKnowledgeAsset"] = json.loads(Web3.to_json(receipt)) + dataset_size = number_of_chunks * CHUNK_BYTE_SIZE - assertions_list = [ - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": public_assertion_id, - "assertion": assertions["public"], - "storeType": StoreTypes.TRIPLE, - } - ] + # Validate the assertion size in bytes + # TODO: Move into validation service once developed + if dataset_size > MAX_FILE_SIZE: + raise ValueError(f"File size limit is {MAX_FILE_SIZE / (1024 * 1024)}MB.") - if content.get("private", None): - assertions_list.append( - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": MerkleTree( - hash_assertion_with_indexes(assertions["private"]), - sort_pairs=True, - ).root, - "assertion": assertions["private"], - "storeType": StoreTypes.TRIPLE, - } - ) + # Calculate the Merkle root + dataset_root = calculate_merkle_root(dataset.get("public")) + + # Get the contract address for KnowledgeCollectionStorage + content_asset_storage_address = self._get_asset_storage_address( + "KnowledgeCollectionStorage" + ) - operation_id = self._publish( - public_assertion_id, - assertions["public"], + publish_operation_id = self._publish( + dataset_root, + dataset, blockchain_id, - content_asset_storage_address, - token_id, DEFAULT_HASH_FUNCTION_ID, + minimum_number_of_node_replications, )["operationId"] - operation_result = self.get_operation_result(operation_id, "publish") + publish_operation_result = self.get_operation_result( + Operations.PUBLISH.value, + publish_operation_id, + ) - result["operation"]["publish"] = { - "operationId": operation_id, - "status": operation_result["status"], - } + if publish_operation_result.get( + "status" + ) != OperationStatus.COMPLETED and not publish_operation_result.get( + "data", {} + ).get("minAcksReached"): + return { + "datasetRoot": dataset_root, + "operation": { + "publish": self.get_operation_status_dict( + publish_operation_result, publish_operation_id + ) + }, + } - if operation_result["status"] == OperationStatus.COMPLETED: - operation_id = self._local_store(assertions_list)["operationId"] - operation_result = self.get_operation_result(operation_id, "local-store") + data = publish_operation_result.get("data", {}) + signatures = data.get("signatures") - result["operation"]["localStore"] = { - "operationId": operation_id, - "status": operation_result["status"], - } + publisher_node_signature = data.get("publisherNodeSignature", {}) + publisher_node_identity_id = publisher_node_signature.get("identityId") + publisher_node_r = publisher_node_signature.get("r") + publisher_node_vs = publisher_node_signature.get("vs") - return result - + identity_ids, r, vs = [], [], [] + + for signature in signatures: + try: + signer_address = self.get_message_signer_address( + dataset_root, signature + ) + + key_is_operational_wallet = self._key_is_operational_wallet( + signature.get("identityId"), + Web3.solidity_keccak(["address"], [signer_address]), + 2, # IdentityLib.OPERATIONAL_KEY + ) + + # If valid, append the signature components + if key_is_operational_wallet: + identity_ids.append(signature.get("identityId")) + r.append(signature.get("r")) + vs.append(signature.get("vs")) + + except Exception: + continue + + # result["operation"]["publish"] = { + # "operationId": operation_id, + # "status": operation_result["status"], + # } + + # if operation_result["status"] == OperationStatus.COMPLETED: + # operation_id = self._local_store(assertions_list)["operationId"] + # operation_result = self.get_operation_result(operation_id, "local-store") + + # result["operation"]["localStore"] = { + # "operationId": operation_id, + # "status": operation_result["status"], + # } + + # return result def local_store( self, @@ -489,7 +599,6 @@ def local_store( return result - _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) def submit_to_paranet( @@ -587,7 +696,10 @@ def handle_latest_finalized_state(token_id: int) -> tuple[HexStr, bool]: is_state_finalized = False match state: - case KnowledgeAssetEnumStates.LATEST | KnowledgeAssetEnumStates.LATEST_FINALIZED: + case ( + KnowledgeAssetEnumStates.LATEST + | KnowledgeAssetEnumStates.LATEST_FINALIZED + ): public_assertion_id, is_state_finalized = handle_latest_finalized_state( token_id ) @@ -898,13 +1010,18 @@ def get_agreement_id(self, contract_address: Address, token_id: int) -> HexStr: _get_operation_result = Method(NodeRequest.get_operation_result) - @retry(catch=OperationNotFinished, max_retries=5, base_delay=1, backoff=2) + @retry( + catch=OperationNotFinished, + max_retries=DefaultParameters.MAX_NUMBER_OF_RETRIES.value, + base_delay=DefaultParameters.FREQUENCY.value, + backoff=2, + ) def get_operation_result( - self, operation_id: str, operation: str + self, operation: str, operation_id: str ) -> NodeResponseDict: operation_result = self._get_operation_result( - operation_id=operation_id, operation=operation, + operation_id=operation_id, ) validate_operation_status(operation_result) diff --git a/dkg/constants.py b/dkg/constants.py index cf50cea..679a135 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -1,3 +1,4 @@ +from enum import Enum # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -15,10 +16,29 @@ # specific language governing permissions and limitations # under the License. +DEFAULT_CANON_ALGORITHM = "URDNA2015" +DEFAULT_RDF_FORMAT = "application/n-quads" + PRIVATE_ASSERTION_PREDICATE = ( - "https://ontology.origintrail.io/dkg/1.0#privateAssertionID" + "https://ontology.origintrail.io/dkg/1.0#privateMerkleRoot" +) + +PRIVATE_HASH_SUBJECT_PREFIX = "https://ontology.origintrail.io/dkg/1.0#metadata-hash:" + +PRIVATE_RESOURCE_PREDICATE = ( + "https://ontology.origintrail.io/dkg/1.0#representsPrivateResource" ) +CHUNK_BYTE_SIZE = 32 + +MAX_FILE_SIZE = 10000000 + + +class DefaultParameters(Enum): + MAX_NUMBER_OF_RETRIES: int = 5 + FREQUENCY: int = 5 + + BLOCKCHAINS = { "development": { "hardhat1:31337": { @@ -67,3 +87,12 @@ PRIVATE_HISTORICAL_REPOSITORY = "privateHistory" PRIVATE_CURRENT_REPOSITORY = "privateCurrent" + + +class Operations(Enum): + PUBLISH = "publish" + GET = "get" + LOCAL_STORE = "local-store" + QUERY = "query" + PUBLISH_PARANET = "publishParanet" + FINALITY = "finality" diff --git a/dkg/data/interfaces/AssertionStorage.json b/dkg/data/interfaces/AssertionStorage.json deleted file mode 100644 index 749ce61..0000000 --- a/dkg/data/interfaces/AssertionStorage.json +++ /dev/null @@ -1,229 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "hubAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "assertionExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - } - ], - "name": "createAssertion", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "deleteAssertion", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "getAssertion", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - } - ], - "internalType": "struct AssertionStructs.Assertion", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "getAssertionChunksNumber", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "getAssertionSize", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "getAssertionTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "getAssertionTriplesNumber", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hub", - "outputs": [ - { - "internalType": "contract Hub", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/dkg/data/interfaces/ContentAsset.json b/dkg/data/interfaces/ContentAsset.json deleted file mode 100644 index df9ed74..0000000 --- a/dkg/data/interfaces/ContentAsset.json +++ /dev/null @@ -1,697 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "hubAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "AssetExpired", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "CommitPhaseOngoing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "CommitPhaseSucceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "FirstEpochHasAlreadyEnded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetStorage", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "NoPendingUpdate", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetStorage", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "latestStateIndex", - "type": "uint256" - } - ], - "name": "PendingUpdateFinalization", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetStorage", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "latestState", - "type": "bytes32" - } - ], - "name": "UpdateIsNotFinalized", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "returnedTokenAmount", - "type": "uint96" - } - ], - "name": "AssetBurnt", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "state", - "type": "bytes32" - } - ], - "name": "AssetMinted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "AssetPaymentIncreased", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "stateIndex", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "returnedTokenAmount", - "type": "uint96" - } - ], - "name": "AssetStateUpdateCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "stateIndex", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "updateTokenAmount", - "type": "uint96" - } - ], - "name": "AssetStateUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "AssetStoringPeriodExtended", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "AssetUpdatePaymentIncreased", - "type": "event" - }, - { - "inputs": [], - "name": "assertionContract", - "outputs": [ - { - "internalType": "contract Assertion", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "burnAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "cancelAssetStateUpdate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "clearOldCommitsMetadata", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "contentAssetStorage", - "outputs": [ - { - "internalType": "contract ContentAssetStorage", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - } - ], - "internalType": "struct ContentAssetStructs.AssetInputArgs", - "name": "args", - "type": "tuple" - } - ], - "name": "createAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - } - ], - "name": "createAssetWithVariables", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "extendAssetStoringPeriod", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "hashingProxy", - "outputs": [ - { - "internalType": "contract HashingProxy", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hub", - "outputs": [ - { - "internalType": "contract Hub", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "increaseAssetTokenAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "increaseAssetUpdateTokenAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "parametersStorage", - "outputs": [ - { - "internalType": "contract ParametersStorage", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "serviceAgreementStorageProxy", - "outputs": [ - { - "internalType": "contract ServiceAgreementStorageProxy", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "serviceAgreementV1", - "outputs": [ - { - "internalType": "contract ServiceAgreementV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_flag", - "type": "bool" - } - ], - "name": "setOldMetadataClearingFlag", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unfinalizedStateStorage", - "outputs": [ - { - "internalType": "contract UnfinalizedStateStorage", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "updateTokenAmount", - "type": "uint96" - } - ], - "name": "updateAssetState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/dkg/data/interfaces/ContentAssetStorage.json b/dkg/data/interfaces/ContentAssetStorage.json deleted file mode 100644 index b931831..0000000 --- a/dkg/data/interfaces/ContentAssetStorage.json +++ /dev/null @@ -1,706 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "hubAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assetAssertionId", - "type": "bytes32" - } - ], - "name": "assertionExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "deleteAssertionIssuer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "deleteAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "generateTokenId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "getAssertionIdByIndex", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getAssertionIds", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getAssertionIdsLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "assertionIndex", - "type": "uint256" - } - ], - "name": "getAssertionIssuer", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getAsset", - "outputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - }, - { - "internalType": "bytes32[]", - "name": "assertionIds", - "type": "bytes32[]" - } - ], - "internalType": "struct ContentAssetStructs.Asset", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getLatestAssertionId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hub", - "outputs": [ - { - "internalType": "contract Hub", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "isMutable", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "issuers", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "pushAssertionId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "issuer", - "type": "address" - } - ], - "name": "setAssertionIssuer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - } - ], - "name": "setMutability", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/dkg/data/interfaces/Hub.json b/dkg/data/interfaces/Hub.json index 1c53f39..92906e6 100644 --- a/dkg/data/interfaces/Hub.json +++ b/dkg/data/interfaces/Hub.json @@ -1,4 +1,118 @@ [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "AddressAlreadyInSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "AddressDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ContractAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ContractDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "contractName", + "type": "string" + } + ], + "name": "ContractNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyName", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "InvalidTargetContract", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -18,6 +132,25 @@ "name": "AssetStorageChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "contractName", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "AssetStorageRemoved", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -37,6 +170,25 @@ "name": "ContractChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "contractName", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractRemoved", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -94,6 +246,30 @@ "name": "OwnershipTransferred", "type": "event" }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forwardCall", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "getAllAssetStorages", @@ -111,7 +287,7 @@ "type": "address" } ], - "internalType": "struct UnorderedNamedContractDynamicSetLib.Contract[]", + "internalType": "struct UnorderedNamedContractDynamicSet.Contract[]", "name": "", "type": "tuple[]" } @@ -136,7 +312,7 @@ "type": "address" } ], - "internalType": "struct UnorderedNamedContractDynamicSetLib.Contract[]", + "internalType": "struct UnorderedNamedContractDynamicSet.Contract[]", "name": "", "type": "tuple[]" } @@ -284,6 +460,58 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "assetStorageAddress", + "type": "address" + } + ], + "name": "removeAssetStorageByAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "assetStorageName", + "type": "string" + } + ], + "name": "removeAssetStorageByName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "removeContractByAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "contractName", + "type": "string" + } + ], + "name": "removeContractByName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "renounceOwnership", @@ -291,6 +519,70 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "internalType": "struct HubLib.Contract[]", + "name": "newContracts", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "internalType": "struct HubLib.Contract[]", + "name": "newAssetStorageContracts", + "type": "tuple[]" + }, + { + "internalType": "address[]", + "name": "contractsToReinitialize", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "contractName", + "type": "string" + }, + { + "internalType": "bytes[]", + "name": "encodedData", + "type": "bytes[]" + } + ], + "internalType": "struct HubLib.ForwardCallInputArgs[]", + "name": "forwardCallsData", + "type": "tuple[]" + } + ], + "name": "setAndReinitializeContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/dkg/data/interfaces/IdentityStorage.json b/dkg/data/interfaces/IdentityStorage.json index 568fde9..e7d99f4 100644 --- a/dkg/data/interfaces/IdentityStorage.json +++ b/dkg/data/interfaces/IdentityStorage.json @@ -10,6 +10,38 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "IndexOutOfBounds", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -264,6 +296,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "lastIdentityId", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "name", @@ -308,6 +353,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "setLastIdentityId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/dkg/data/interfaces/Paranet.json b/dkg/data/interfaces/Paranet.json index ba21816..04ce899 100644 --- a/dkg/data/interfaces/Paranet.json +++ b/dkg/data/interfaces/Paranet.json @@ -13,12 +13,12 @@ { "inputs": [ { - "internalType": "enum ParanetStructs.MinersAccessPolicy[]", + "internalType": "enum ParanetLib.MinersAccessPolicy[]", "name": "expectedAccessPolicies", "type": "uint8[]" }, { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "actualAccessPolicy", "type": "uint8" } @@ -29,12 +29,12 @@ { "inputs": [ { - "internalType": "enum ParanetStructs.NodesAccessPolicy[]", + "internalType": "enum ParanetLib.NodesAccessPolicy[]", "name": "expectedAccessPolicies", "type": "uint8[]" }, { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "actualAccessPolicy", "type": "uint8" } @@ -42,27 +42,6 @@ "name": "InvalidParanetNodesAccessPolicy", "type": "error" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKnowledgeAssetStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetTokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - } - ], - "name": "KnowledgeAssetIsAPartOfOtherParanet", - "type": "error" - }, { "inputs": [ { @@ -92,7 +71,7 @@ "type": "address" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } @@ -193,7 +172,7 @@ "type": "uint72" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } @@ -292,6 +271,22 @@ "name": "ProfileDoesntExist", "type": "error" }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -602,7 +597,7 @@ } ], "indexed": false, - "internalType": "struct ParanetStructs.IncentivesPool", + "internalType": "struct ParanetLib.IncentivesPool", "name": "incentivesPool", "type": "tuple" } @@ -670,19 +665,19 @@ }, { "indexed": false, - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" }, { "indexed": false, - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" }, { "indexed": false, - "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", "name": "knowledgeAssetsAccessPolicy", "type": "uint8" } @@ -866,7 +861,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.UniversalAssetLocator[]", + "internalType": "struct ParanetLib.UniversalAssetLocator[]", "name": "services", "type": "tuple[]" } @@ -922,51 +917,12 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "contentAsset", - "outputs": [ - { - "internalType": "contract ContentAssetV2", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "contentAssetStorage", - "outputs": [ - { - "internalType": "contract ContentAssetStorageV2", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hashingProxy", - "outputs": [ - { - "internalType": "contract HashingProxy", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } @@ -994,77 +950,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKAStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - } - ], - "internalType": "struct ContentAssetStructs.AssetInputArgs", - "name": "knowledgeAssetArgs", - "type": "tuple" - } - ], - "name": "mintKnowledgeAsset", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "name", @@ -1130,34 +1015,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKAStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "start", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "end", - "type": "uint256" - } - ], - "name": "processUpdatedKnowledgeAssetStatesMetadata", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "profileStorage", @@ -1194,12 +1051,12 @@ "type": "string" }, { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" } @@ -1382,19 +1239,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "serviceAgreementStorageProxy", - "outputs": [ - { - "internalType": "contract ServiceAgreementStorageProxy", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1421,34 +1265,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKAStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "knowledgeAssetStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "knowledgeAssetTokenId", - "type": "uint256" - } - ], - "name": "submitKnowledgeAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { diff --git a/dkg/data/interfaces/ParanetIncentivesPoolFactory.json b/dkg/data/interfaces/ParanetIncentivesPoolFactory.json index c276757..774b229 100644 --- a/dkg/data/interfaces/ParanetIncentivesPoolFactory.json +++ b/dkg/data/interfaces/ParanetIncentivesPoolFactory.json @@ -36,6 +36,22 @@ "name": "ParanetIncentivesPoolAlreadyExists", "type": "error" }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -65,7 +81,7 @@ } ], "indexed": false, - "internalType": "struct ParanetStructs.IncentivesPool", + "internalType": "struct ParanetLib.IncentivesPool", "name": "incentivesPool", "type": "tuple" } @@ -117,7 +133,7 @@ "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } diff --git a/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json b/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json index e725892..f78c7e5 100644 --- a/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json +++ b/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json @@ -10,6 +10,22 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, { "inputs": [ { @@ -288,7 +304,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.KnowledgeMinerMetadata", + "internalType": "struct ParanetLib.KnowledgeMinerMetadata", "name": "", "type": "tuple" } @@ -464,7 +480,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetStructs.UpdatingKnowledgeAssetState[]", + "internalType": "struct ParanetLib.UpdatingKnowledgeAssetState[]", "name": "", "type": "tuple[]" } @@ -510,7 +526,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetStructs.UpdatingKnowledgeAssetState[]", + "internalType": "struct ParanetLib.UpdatingKnowledgeAssetState[]", "name": "", "type": "tuple[]" } @@ -523,7 +539,7 @@ "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } diff --git a/dkg/data/interfaces/ParanetNeurowebIncentivesPool.json b/dkg/data/interfaces/ParanetNeuroIncentivesPool.json similarity index 97% rename from dkg/data/interfaces/ParanetNeurowebIncentivesPool.json rename to dkg/data/interfaces/ParanetNeuroIncentivesPool.json index 288bf3e..1677d83 100644 --- a/dkg/data/interfaces/ParanetNeurowebIncentivesPool.json +++ b/dkg/data/interfaces/ParanetNeuroIncentivesPool.json @@ -212,7 +212,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetStructs.ParanetIncentivizationProposalVoterInput[]", + "internalType": "struct ParanetLib.ParanetIncentivizationProposalVoterInput[]", "name": "voters_", "type": "tuple[]" } @@ -366,7 +366,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.ParanetIncentivesPoolClaimedRewardsProfile[]", + "internalType": "struct ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[]", "name": "", "type": "tuple[]" } @@ -391,7 +391,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.ParanetIncentivesPoolClaimedRewardsProfile[]", + "internalType": "struct ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[]", "name": "", "type": "tuple[]" } @@ -518,7 +518,7 @@ "type": "bool" } ], - "internalType": "struct ParanetStructs.NeuroEmissionMultiplier[]", + "internalType": "struct ParanetLib.NeuroEmissionMultiplier[]", "name": "", "type": "tuple[]" } @@ -619,7 +619,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.ParanetIncentivizationProposalVoter", + "internalType": "struct ParanetLib.ParanetIncentivizationProposalVoter", "name": "", "type": "tuple" } @@ -649,7 +649,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.ParanetIncentivizationProposalVoter[]", + "internalType": "struct ParanetLib.ParanetIncentivizationProposalVoter[]", "name": "", "type": "tuple[]" } @@ -675,7 +675,7 @@ "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } diff --git a/dkg/data/interfaces/ParanetsRegistry.json b/dkg/data/interfaces/ParanetsRegistry.json index 4810d44..438a9fb 100644 --- a/dkg/data/interfaces/ParanetsRegistry.json +++ b/dkg/data/interfaces/ParanetsRegistry.json @@ -10,6 +10,76 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "AddressAlreadyInSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "AddressDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ContractAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ContractDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyName", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, { "inputs": [ { @@ -100,7 +170,7 @@ "type": "address" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } @@ -123,7 +193,7 @@ "type": "uint72" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } @@ -187,7 +257,7 @@ "type": "address" } ], - "internalType": "struct UnorderedNamedContractDynamicSetStructs.Contract[]", + "internalType": "struct UnorderedNamedContractDynamicSet.Contract[]", "name": "", "type": "tuple[]" } @@ -237,7 +307,7 @@ "type": "bytes" } ], - "internalType": "struct ParanetStructs.Node[]", + "internalType": "struct ParanetLib.Node[]", "name": "", "type": "tuple[]" } @@ -337,7 +407,7 @@ "name": "getKnowledgeAssetsAccessPolicy", "outputs": [ { - "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", "name": "", "type": "uint8" } @@ -460,12 +530,12 @@ "type": "address" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetKnowledgeMinerAccessRequest", + "internalType": "struct ParanetLib.ParanetKnowledgeMinerAccessRequest", "name": "", "type": "tuple" } @@ -506,12 +576,12 @@ "type": "address" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetKnowledgeMinerAccessRequest[]", + "internalType": "struct ParanetLib.ParanetKnowledgeMinerAccessRequest[]", "name": "", "type": "tuple[]" } @@ -614,12 +684,12 @@ "type": "address" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetKnowledgeMinerAccessRequest", + "internalType": "struct ParanetLib.ParanetKnowledgeMinerAccessRequest", "name": "", "type": "tuple" } @@ -660,12 +730,12 @@ "type": "uint72" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetNodeJoinRequest", + "internalType": "struct ParanetLib.ParanetNodeJoinRequest", "name": "", "type": "tuple" } @@ -684,7 +754,7 @@ "name": "getMinersAccessPolicy", "outputs": [ { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "", "type": "uint8" } @@ -749,12 +819,12 @@ "type": "uint72" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetNodeJoinRequest", + "internalType": "struct ParanetLib.ParanetNodeJoinRequest", "name": "", "type": "tuple" } @@ -795,12 +865,12 @@ "type": "uint72" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetNodeJoinRequest[]", + "internalType": "struct ParanetLib.ParanetNodeJoinRequest[]", "name": "", "type": "tuple[]" } @@ -843,7 +913,7 @@ "name": "getNodesAccessPolicy", "outputs": [ { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "", "type": "uint8" } @@ -908,17 +978,17 @@ "type": "string" }, { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", "name": "knowledgeAssetsAccessPolicy", "type": "uint8" }, @@ -928,7 +998,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetStructs.ParanetMetadata", + "internalType": "struct ParanetLib.ParanetMetadata", "name": "", "type": "tuple" } @@ -1027,7 +1097,7 @@ "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } @@ -1186,17 +1256,17 @@ "type": "string" }, { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", "name": "knowledgeAssetsAccessPolicy", "type": "uint8" } @@ -1433,7 +1503,7 @@ "type": "bytes32" }, { - "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", "name": "knowledgeAssetsAccessPolicy", "type": "uint8" } @@ -1451,7 +1521,7 @@ "type": "bytes32" }, { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" } @@ -1487,7 +1557,7 @@ "type": "bytes32" }, { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" } @@ -1556,7 +1626,7 @@ "type": "uint256" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } @@ -1584,7 +1654,7 @@ "type": "uint256" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } diff --git a/dkg/data/interfaces/ServiceAgreementStorageProxy.json b/dkg/data/interfaces/ServiceAgreementStorageProxy.json deleted file mode 100644 index 342afe4..0000000 --- a/dkg/data/interfaces/ServiceAgreementStorageProxy.json +++ /dev/null @@ -1,1314 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "hubAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "agreementV1Exists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "agreementV1StorageAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "agreementV1U1Exists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "agreementV1U1StorageAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "commitSubmissionExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "commitV1Exists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "commitV1U1Exists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "prevIdentityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "nextIdentityId", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "score", - "type": "uint40" - } - ], - "name": "createV1CommitSubmissionObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint128", - "name": "epochLength", - "type": "uint128" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "proofWindowOffsetPerc", - "type": "uint8" - } - ], - "name": "createV1ServiceAgreementObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "prevIdentityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "nextIdentityId", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "score", - "type": "uint40" - } - ], - "name": "createV1U1CommitSubmissionObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "startTime", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint128", - "name": "epochLength", - "type": "uint128" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "proofWindowOffsetPerc", - "type": "uint8" - } - ], - "name": "createV1U1ServiceAgreementObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - } - ], - "name": "decrementAgreementRewardedNodesNumber", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "epochStateId", - "type": "bytes32" - } - ], - "name": "decrementCommitsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - } - ], - "name": "deleteAgreementRewardedNodesNumber", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "deleteCommitSubmissionsObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "epochStateId", - "type": "bytes32" - } - ], - "name": "deleteCommitsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "deleteServiceAgreementObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "deleteServiceAgreementV1Object", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "deleteServiceAgreementV1U1Object", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "stateId", - "type": "bytes32" - } - ], - "name": "deleteUpdateCommitsDeadline", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementData", - "outputs": [ - { - "internalType": "uint256", - "name": "startTime", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint128", - "name": "epochLength", - "type": "uint128" - }, - { - "internalType": "uint96[2]", - "name": "tokens", - "type": "uint96[2]" - }, - { - "internalType": "uint8[2]", - "name": "scoreFunctionIdAndProofWindowOffsetPerc", - "type": "uint8[2]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementEpochLength", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementEpochsNumber", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementProofWindowOffsetPerc", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - } - ], - "name": "getAgreementRewardedNodesNumber", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementScoreFunctionId", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementStartTime", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementTokenAmount", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementUpdateTokenAmount", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "getCommitSubmission", - "outputs": [ - { - "components": [ - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "prevIdentityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "nextIdentityId", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "score", - "type": "uint40" - } - ], - "internalType": "struct ServiceAgreementStructsV1.CommitSubmission", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "getCommitSubmissionIdentityId", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "getCommitSubmissionNextIdentityId", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "getCommitSubmissionPrevIdentityId", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "getCommitSubmissionScore", - "outputs": [ - { - "internalType": "uint40", - "name": "", - "type": "uint40" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "epochStateId", - "type": "bytes32" - } - ], - "name": "getCommitsCount", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "stateId", - "type": "bytes32" - } - ], - "name": "getUpdateCommitsDeadline", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - } - ], - "name": "getV1AgreementEpochSubmissionHead", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "stateIndex", - "type": "uint256" - } - ], - "name": "getV1U1AgreementEpochSubmissionHead", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hub", - "outputs": [ - { - "internalType": "contract Hub", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - } - ], - "name": "incrementAgreementRewardedNodesNumber", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "epochStateId", - "type": "bytes32" - } - ], - "name": "incrementCommitsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "migrateV1ServiceAgreement", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "serviceAgreementExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "epochLength", - "type": "uint128" - } - ], - "name": "setAgreementEpochLength", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - } - ], - "name": "setAgreementEpochsNumber", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "proofWindowOffsetPerc", - "type": "uint8" - } - ], - "name": "setAgreementProofWindowOffsetPerc", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "rewardedNodesNumber", - "type": "uint32" - } - ], - "name": "setAgreementRewardedNodesNumber", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "newScoreFunctionId", - "type": "uint8" - } - ], - "name": "setAgreementScoreFunctionId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "startTime", - "type": "uint256" - } - ], - "name": "setAgreementStartTime", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "setAgreementTokenAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint96", - "name": "updateTokenAmount", - "type": "uint96" - } - ], - "name": "setAgreementUpdateTokenAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "setCommitSubmissionIdentityId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "nextIdentityId", - "type": "uint72" - } - ], - "name": "setCommitSubmissionNextIdentityId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "prevIdentityId", - "type": "uint72" - } - ], - "name": "setCommitSubmissionPrevIdentityId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint40", - "name": "score", - "type": "uint40" - } - ], - "name": "setCommitSubmissionScore", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "epochStateId", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "epochStateCommitsCount", - "type": "uint8" - } - ], - "name": "setCommitsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "stateId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "setUpdateCommitsDeadline", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - }, - { - "internalType": "bytes32", - "name": "headCommitId", - "type": "bytes32" - } - ], - "name": "setV1AgreementEpochSubmissionHead", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "stateIndex", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "headCommitId", - "type": "bytes32" - } - ], - "name": "setV1U1AgreementEpochSubmissionHead", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "storageV1", - "outputs": [ - { - "internalType": "contract ServiceAgreementStorageV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "storageV1U1", - "outputs": [ - { - "internalType": "contract ServiceAgreementStorageV1U1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "transferAgreementTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "transferV1AgreementTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "transferV1U1AgreementTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/dkg/data/interfaces/Token.json b/dkg/data/interfaces/Token.json index 8a5ce2b..c722726 100644 --- a/dkg/data/interfaces/Token.json +++ b/dkg/data/interfaces/Token.json @@ -15,6 +15,135 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -218,7 +347,7 @@ }, { "internalType": "uint256", - "name": "amount", + "name": "value", "type": "uint256" } ], @@ -326,6 +455,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -434,7 +576,7 @@ }, { "internalType": "address", - "name": "account", + "name": "callerConfirmation", "type": "address" } ], @@ -461,19 +603,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "setupRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -528,7 +657,7 @@ }, { "internalType": "uint256", - "name": "amount", + "name": "value", "type": "uint256" } ], @@ -557,7 +686,7 @@ }, { "internalType": "uint256", - "name": "amount", + "name": "value", "type": "uint256" } ], diff --git a/dkg/providers/blockchain.py b/dkg/providers/blockchain.py index 96b2603..321b5f1 100644 --- a/dkg/providers/blockchain.py +++ b/dkg/providers/blockchain.py @@ -260,11 +260,14 @@ def _update_contract_instance(self, contract: str) -> bool: ): self.contracts[contract] = self.w3.eth.contract( address=( - self.contracts["Hub"].functions.getContractAddress(contract).call() - if not contract.endswith("AssetStorage") - else self.contracts["Hub"] + self.contracts["Hub"] .functions.getAssetStorageAddress(contract) .call() + if contract.endswith("AssetStorage") + or contract.endswith("CollectionStorage") + else self.contracts["Hub"] + .functions.getContractAddress(contract) + .call() ), abi=self.abi[contract], decode_tuples=True, diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index 9ec37a0..fc5b379 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -67,6 +67,12 @@ class BlockchainRequest: args={"assetStorageName": str}, ) + key_is_operational_wallet = ContractCall( + contract="IdentityStorage", + function="keyHasPurpose", + args={"identityId": int, "_key": Address, "_purpose": int}, + ) + allowance = ContractCall( contract="Token", function="allowance", diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index d7faac4..340c650 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -61,12 +61,11 @@ class NodeRequest: method=HTTPRequestMethod.POST, path="publish", data={ - "assertionId": str, - "assertion": NQuads, + "datasetRoot": str, + "dataset": dict[str, list[str]], "blockchain": str, - "contract": Address, - "tokenId": int, "hashFunctionId": int, + "minimumNumberOfNodeReplications": int, }, ) get = NodeCall( @@ -77,7 +76,12 @@ class NodeRequest: query = NodeCall( method=HTTPRequestMethod.POST, path="query", - data={"query": str, "type": str, "repository": str | None, "paranet_ual": str | None}, + data={ + "query": str, + "type": str, + "repository": str | None, + "paranet_ual": str | None, + }, ) diff --git a/dkg/utils/rdf.py b/dkg/utils/rdf.py index 409a61d..06eced2 100644 --- a/dkg/utils/rdf.py +++ b/dkg/utils/rdf.py @@ -17,20 +17,30 @@ from typing import Literal -from dkg.constants import PRIVATE_ASSERTION_PREDICATE +from rdflib.plugins.parsers.nquads import NQuadsParser +from io import StringIO + +from dkg.constants import CHUNK_BYTE_SIZE, PRIVATE_ASSERTION_PREDICATE from dkg.exceptions import DatasetInputFormatNotSupported, InvalidDataset from dkg.types import JSONLD, HexStr, NQuads from dkg.utils.merkle import MerkleTree, hash_assertion_with_indexes from pyld import jsonld +from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM +from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral +from uuid import uuid4 +from web3 import Web3 +import math def normalize_dataset( dataset: JSONLD | NQuads, input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + output_format=DEFAULT_RDF_FORMAT, + algorithm=DEFAULT_CANON_ALGORITHM, ) -> NQuads: normalization_options = { - "algorithm": "URDNA2015", - "format": "application/n-quads", + "algorithm": algorithm, + "format": output_format, } match input_format.lower(): @@ -79,3 +89,188 @@ def format_content( "public": public_assertion, "private": private_assertion if content.get("private", None) else {}, } + + +def is_empty_dict(dictionary: dict): + return len(dictionary.keys()) == 0 and isinstance(dictionary, dict) + + +def format_dataset( + content: dict, + input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + output_format=DEFAULT_RDF_FORMAT, + algorithm=DEFAULT_CANON_ALGORITHM, +): + private_assertion = None + if content.get("private") and not is_empty_dict(content.get("private")): + private_assertion = normalize_dataset( + content.get("private"), input_format, output_format, algorithm + ) + elif not content.get("public"): + content = {"public": content} + + public_assertion = [] + if content.get("public"): + public_assertion = normalize_dataset( + content.get("public"), input_format, output_format, algorithm + ) + + if ( + public_assertion + and len(public_assertion) == 0 + and private_assertion + and len(private_assertion) == 0 + ): + raise ValueError("File format is corrupted, no n-quads are extracted.") + + dataset = {"public": public_assertion} + if private_assertion: + dataset["private"] = private_assertion + + return dataset + + +def generate_missing_ids_for_blank_nodes(nquads_list: list[str]) -> list[str]: + generated_ids = {} + + def replace_blank_node(term): + # Handle blank nodes + if isinstance(term, BNode): + if str(term) not in generated_ids: + generated_ids[str(term)] = URIRef(f"uuid:{str(uuid4())}") + return generated_ids[str(term)] + + # Handle nested quads (RDF-star) + if hasattr(term, "subject"): # Check if term is a quad + return Graph().quad( + replace_blank_node(term.subject), + replace_blank_node(term.predicate), + replace_blank_node(term.object), + ) + + return term # Return IRIs or Literals unchanged + + # Create a graph and parse the N-Quads + g = Graph() + g.parse(data="".join(nquads_list)) + + # Create new graph for updated quads + updated_graph = Graph() + + # Process each quad and replace blank nodes + for quad in g: + updated_quad = ( + replace_blank_node(quad[0]), # subject + replace_blank_node(quad[1]), # predicate + replace_blank_node(quad[2]), # object + ) + updated_graph.add(updated_quad) + + # Serialize back to N-Quads format and split into lines + result = updated_graph.serialize(format="nquads").strip().split("\n") + return [line for line in result if line] # Remove empty + + +def group_nquads_by_subject(nquads_list: list[str], sort: bool = False): + grouped = {} + + # Process each quad in original order + for nquad in nquads_list: + if not nquad.strip(): # Skip empty lines + continue + + # Parse single quad + g = Graph() + g.parse(data=nquad, format="nquads") + quad = next(iter(g)) + subject, predicate, obj = quad + + # Get subject key + subject_key = ( + f"<<<{subject.subject}> <{subject.predicate}> <{subject.object}>>" + if hasattr(subject, "subject") + else f"<{subject}>" + ) + + # Initialize group if needed + if subject_key not in grouped: + grouped[subject_key] = [] + + # Format object + object_value = f'"{obj}"' if isinstance(obj, RDFLiteral) else f"<{obj}>" + + # Add quad to group + quad_string = f"{subject_key} <{predicate}> {object_value} ." + grouped[subject_key].append(quad_string) + + # Return grouped quads (sorted if requested) + grouped_items = sorted(grouped.items()) if sort else grouped.items() + return [quads for _, quads in grouped_items] + + +def split_into_chunks(quads, chunk_size_bytes=32): + # Concatenate the quads with newline characters + concatenated_quads = "\n".join(quads) + + # Encode the concatenated string to bytes + encoded_bytes = concatenated_quads.encode("utf-8") + + # Split the encoded bytes into chunks + chunks = [] + start = 0 + + while start < len(encoded_bytes): + end = min(start + chunk_size_bytes, len(encoded_bytes)) + chunk = encoded_bytes[start:end] + chunks.append(chunk.decode("utf-8")) # Decode bytes back to string + start = end + + return chunks + + +def calculate_merkle_root(quads: list[str], chunk_size_bytes: int = CHUNK_BYTE_SIZE): + chunks = split_into_chunks(quads, chunk_size_bytes) + + # Create leaves using solidityKeccak256 equivalent + leaves = [ + bytes.fromhex(Web3.solidity_keccak(["string", "uint256"], [chunk, index]).hex()) + for index, chunk in enumerate(chunks) + ] + + while len(leaves) > 1: + next_level = [] + + for i in range(0, len(leaves), 2): + left = leaves[i] + + if i + 1 >= len(leaves): + next_level.append(left) + break + + right = leaves[i + 1] + + # Combine and sort the leaves + combined = [left, right] + combined.sort() + + # Calculate the hash of the combined leaves + hash_value = Web3.keccak(b"".join(combined)) + next_level.append(hash_value) + + leaves = next_level + + return f"0x{leaves[0].hex()}" + + +def generate_named_node(): + return f"uuid:{uuid4()}" + + +def calculate_number_of_chunks(quads, chunk_size_bytes=CHUNK_BYTE_SIZE): + # Concatenate the quads with newline characters + concatenated_quads = "\n".join(quads) + + total_size_bytes = len(concatenated_quads.encode("utf-8")) + + # Calculate and return the number of chunks + return math.ceil(total_size_bytes / chunk_size_bytes) diff --git a/examples/demo.py b/examples/demo.py index d3679e0..9bddbf9 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -23,7 +23,7 @@ node_provider = NodeHTTPProvider(endpoint_uri="http://localhost:8900", api_version="v1") blockchain_provider = BlockchainProvider( "development", - "hardhat2:31337", + "hardhat1:31337", private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", ) @@ -41,18 +41,17 @@ def print_json(json_dict: dict): content = { - "public": { - "@context": ["http://schema.org"], - "@id": "uuid:1", - "company": "OT", - "user": {"@id": "uuid:user:1"}, - "city": {"@id": "uuid:belgrade"}, - }, "private": { - "@context": ["http://schema.org"], - "@graph": [ - {"@id": "uuid:user:1", "name": "Adam", "lastname": "Smith"}, - {"@id": "uuid:belgrade", "title": "Belgrade", "postCode": "11000"}, + "@context": "https://www.schema.org", + "@id": "urn:eu-pp:safety-test:3oRIwPtUOJapwNSAGZTzCOWR9bEo", + "@type": "ProductSafetyTest", + "testType": "Functional Safety Test", + "testResults": "Fail", + "relatedProduct": [ + { + "@id": "urn:epc:id:sgtin:59G1yu8uivSRKLLu", + "name": "59G1yu8uivSRKLLu", + }, ], }, } @@ -129,12 +128,12 @@ def print_json(json_dict: dict): # print("======================== SET ALLOWANCE") # print(allowance_set) -# divider() +divider() -# create_asset_result = dkg.asset.create(content, 2) -# print("======================== ASSET CREATED") -# print_json(create_asset_result) -# divider() +create_asset_result = dkg.asset.create(content, 2, 3, 1, "100") +print("======================== ASSET CREATED") +print_json(create_asset_result) +divider() # validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) # print("======================== VALIDATE UAL") From 7ddcc6c47bf1116a42cfe9bf5042ca239023934c Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Mon, 6 Jan 2025 14:34:40 +0100 Subject: [PATCH 031/146] implemented v8 get --- dkg/asset.py | 195 +++++++++++++++++++++++++++++++++++--- dkg/constants.py | 22 +++++ dkg/utils/node_request.py | 9 +- examples/demo.py | 191 +++++++++++++++++++------------------ 4 files changed, 308 insertions(+), 109 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index cc56961..35791a4 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -32,6 +32,7 @@ PRIVATE_ASSERTION_PREDICATE, PRIVATE_CURRENT_REPOSITORY, PRIVATE_HISTORICAL_REPOSITORY, + DEFAULT_PARAMETERS, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -360,7 +361,6 @@ def create( } return result - def local_store( self, @@ -489,7 +489,6 @@ def local_store( return result - _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) def submit_to_paranet( @@ -563,6 +562,122 @@ def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: _get = Method(NodeRequest.get) _query = Method(NodeRequest.query) + def get_v8(self, ual: UAL) -> dict: + get_public_operation_id: NodeResponseDict = self._get( + ual, + DEFAULT_PARAMETERS["CONTENT_TYPE"], + DEFAULT_PARAMETERS["INCLUDE_METADATA"], + DEFAULT_PARAMETERS["HASH_FUNCTION_ID"], + DEFAULT_PARAMETERS["PARANET_UAL"], + DEFAULT_PARAMETERS["GET_SUBJECT_UAL"], + )["operationId"] + + get_public_operation_result = self.get_operation_result( + get_public_operation_id, + "get", + DEFAULT_PARAMETERS["MAX_NUMBER_OF_RETRIES"], + ) + + def get_operation_status_object(self, operation_result, operation_id): + + if "errorType" in operation_result.get("data", {}): + + operation_data = { + "status": operation_result["status"], + **operation_result["data"], + } + else: + + operation_data = {"status": operation_result["status"]} + + return {"operationId": operation_id, **operation_data} + + if DEFAULT_PARAMETERS["GET_SUBJECT_UAL"]: + if get_public_operation_result["data"]: + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + "subjectUALPairs": get_public_operation_result["data"], + } + if get_public_operation_result["status"] != "FAILED": + get_public_operation_result["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Unable to find assertion on the network!", + } + get_public_operation_result["status"] = "FAILED" + + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + metadata = get_public_operation_result["data"] + assertion = get_public_operation_result["data"].get("assertion", None) + + if not assertion: + if get_public_operation_result["status"] != "FAILED": + get_public_operation_result["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Unable to find assertion on the network!", + } + get_public_operation_result["status"] = "FAILED" + + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + + if DEFAULT_PARAMETERS["GET_SUBJECT_UAL"]: + is_valid = True # #TODO: Implement assertion validation logic + if not is_valid: + get_public_operation_result["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Calculated root hashes don't match!", + } + + formatted_assertion = "\n".join( + assertion.get("public", []) + assertion.get("private", []) + ) + + formatted_metadata = None + if DEFAULT_PARAMETERS["OUTPUT_FORMAT"] == "JSON-LD": + formatted_assertion = self.to_jsonld(formatted_assertion) + + if DEFAULT_PARAMETERS["INCLUDE_METADATA"]: + print("USAO") + formatted_metadata = self.to_jsonld("\n".join(metadata)) + + if DEFAULT_PARAMETERS["OUTPUT_FORMAT"] == "N-QUADS": + formatted_assertion = self.to_nquads( + formatted_assertion, "application/n-quads" + ) + if DEFAULT_PARAMETERS["INCLUDE_METADATA"]: + formatted_metadata = self.to_nquads( + "\n".join(metadata), "application/n-quads" + ) + + result = { + "assertion": formatted_assertion, + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + + if DEFAULT_PARAMETERS["INCLUDE_METADATA"] and metadata: + result["metadata"] = formatted_metadata + + return result + def get( self, ual: UAL, @@ -587,7 +702,10 @@ def handle_latest_finalized_state(token_id: int) -> tuple[HexStr, bool]: is_state_finalized = False match state: - case KnowledgeAssetEnumStates.LATEST | KnowledgeAssetEnumStates.LATEST_FINALIZED: + case ( + KnowledgeAssetEnumStates.LATEST + | KnowledgeAssetEnumStates.LATEST_FINALIZED + ): public_assertion_id, is_state_finalized = handle_latest_finalized_state( token_id ) @@ -716,9 +834,11 @@ def handle_latest_finalized_state(token_id: int) -> tuple[HexStr, bool]: query_private_operation_id = self._query( query, "CONSTRUCT", - PRIVATE_CURRENT_REPOSITORY - if is_state_finalized - else PRIVATE_HISTORICAL_REPOSITORY, + ( + PRIVATE_CURRENT_REPOSITORY + if is_state_finalized + else PRIVATE_HISTORICAL_REPOSITORY + ), )["operationId"] query_private_operation_result = self.get_operation_result( @@ -898,15 +1018,62 @@ def get_agreement_id(self, contract_address: Address, token_id: int) -> HexStr: _get_operation_result = Method(NodeRequest.get_operation_result) - @retry(catch=OperationNotFinished, max_retries=5, base_delay=1, backoff=2) def get_operation_result( - self, operation_id: str, operation: str - ) -> NodeResponseDict: - operation_result = self._get_operation_result( - operation_id=operation_id, - operation=operation, + self, operation_id: str, operation: str, max_retries: int = 5 + ): + @retry( + catch=OperationNotFinished, max_retries=max_retries, base_delay=1, backoff=2 ) + def _get_opeation_results_(): + operation_result = self._get_operation_result( + operation_id=operation_id, + operation=operation, + ) + print(operation_result) + validate_operation_status(operation_result) - validate_operation_status(operation_result) + return operation_result - return operation_result + return _get_opeation_results_() + + def to_jsonld(self, nquads: str): + options = { + "algorithm": "URDNA2015", + "format": "application/n-quads", + } + + return jsonld.from_rdf(nquads, options) + + def to_nquads(self, content, input_format): + options = { + "algorithm": "URDNA2015", + "format": "application/n-quads", + } + + if input_format: + options["inputFormat"] = input_format + try: + + jsonld_data = jsonld.from_rdf(content, options) + canonized = jsonld.to_rdf(jsonld_data, options) + + if isinstance(canonized, str): + return [line for line in canonized.split("\n") if line.strip()] + + except Exception as e: + raise ValueError(f"Error processing content: {e}") + + def get_operation_status_object(self, operation_result, operation_id): + + if operation_result.get("data", {}).get("errorType"): + operation_data = { + "status": operation_result["status"], + **operation_result["data"], + } + else: + operation_data = {"status": operation_result["status"]} + + return { + "operationId": operation_id, + **operation_data, + } diff --git a/dkg/constants.py b/dkg/constants.py index cf50cea..b5b47bd 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -67,3 +67,25 @@ PRIVATE_HISTORICAL_REPOSITORY = "privateHistory" PRIVATE_CURRENT_REPOSITORY = "privateCurrent" + +DEFAULT_PARAMETERS = { + "ENVIRONMENT": "mainnet", + "PORT": 8900, + "FREQUENCY": 5, + "MAX_NUMBER_OF_RETRIES": 5, + "HASH_FUNCTION_ID": 1, + "IMMUTABLE": False, + "VALIDATE": True, + "OUTPUT_FORMAT": "JSON-LD", + "STATE": None, + "INCLUDE_METADATA": False, + "CONTENT_TYPE": "all", + "GRAPH_LOCATION": "LOCAL_KG", + "GRAPH_STATE": "CURRENT", + "HANDLE_NOT_MINED_ERROR": False, + "SIMULATE_TXS": False, + "FORCE_REPLACE_TXS": False, + "GAS_LIMIT_MULTIPLIER": 1, + "PARANET_UAL": None, + "GET_SUBJECT_UAL": False, +} diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 977dc8e..84c6a9a 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -72,7 +72,14 @@ class NodeRequest: get = NodeCall( method=HTTPRequestMethod.POST, path="get", - data={"id": UAL, "state": str, "hashFunctionId": int}, + data={ + "id": UAL, + "contentType": str, + "includeMetadata": bool, + "hashFunctionId": int, + "paranetUAL": UAL, + "subjectUAL": UAL, + }, ) query = NodeCall( method=HTTPRequestMethod.POST, diff --git a/examples/demo.py b/examples/demo.py index 071b216..2d521fd 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -20,11 +20,11 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider -node_provider = NodeHTTPProvider("http://localhost:8900") +node_provider = NodeHTTPProvider("https://v6-pegasus-node-04.origin-trail.network:8900") blockchain_provider = BlockchainProvider( - "development", - "hardhat2:31337", - private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "testnet", + "base:84532", + private_key="db20be6415f83a8a9f0c129bf20ab99ba15bfb90ac5e34f1848f59c20ea9c068", ) dkg = DKG(node_provider, blockchain_provider) @@ -58,125 +58,128 @@ def print_json(json_dict: dict): } -divider() +# divider() -info_result = dkg.node.info +# info_result = dkg.node.info -print("======================== NODE INFO RECEIVED") -print_json(info_result) +# print("======================== NODE INFO RECEIVED") +# print_json(info_result) divider() -formatted_assertions = dkg.assertion.format_graph(content) -print("======================== ASSET FORMATTED") -print_json(formatted_assertions) +# formatted_assertions = dkg.assertion.format_graph(content) +# print("======================== ASSET FORMATTED") +# print_json(formatted_assertions) -divider() +# divider() -public_assertion_id = dkg.assertion.get_public_assertion_id(content) -print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") -print(public_assertion_id) +# public_assertion_id = dkg.assertion.get_public_assertion_id(content) +# print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") +# print(public_assertion_id) -divider() +# divider() -public_assertion_size = dkg.assertion.get_size(content) -print("======================== PUBLIC ASSERTION SIZE CALCULATED") -print(public_assertion_size) +# public_assertion_size = dkg.assertion.get_size(content) +# print("======================== PUBLIC ASSERTION SIZE CALCULATED") +# print(public_assertion_size) -divider() +# divider() -public_assertion_triples_number = dkg.assertion.get_triples_number(content) -print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") -print(public_assertion_triples_number) +# public_assertion_triples_number = dkg.assertion.get_triples_number(content) +# print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") +# print(public_assertion_triples_number) -divider() +# divider() -public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) -print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") -print(public_assertion_chunks_number) +# public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) +# print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") +# print(public_assertion_chunks_number) -divider() +# divider() -bid_suggestion = dkg.network.get_bid_suggestion( - public_assertion_id, - public_assertion_size, - 2, -) -print("======================== BID SUGGESTION CALCULATED") -print(bid_suggestion) +# bid_suggestion = dkg.network.get_bid_suggestion( +# public_assertion_id, +# public_assertion_size, +# 2, +# ) +# print("======================== BID SUGGESTION CALCULATED") +# print(bid_suggestion) -divider() - -current_allowance = dkg.asset.get_current_allowance() -print("======================== GET CURRENT ALLOWANCE") -print(current_allowance) - -divider() +# divider() -allowance_increase = dkg.asset.increase_allowance(bid_suggestion) -print("======================== INCREASE ALLOWANCE") -print(allowance_increase) +# current_allowance = dkg.asset.get_current_allowance() +# print("======================== GET CURRENT ALLOWANCE") +# print(current_allowance) -divider() +# divider() -allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) -print("======================== DECREASE ALLOWANCE") -print(allowance_decrease) +# allowance_increase = dkg.asset.increase_allowance(bid_suggestion) +# print("======================== INCREASE ALLOWANCE") +# print(allowance_increase) -divider() +# divider() -allowance_set = dkg.asset.set_allowance(bid_suggestion) -print("======================== SET ALLOWANCE") -print(allowance_set) +# allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) +# print("======================== DECREASE ALLOWANCE") +# print(allowance_decrease) -divider() +# divider() -create_asset_result = dkg.asset.create(content, 2) -print("======================== ASSET CREATED") -print_json(create_asset_result) -divider() +# allowance_set = dkg.asset.set_allowance(bid_suggestion) +# print("======================== SET ALLOWANCE") +# print(allowance_set) -validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) -print("======================== VALIDATE UAL") -print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") -divider() +# divider() -owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) -print("======================== GET ASSET OWNER") -print(owner_result) -divider() +# create_asset_result = dkg.asset.create(content, 2) +# print("======================== ASSET CREATED") +# print_json(create_asset_result) +# divider() -get_asset_result = dkg.asset.get(create_asset_result["UAL"]) -print("======================== ASSET RESOLVED") -print_json(get_asset_result) -divider() +# validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) +# print("======================== VALIDATE UAL") +# print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") +# divider() -get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") -print("======================== ASSET LATEST RESOLVED") -print_json(get_latest_asset_result) -divider() +# owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) +# print("======================== GET ASSET OWNER") +# print(owner_result) +# divider() -get_latest_finalized_asset_result = dkg.asset.get( - create_asset_result["UAL"], "latest_finalized", "all" -) -print("======================== ASSET LATEST FINALIZED RESOLVED") -print_json(get_latest_finalized_asset_result) -divider() +# get_asset_result = dkg.asset.get(create_asset_result["UAL"]) +# print("======================== ASSET RESOLVED") +# print_json(get_asset_result) +# divider() -get_first_state_by_index = dkg.asset.get(create_asset_result["UAL"], 0, "all") -print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") -print_json(get_first_state_by_index) -divider() +# get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") +# print("======================== ASSET LATEST RESOLVED") +# print_json(get_latest_asset_result) +# divider() -get_first_state_by_hash = dkg.asset.get( - create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" -) -print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") -print_json(get_first_state_by_hash) -divider() +# get_latest_finalized_asset_result = dkg.asset.get( +# create_asset_result["UAL"], "latest_finalized", "all" +# ) +# print("======================== ASSET LATEST FINALIZED RESOLVED") +# print_json(get_latest_finalized_asset_result) +# divider() -query_result = dkg.graph.query( - "construct { ?s ?p ?o } where { ?s ?p ?o . ?p ?o }", "privateCurrent" +get_v8_test = dkg.asset.get_v8( + "did:dkg:base:84532/0xd5550173b0f7b8766ab2770e4ba86caf714a5af5/10176" ) -print("======================== QUERY LOCAL CURRENT RESULT") -print(query_result) +print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") +print(get_v8_test) +# print_json(get_v8_test) +divider() + +# get_first_state_by_hash = dkg.asset.get( +# create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" +# ) +# print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") +# print_json(get_first_state_by_hash) +# divider() + +# query_result = dkg.graph.query( +# "construct { ?s ?p ?o } where { ?s ?p ?o . ?p ?o }", "privateCurrent" +# ) +# print("======================== QUERY LOCAL CURRENT RESULT") +# print(query_result) From 87657df982d2f3dc8defa27dbf9f1119f5abbd86 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 15:48:37 +0100 Subject: [PATCH 032/146] Update abi --- dkg/data/interfaces/KnowledgeCollection.json | 610 +++++ .../KnowledgeCollectionStorage.json | 2312 +++++++++++++++++ 2 files changed, 2922 insertions(+) create mode 100644 dkg/data/interfaces/KnowledgeCollection.json create mode 100644 dkg/data/interfaces/KnowledgeCollectionStorage.json diff --git a/dkg/data/interfaces/KnowledgeCollection.json b/dkg/data/interfaces/KnowledgeCollection.json new file mode 100644 index 0000000..3eaeebf --- /dev/null +++ b/dkg/data/interfaces/KnowledgeCollection.json @@ -0,0 +1,610 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "CannotUpdateImmutableKnowledgeCollection", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "vs", + "type": "bytes32" + } + ], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "expectedTokenAMount", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + } + ], + "name": "InvalidTokenAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentEpoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endEpoch", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requiredSignatures", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receivedSignatures", + "type": "uint256" + } + ], + "name": "MinSignaturesRequirementNotMet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "rAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vsAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "identityIdsAmount", + "type": "uint256" + } + ], + "name": "SignaturesSignersMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "SignerIsNotNodeOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "TooLowAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "TooLowBalance", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroTokenAmount", + "type": "error" + }, + { + "inputs": [], + "name": "askStorage", + "outputs": [ + { + "internalType": "contract AskStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chronos", + "outputs": [ + { + "internalType": "contract Chronos", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "publishOperationId", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetsAmount", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint40", + "name": "epochs", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isImmutable", + "type": "bool" + }, + { + "internalType": "address", + "name": "paymaster", + "type": "address" + }, + { + "internalType": "uint72", + "name": "publisherNodeIdentityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "publisherNodeR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "publisherNodeVS", + "type": "bytes32" + }, + { + "internalType": "uint72[]", + "name": "identityIds", + "type": "uint72[]" + }, + { + "internalType": "bytes32[]", + "name": "r", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "vs", + "type": "bytes32[]" + } + ], + "name": "createKnowledgeCollection", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "epochStorage", + "outputs": [ + { + "internalType": "contract EpochStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint40", + "name": "epochs", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "address", + "name": "paymaster", + "type": "address" + } + ], + "name": "extendKnowledgeCollectionLifetime", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "identityStorage", + "outputs": [ + { + "internalType": "contract IdentityStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "address", + "name": "paymaster", + "type": "address" + } + ], + "name": "increaseKnowledgeCollectionTokenAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "knowledgeCollectionStorage", + "outputs": [ + { + "internalType": "contract KnowledgeCollectionStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "parametersStorage", + "outputs": [ + { + "internalType": "contract ParametersStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paymasterManager", + "outputs": [ + { + "internalType": "contract PaymasterManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_status", + "type": "bool" + } + ], + "name": "setStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shardingTableStorage", + "outputs": [ + { + "internalType": "contract ShardingTableStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenContract", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "string", + "name": "updateOperationId", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "mintKnowledgeAssetsAmount", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "knowledgeAssetsToBurn", + "type": "uint256[]" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "address", + "name": "paymaster", + "type": "address" + }, + { + "internalType": "uint72", + "name": "publisherNodeIdentityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "publisherNodeR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "publisherNodeVS", + "type": "bytes32" + }, + { + "internalType": "uint72[]", + "name": "identityIds", + "type": "uint72[]" + }, + { + "internalType": "bytes32[]", + "name": "r", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "vs", + "type": "bytes32[]" + } + ], + "name": "updateKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/dkg/data/interfaces/KnowledgeCollectionStorage.json b/dkg/data/interfaces/KnowledgeCollectionStorage.json new file mode 100644 index 0000000..7940b0f --- /dev/null +++ b/dkg/data/interfaces/KnowledgeCollectionStorage.json @@ -0,0 +1,2312 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_knowledgeCollectionMaxSize", + "type": "uint256" + }, + { + "internalType": "string", + "name": "uri", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ApprovalCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceQueryForZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "BurnFromNonOnwerAddress", + "type": "error" + }, + { + "inputs": [], + "name": "BurnFromZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "custodian", + "type": "address" + } + ], + "name": "CustodianHasNoOwners", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "custodian", + "type": "address" + } + ], + "name": "CustodianNotAContract", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "custodian", + "type": "address" + } + ], + "name": "CustodianWithoutOwnersFunction", + "type": "error" + }, + { + "inputs": [], + "name": "EtherTransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSize", + "type": "uint256" + } + ], + "name": "ExceededKnowledgeCollectionMaxSize", + "type": "error" + }, + { + "inputs": [], + "name": "InputLengthMistmatch", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidQueryRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenContractAddress", + "type": "address" + } + ], + "name": "InvalidTokenContract", + "type": "error" + }, + { + "inputs": [], + "name": "MintToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintZeroQuantity", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NotPartOfKnowledgeCollection", + "type": "error" + }, + { + "inputs": [], + "name": "TokenTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "TransferCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFromIncorrectOwnerOrInvalidAmount", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToNonERC1155ReceiverImplementer", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressCustodian", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "KnowledgeAssetsBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endId", + "type": "uint256" + } + ], + "name": "KnowledgeAssetsMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "burned", + "type": "uint256[]" + } + ], + "name": "KnowledgeCollectionBurnedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "byteSize", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionByteSizeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chunksAmount", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionChunksAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "publishOperationId", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "indexed": false, + "internalType": "uint40", + "name": "startEpoch", + "type": "uint40" + }, + { + "indexed": false, + "internalType": "uint40", + "name": "endEpoch", + "type": "uint40" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isImmutable", + "type": "bool" + } + ], + "name": "KnowledgeCollectionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endEpoch", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionEndEpochUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + } + ], + "name": "KnowledgeCollectionMerkleRootAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + } + ], + "name": "KnowledgeCollectionMerkleRootRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct KnowledgeCollectionLib.MerkleRoot[]", + "name": "merkleRoots", + "type": "tuple[]" + } + ], + "name": "KnowledgeCollectionMerkleRootsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minted", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionMintedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "publisher", + "type": "address" + } + ], + "name": "KnowledgeCollectionPublisherUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startEpoch", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionStartEpochUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionTokenAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "updateOperationId", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "byteSize", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + } + ], + "name": "KnowledgeCollectionUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "custodian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "tokenContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MisplacedERC20Withdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "custodian", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MisplacedEtherWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "custodian", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "newURI", + "type": "string" + } + ], + "name": "URIUpdate", + "type": "event" + }, + { + "inputs": [], + "name": "KNOWLEDGE_COLLECTION_MAX_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stop", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "burnKnowledgeAssetsTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "string", + "name": "publishOperationId", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetsAmount", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint40", + "name": "startEpoch", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "endEpoch", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isImmutable", + "type": "bool" + } + ], + "name": "createKnowledgeCollection", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBurned", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBurnedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getByteSize", + "outputs": [ + { + "internalType": "uint88", + "name": "", + "type": "uint88" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getEndEpoch", + "outputs": [ + { + "internalType": "uint40", + "name": "", + "type": "uint40" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getKnowledgeAssetsAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getKnowledgeAssetsRange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getKnowledgeCollection", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot[]", + "name": "merkleRoots", + "type": "tuple[]" + }, + { + "internalType": "uint256[]", + "name": "burned", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "minted", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint40", + "name": "startEpoch", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "endEpoch", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isImmutable", + "type": "bool" + } + ], + "internalType": "struct KnowledgeCollectionLib.KnowledgeCollection", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getKnowledgeCollectionId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getKnowledgeCollectionMetadata", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot[]", + "name": "", + "type": "tuple[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "", + "type": "uint88" + }, + { + "internalType": "uint40", + "name": "", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLatestKnowledgeCollectionId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getLatestMerkleRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getLatestMerkleRootObject", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getLatestMerkleRootPublisher", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getLatestMerkleRootTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getMerkleRootByIndex", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getMerkleRootObjectByIndex", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getMerkleRootPublisherByIndex", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getMerkleRootTimestampByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMerkleRoots", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getStartEpoch", + "outputs": [ + { + "internalType": "uint40", + "name": "", + "type": "uint40" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getTokenAmount", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalTokenAmount", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "isKnowledgeAssetBurned", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "isKnowledgeCollectionOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "isOwnerOf", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "isPartOfKnowledgeCollection", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "knowledgeCollectionMaxSize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "knowledgeCollections", + "outputs": [ + { + "internalType": "uint256", + "name": "minted", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint40", + "name": "startEpoch", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "endEpoch", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isImmutable", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mintKnowledgeAssetsTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "popMerkleRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + } + ], + "name": "pushMerkleRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_burned", + "type": "uint256[]" + } + ], + "name": "setBurned", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "_byteSize", + "type": "uint88" + } + ], + "name": "setByteSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint40", + "name": "_endEpoch", + "type": "uint40" + } + ], + "name": "setEndEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot[]", + "name": "_merkleRoots", + "type": "tuple[]" + } + ], + "name": "setMerkleRoots", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minted", + "type": "uint256" + } + ], + "name": "setMinted", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint40", + "name": "_startEpoch", + "type": "uint40" + } + ], + "name": "setStartEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "_tokenAmount", + "type": "uint96" + } + ], + "name": "setTokenAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "baseURI", + "type": "string" + } + ], + "name": "setURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenContract", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "tokensOfOwner", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stop", + "type": "uint256" + } + ], + "name": "tokensOfOwnerIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBurned", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "custodian", + "type": "address" + } + ], + "name": "transferTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "string", + "name": "updateOperationId", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "mintKnowledgeAssetsAmount", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "knowledgeAssetsToBurn", + "type": "uint256[]" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + } + ], + "name": "updateKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawMisplacedEther", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenContractAddress", + "type": "address" + } + ], + "name": "withdrawMisplacedTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] From 12aaeabbecd075c378e5c8c6ef18f645fbd80bc4 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 15:49:37 +0100 Subject: [PATCH 033/146] Update DefaultParameters --- dkg/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dkg/constants.py b/dkg/constants.py index 679a135..0d12f10 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -37,6 +37,8 @@ class DefaultParameters(Enum): MAX_NUMBER_OF_RETRIES: int = 5 FREQUENCY: int = 5 + IMMUTABLE: bool = False + ZERO_ADDRESS: str = "0x0000000000000000000000000000000000000000" BLOCKCHAINS = { From b66ec2057d9c0389964dbbe9f9a58da2f03a926b Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 15:51:57 +0100 Subject: [PATCH 034/146] Create kc and ka tools --- dkg/utils/knowledge_asset_tools.py | 5 + dkg/utils/knowledge_collection_tools.py | 236 ++++++++++++++++++++++++ dkg/utils/rdf.py | 199 +------------------- 3 files changed, 246 insertions(+), 194 deletions(-) create mode 100644 dkg/utils/knowledge_asset_tools.py create mode 100644 dkg/utils/knowledge_collection_tools.py diff --git a/dkg/utils/knowledge_asset_tools.py b/dkg/utils/knowledge_asset_tools.py new file mode 100644 index 0000000..2c2ac14 --- /dev/null +++ b/dkg/utils/knowledge_asset_tools.py @@ -0,0 +1,5 @@ +from uuid import uuid4 + + +def generate_named_node(): + return f"uuid:{uuid4()}" diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py new file mode 100644 index 0000000..6c5ad4f --- /dev/null +++ b/dkg/utils/knowledge_collection_tools.py @@ -0,0 +1,236 @@ +from typing import Literal +from dkg.constants import CHUNK_BYTE_SIZE +from dkg.exceptions import DatasetInputFormatNotSupported, InvalidDataset +from dkg.types import JSONLD, NQuads +from pyld import jsonld +from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM +from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral +from uuid import uuid4 +from web3 import Web3 +import math + + +def normalize_dataset( + dataset: JSONLD | NQuads, + input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + output_format=DEFAULT_RDF_FORMAT, + algorithm=DEFAULT_CANON_ALGORITHM, +) -> NQuads: + normalization_options = { + "algorithm": algorithm, + "format": output_format, + } + + match input_format.lower(): + case "json-ld" | "jsonld": + pass + case "n-quads" | "nquads": + normalization_options["inputFormat"] = "application/n-quads" + case _: + raise DatasetInputFormatNotSupported( + f"Dataset input format isn't supported: {input_format}. " + "Supported formats: JSON-LD / N-Quads." + ) + + n_quads = jsonld.normalize(dataset, normalization_options) + assertion = [quad for quad in n_quads.split("\n") if quad] + + if not assertion: + raise InvalidDataset("Invalid dataset, no quads were extracted.") + + return assertion + + +def is_empty_dict(dictionary: dict): + return len(dictionary.keys()) == 0 and isinstance(dictionary, dict) + + +def format_dataset( + content: dict, + input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + output_format=DEFAULT_RDF_FORMAT, + algorithm=DEFAULT_CANON_ALGORITHM, +): + private_assertion = None + if content.get("private") and not is_empty_dict(content.get("private")): + private_assertion = normalize_dataset( + content.get("private"), input_format, output_format, algorithm + ) + elif not content.get("public"): + content = {"public": content} + + public_assertion = [] + if content.get("public"): + public_assertion = normalize_dataset( + content.get("public"), input_format, output_format, algorithm + ) + + if ( + public_assertion + and len(public_assertion) == 0 + and private_assertion + and len(private_assertion) == 0 + ): + raise ValueError("File format is corrupted, no n-quads are extracted.") + + dataset = {"public": public_assertion} + if private_assertion: + dataset["private"] = private_assertion + + return dataset + + +def split_into_chunks(quads, chunk_size_bytes=32): + # Concatenate the quads with newline characters + concatenated_quads = "\n".join(quads) + + # Encode the concatenated string to bytes + encoded_bytes = concatenated_quads.encode("utf-8") + + # Split the encoded bytes into chunks + chunks = [] + start = 0 + + while start < len(encoded_bytes): + end = min(start + chunk_size_bytes, len(encoded_bytes)) + chunk = encoded_bytes[start:end] + chunks.append(chunk.decode("utf-8")) # Decode bytes back to string + start = end + + return chunks + + +def calculate_merkle_root(quads: list[str], chunk_size_bytes: int = CHUNK_BYTE_SIZE): + chunks = split_into_chunks(quads, chunk_size_bytes) + + # Create leaves using solidityKeccak256 equivalent + leaves = [ + bytes.fromhex(Web3.solidity_keccak(["string", "uint256"], [chunk, index]).hex()) + for index, chunk in enumerate(chunks) + ] + + while len(leaves) > 1: + next_level = [] + + for i in range(0, len(leaves), 2): + left = leaves[i] + + if i + 1 >= len(leaves): + next_level.append(left) + break + + right = leaves[i + 1] + + # Combine and sort the leaves + combined = [left, right] + combined.sort() + + # Calculate the hash of the combined leaves + hash_value = Web3.keccak(b"".join(combined)) + next_level.append(hash_value) + + leaves = next_level + + return f"0x{leaves[0].hex()}" + + +def generate_missing_ids_for_blank_nodes(nquads_list: list[str] | None) -> list[str]: + if not nquads_list: + return [""] + + generated_ids = {} + + def replace_blank_node(term): + # Handle blank nodes + if isinstance(term, BNode): + if str(term) not in generated_ids: + generated_ids[str(term)] = URIRef(f"uuid:{str(uuid4())}") + return generated_ids[str(term)] + + return term # Return IRIs or Literals unchanged + + # Create a temporary graph for parsing individual quads + result = [] + + # Process each N-Quad string individually to maintain order + for nquad in nquads_list: + if not nquad.strip(): + continue + + # Parse single N-Quad + g = Graph() + g.parse(data=nquad, format="nquads") + + # Get the triple and replace blank nodes + for s, p, o in g: + updated_quad = ( + replace_blank_node(s), + replace_blank_node(p), + replace_blank_node(o), + ) + # Format as N-Quad string + result.append( + f"{updated_quad[0].n3()} {updated_quad[1].n3()} {updated_quad[2].n3()} ." + ) + + return result + + +def group_nquads_by_subject(nquads_list: list[str], sort: bool = False): + grouped = {} + + # Process each quad in original order + for nquad in nquads_list: + if not nquad.strip(): # Skip empty lines + continue + + # Parse single quad + g = Graph() + g.parse(data=nquad, format="nquads") + quad = next(iter(g)) + subject, predicate, obj = quad + + # Get subject key + subject_key = ( + f"<<<{subject.subject}> <{subject.predicate}> <{subject.object}>>" + if hasattr(subject, "subject") + else f"<{subject}>" + ) + + # Initialize group if needed + if subject_key not in grouped: + grouped[subject_key] = [] + + # Format object + object_value = f'"{obj}"' if isinstance(obj, RDFLiteral) else f"<{obj}>" + + # Add quad to group + quad_string = f"{subject_key} <{predicate}> {object_value} ." + grouped[subject_key].append(quad_string) + + # Return grouped quads (sorted if requested) + grouped_items = sorted(grouped.items()) if sort else grouped.items() + return [quads for _, quads in grouped_items] + + +def calculate_number_of_chunks(quads, chunk_size_bytes=CHUNK_BYTE_SIZE): + # Concatenate the quads with newline characters + concatenated_quads = "\n".join(quads) + + total_size_bytes = len(concatenated_quads.encode("utf-8")) + + # Calculate and return the number of chunks + return math.ceil(total_size_bytes / chunk_size_bytes) + + +def count_distinct_subjects(nquads_list: list[str]) -> int: + # Create a new RDF graph + graph = Graph() + + # Parse the joined N-Quads + graph.parse(data="\n".join(nquads_list), format="nquads") + + # Extract unique subjects using set comprehension + subjects = {str(quad[0]) for quad in graph} + + return len(subjects) diff --git a/dkg/utils/rdf.py b/dkg/utils/rdf.py index 06eced2..b01548b 100644 --- a/dkg/utils/rdf.py +++ b/dkg/utils/rdf.py @@ -17,19 +17,15 @@ from typing import Literal -from rdflib.plugins.parsers.nquads import NQuadsParser -from io import StringIO - -from dkg.constants import CHUNK_BYTE_SIZE, PRIVATE_ASSERTION_PREDICATE +from dkg.constants import ( + PRIVATE_ASSERTION_PREDICATE, + DEFAULT_RDF_FORMAT, + DEFAULT_CANON_ALGORITHM, +) from dkg.exceptions import DatasetInputFormatNotSupported, InvalidDataset from dkg.types import JSONLD, HexStr, NQuads from dkg.utils.merkle import MerkleTree, hash_assertion_with_indexes from pyld import jsonld -from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM -from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral -from uuid import uuid4 -from web3 import Web3 -import math def normalize_dataset( @@ -89,188 +85,3 @@ def format_content( "public": public_assertion, "private": private_assertion if content.get("private", None) else {}, } - - -def is_empty_dict(dictionary: dict): - return len(dictionary.keys()) == 0 and isinstance(dictionary, dict) - - -def format_dataset( - content: dict, - input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - output_format=DEFAULT_RDF_FORMAT, - algorithm=DEFAULT_CANON_ALGORITHM, -): - private_assertion = None - if content.get("private") and not is_empty_dict(content.get("private")): - private_assertion = normalize_dataset( - content.get("private"), input_format, output_format, algorithm - ) - elif not content.get("public"): - content = {"public": content} - - public_assertion = [] - if content.get("public"): - public_assertion = normalize_dataset( - content.get("public"), input_format, output_format, algorithm - ) - - if ( - public_assertion - and len(public_assertion) == 0 - and private_assertion - and len(private_assertion) == 0 - ): - raise ValueError("File format is corrupted, no n-quads are extracted.") - - dataset = {"public": public_assertion} - if private_assertion: - dataset["private"] = private_assertion - - return dataset - - -def generate_missing_ids_for_blank_nodes(nquads_list: list[str]) -> list[str]: - generated_ids = {} - - def replace_blank_node(term): - # Handle blank nodes - if isinstance(term, BNode): - if str(term) not in generated_ids: - generated_ids[str(term)] = URIRef(f"uuid:{str(uuid4())}") - return generated_ids[str(term)] - - # Handle nested quads (RDF-star) - if hasattr(term, "subject"): # Check if term is a quad - return Graph().quad( - replace_blank_node(term.subject), - replace_blank_node(term.predicate), - replace_blank_node(term.object), - ) - - return term # Return IRIs or Literals unchanged - - # Create a graph and parse the N-Quads - g = Graph() - g.parse(data="".join(nquads_list)) - - # Create new graph for updated quads - updated_graph = Graph() - - # Process each quad and replace blank nodes - for quad in g: - updated_quad = ( - replace_blank_node(quad[0]), # subject - replace_blank_node(quad[1]), # predicate - replace_blank_node(quad[2]), # object - ) - updated_graph.add(updated_quad) - - # Serialize back to N-Quads format and split into lines - result = updated_graph.serialize(format="nquads").strip().split("\n") - return [line for line in result if line] # Remove empty - - -def group_nquads_by_subject(nquads_list: list[str], sort: bool = False): - grouped = {} - - # Process each quad in original order - for nquad in nquads_list: - if not nquad.strip(): # Skip empty lines - continue - - # Parse single quad - g = Graph() - g.parse(data=nquad, format="nquads") - quad = next(iter(g)) - subject, predicate, obj = quad - - # Get subject key - subject_key = ( - f"<<<{subject.subject}> <{subject.predicate}> <{subject.object}>>" - if hasattr(subject, "subject") - else f"<{subject}>" - ) - - # Initialize group if needed - if subject_key not in grouped: - grouped[subject_key] = [] - - # Format object - object_value = f'"{obj}"' if isinstance(obj, RDFLiteral) else f"<{obj}>" - - # Add quad to group - quad_string = f"{subject_key} <{predicate}> {object_value} ." - grouped[subject_key].append(quad_string) - - # Return grouped quads (sorted if requested) - grouped_items = sorted(grouped.items()) if sort else grouped.items() - return [quads for _, quads in grouped_items] - - -def split_into_chunks(quads, chunk_size_bytes=32): - # Concatenate the quads with newline characters - concatenated_quads = "\n".join(quads) - - # Encode the concatenated string to bytes - encoded_bytes = concatenated_quads.encode("utf-8") - - # Split the encoded bytes into chunks - chunks = [] - start = 0 - - while start < len(encoded_bytes): - end = min(start + chunk_size_bytes, len(encoded_bytes)) - chunk = encoded_bytes[start:end] - chunks.append(chunk.decode("utf-8")) # Decode bytes back to string - start = end - - return chunks - - -def calculate_merkle_root(quads: list[str], chunk_size_bytes: int = CHUNK_BYTE_SIZE): - chunks = split_into_chunks(quads, chunk_size_bytes) - - # Create leaves using solidityKeccak256 equivalent - leaves = [ - bytes.fromhex(Web3.solidity_keccak(["string", "uint256"], [chunk, index]).hex()) - for index, chunk in enumerate(chunks) - ] - - while len(leaves) > 1: - next_level = [] - - for i in range(0, len(leaves), 2): - left = leaves[i] - - if i + 1 >= len(leaves): - next_level.append(left) - break - - right = leaves[i + 1] - - # Combine and sort the leaves - combined = [left, right] - combined.sort() - - # Calculate the hash of the combined leaves - hash_value = Web3.keccak(b"".join(combined)) - next_level.append(hash_value) - - leaves = next_level - - return f"0x{leaves[0].hex()}" - - -def generate_named_node(): - return f"uuid:{uuid4()}" - - -def calculate_number_of_chunks(quads, chunk_size_bytes=CHUNK_BYTE_SIZE): - # Concatenate the quads with newline characters - concatenated_quads = "\n".join(quads) - - total_size_bytes = len(concatenated_quads.encode("utf-8")) - - # Calculate and return the number of chunks - return math.ceil(total_size_bytes / chunk_size_bytes) From fb35143900a151bf01b720bf399255a2274f55c7 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 15:54:28 +0100 Subject: [PATCH 035/146] Finish v8 create --- dkg/asset.py | 330 +++++++++++++++++++++++++++----- dkg/providers/node_http.py | 2 +- dkg/utils/blockchain_request.py | 69 ++++++- dkg/utils/node_request.py | 7 + 4 files changed, 362 insertions(+), 46 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 61cf419..1a0fff3 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -16,11 +16,11 @@ # under the License. import json +import time import math import re import hashlib -from typing import Literal, Type - +from typing import Literal, Type, Dict, Optional, Any from pyld import jsonld from web3 import Web3 from web3.constants import ADDRESS_ZERO @@ -30,6 +30,7 @@ from eth_abi.packed import encode_packed from eth_account.messages import encode_defunct from eth_account import Account +from hexbytes import HexBytes from dkg.constants import ( DEFAULT_HASH_FUNCTION_ID, @@ -62,7 +63,11 @@ from dkg.method import Method from dkg.module import Module from dkg.types import JSONLD, UAL, Address, AgreementData, HexStr, Wei -from dkg.utils.blockchain_request import BlockchainRequest +from dkg.utils.blockchain_request import ( + BlockchainRequest, + KnowledgeCollectionResult, + AllowanceResult, +) from dkg.utils.decorators import retry from dkg.utils.merkle import MerkleTree, hash_assertion_with_indexes from dkg.utils.metadata import ( @@ -79,14 +84,10 @@ from dkg.utils.rdf import ( format_content, normalize_dataset, - format_dataset, - generate_missing_ids_for_blank_nodes, - group_nquads_by_subject, - generate_named_node, - calculate_merkle_root, - calculate_number_of_chunks, ) from dkg.utils.ual import format_ual, parse_ual +import dkg.utils.knowledge_collection_tools as kc_tools +import dkg.utils.knowledge_asset_tools as ka_tools class KnowledgeAsset(Module): @@ -218,10 +219,181 @@ def decrease_allowance( _create = Method(BlockchainRequest.create_asset) _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) - + _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) + _epoch_length = Method(BlockchainRequest.epoch_length) + _get_stake_weighted_average_ask = Method( + BlockchainRequest.get_stake_weighted_average_ask + ) _get_bid_suggestion = Method(NodeRequest.bid_suggestion) _local_store = Method(NodeRequest.local_store) _publish = Method(NodeRequest.publish) + _finality_status = Method(NodeRequest.finality_status) + + _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) + _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + _decrease_allowance = Method(BlockchainRequest.decrease_allowance) + + def get_operation_status_object( + self, operation_result: Dict[str, Any], operation_id: str + ) -> Dict[str, Any]: + """ + Creates an operation status object from operation result and ID. + + Args: + operation_result: Dictionary containing operation result data + operation_id: The ID of the operation + + Returns: + Dictionary containing operation status information + """ + # Check if error_type exists in operation_result.data + operation_data = ( + {"status": operation_result.get("status"), **operation_result.get("data")} + if operation_result.get("data", {}).get("errorType") + else {"status": operation_result.get("status")} + ) + + return {"operationId": operation_id, **operation_data} + + def finality_status( + self, + ual: str, + required_confirmations: int, + max_number_of_retries: int, + frequency: int, + ): + retries = 0 + finality = 0 + + while finality < required_confirmations and retries <= max_number_of_retries: + if retries > max_number_of_retries: + raise Exception( + f"Unable to achieve required confirmations. " + f"Max number of retries ({max_number_of_retries}) reached." + ) + + retries += 1 + + # Sleep between attempts (except for first try) + if retries > 1: + time.sleep(frequency) + + try: + response = self._finality_status(ual) + finality = response.get("finality", 0) + except Exception: + finality = 0 + + return finality + + def increase_knowledge_collection_allowance( + self, sender: str, token_amount: str + ) -> AllowanceResult: + """ + Increases the allowance for knowledge collection if necessary. + + Args: + sender: The address of the sender + token_amount: The amount of tokens to check/increase allowance for + + Returns: + AllowanceResult containing whether allowance was increased and the gap + """ + knowledge_collection_address = self._get_contract_address("KnowledgeCollection") + + allowance = self._get_current_allowance(sender, knowledge_collection_address) + allowance_gap = int(token_amount) - int(allowance) + + if allowance_gap > 0: + self._increase_allowance(knowledge_collection_address, allowance_gap) + + return AllowanceResult( + allowance_increased=True, allowance_gap=allowance_gap + ) + + return AllowanceResult(allowance_increased=False, allowance_gap=allowance_gap) + + def create_knowledge_collection( + self, + request: dict, + paranet_ka_contract: Optional[Address] = None, + paranet_token_id: Optional[int] = None, + ) -> KnowledgeCollectionResult: + """ + Creates a knowledge collection on the blockchain. + + Args: + request: dict containing all collection parameters + paranet_ka_contract: Optional paranet contract address + paranet_token_id: Optional paranet token ID + blockchain: Blockchain configuration + + Returns: + KnowledgeCollectionResult containing collection ID and transaction receipt + + Raises: + BlockchainError: If the collection creation fails + """ + sender = self.manager.blockchain_provider.account.address + service_agreement_v1_address = None + allowance_increased = False + allowance_gap = 0 + + try: + # Handle allowance + if request.get("payer"): + pass + else: + allowance_result = self.increase_knowledge_collection_allowance( + sender=sender, + token_amount=request.get("tokenAmount"), + ) + allowance_increased = allowance_result.allowance_increased + allowance_gap = allowance_result.allowance_gap + + if not paranet_ka_contract and not paranet_token_id: + receipt = self._create_knowledge_collection( + request.get("publishOperationId"), + Web3.to_bytes(hexstr=request.get("merkleRoot")), + request.get("knowledgeAssetsAmount"), + request.get("byteSize"), + request.get("epochs"), + int(request.get("tokenAmount")), + request.get("isImmutable"), + request.get("paymaster"), + request.get("publisherNodeIdentityId"), + Web3.to_bytes(hexstr=request.get("publisherNodeR")), + Web3.to_bytes(hexstr=request.get("publisherNodeVS")), + request.get("identityIds"), + [Web3.to_bytes(hexstr=x) for x in request.get("r")], + [Web3.to_bytes(hexstr=x) for x in request.get("vs")], + ) + else: + receipt = self._mint_knowledge_asset( + paranet_ka_contract, + paranet_token_id, + list(request.values()), + ) + + event_data = self.manager.blockchain_provider.decode_logs_event( + receipt=receipt, + contract_name="KnowledgeCollectionStorage", + event_name="KnowledgeCollectionCreated", + ) + collection_id = ( + int(getattr(event_data[0].get("args", {}), "id", None)) + if event_data + else None + ) + + return KnowledgeCollectionResult( + knowledge_collection_id=collection_id, receipt=receipt + ) + + except Exception as e: + if allowance_increased: + self._decrease_allowance(service_agreement_v1_address, allowance_gap) + raise e def process_content(self, content: str) -> list: return [line.strip() for line in content.split("\n") if line.strip() != ""] @@ -263,7 +435,7 @@ def get_operation_status_dict(self, operation_result, operation_id): return {"operationId": operation_id, **operation_data} def get_message_signer_address(self, dataset_root: str, signature: dict): - message = encode_defunct(Web3.to_bytes(dataset_root)) + message = encode_defunct(HexBytes(dataset_root)) r, s, v = signature.get("r"), signature.get("s"), signature.get("v") r = r[2:] if r.startswith("0x") else r s = s[2:] if s.startswith("0x") else s @@ -275,7 +447,7 @@ def get_message_signer_address(self, dataset_root: str, signature: dict): def create( self, content: dict[Literal["public", "private"], JSONLD], - epochs_number: int, + epochs_num: int, minimum_number_of_finalization_confirmations: int, minimum_number_of_node_replications: int, token_amount: Wei | None = None, @@ -301,34 +473,34 @@ def create( if private_content and isinstance(private_content, str): dataset["private"] = self.process_content(private_content) else: - dataset = format_dataset(content) + dataset = kc_tools.format_dataset(content) public_triples_grouped = [] - # TODO: Uncomment and test this - # dataset["public"] = generate_missing_ids_for_blank_nodes(dataset.get("public")) + dataset["public"] = kc_tools.generate_missing_ids_for_blank_nodes( + dataset.get("public") + ) if dataset.get("private") and len(dataset.get("private")): - # TODO: Uncomment and test this - # dataset["private"] = generate_missing_ids_for_blank_nodes( - # dataset.get("private") - # ) + dataset["private"] = kc_tools.generate_missing_ids_for_blank_nodes( + dataset.get("private") + ) # Group private triples by subject and flatten - private_triples_grouped = group_nquads_by_subject( + private_triples_grouped = kc_tools.group_nquads_by_subject( dataset.get("private"), True ) dataset["private"] = list(chain.from_iterable(private_triples_grouped)) # Compute private root and add to public - private_root = calculate_merkle_root(dataset.get("private")) + private_root = kc_tools.calculate_merkle_root(dataset.get("private")) dataset["public"].append( - f'<{generate_named_node()}> <${PRIVATE_ASSERTION_PREDICATE}> "{private_root}" .' + f'<{ka_tools.generate_named_node()}> <{PRIVATE_ASSERTION_PREDICATE}> "{private_root}" .' ) # Compute private root and add to public - public_triples_grouped = group_nquads_by_subject( + public_triples_grouped = kc_tools.group_nquads_by_subject( dataset.get("public"), True ) @@ -355,17 +527,16 @@ def create( private_subject in public_subject_dict ): # Check if there's a public pair # If there's a public pair, insert a representation in that group - # TODO: Test this public_index = public_subject_dict.get(private_subject) self.insert_triple_sorted( - public_triples_grouped.get(public_index), - f"{private_subject} <{PRIVATE_RESOURCE_PREDICATE}> <{generate_named_node()}> .", + public_triples_grouped[public_index], + f"{private_subject} <{PRIVATE_RESOURCE_PREDICATE}> <{ka_tools.generate_named_node()}> .", ) else: # If no public pair, maintain separate list, inserting sorted by hash self.insert_triple_sorted( private_triple_subject_hashes_grouped_without_public_pair, - f"<{PRIVATE_HASH_SUBJECT_PREFIX}{private_subject_hash}> <{PRIVATE_RESOURCE_PREDICATE}> <{generate_named_node()}> .", + f"<{PRIVATE_HASH_SUBJECT_PREFIX}{private_subject_hash}> <{PRIVATE_RESOURCE_PREDICATE}> <{ka_tools.generate_named_node()}> .", ) for triple in private_triple_subject_hashes_grouped_without_public_pair: @@ -373,26 +544,24 @@ def create( dataset["public"] = list(chain.from_iterable(public_triples_grouped)) else: - # TODO: Test this # No private triples, just group and flatten public - public_triples_grouped = group_nquads_by_subject( + public_triples_grouped = kc_tools.group_nquads_by_subject( dataset.get("public"), True ) dataset["public"] = list(chain.from_iterable(public_triples_grouped)) # Calculate the number of chunks - number_of_chunks = calculate_number_of_chunks( + number_of_chunks = kc_tools.calculate_number_of_chunks( dataset.get("public"), CHUNK_BYTE_SIZE ) dataset_size = number_of_chunks * CHUNK_BYTE_SIZE # Validate the assertion size in bytes - # TODO: Move into validation service once developed if dataset_size > MAX_FILE_SIZE: raise ValueError(f"File size limit is {MAX_FILE_SIZE / (1024 * 1024)}MB.") # Calculate the Merkle root - dataset_root = calculate_merkle_root(dataset.get("public")) + dataset_root = kc_tools.calculate_merkle_root(dataset.get("public")) # Get the contract address for KnowledgeCollectionStorage content_asset_storage_address = self._get_asset_storage_address( @@ -456,21 +625,94 @@ def create( except Exception: continue - # result["operation"]["publish"] = { - # "operationId": operation_id, - # "status": operation_result["status"], - # } + if token_amount: + estimated_publishing_cost = token_amount + else: + time_until_next_epoch = self._time_until_next_epoch() + epoch_length = self._epoch_length() + stake_weighted_average_ask = self._get_stake_weighted_average_ask() + + # Convert to integers and perform calculation + # Note: In Python we use regular int as it handles arbitrary precision automatically + estimated_publishing_cost = ( + ( + int(stake_weighted_average_ask) + * ( + int(epochs_num) * int(1e18) + + (int(time_until_next_epoch) * int(1e18)) / int(epoch_length) + ) + * int(dataset_size) + ) + / 1024 + / int(1e18) + ) + + knowledge_collection_id = None + mint_knowledge_asset_receipt = None + + knowledge_collection_result = self.create_knowledge_collection( + { + "publishOperationId": publish_operation_id, + "merkleRoot": dataset_root, + "knowledgeAssetsAmount": kc_tools.count_distinct_subjects( + dataset.get("public") + ), + "byteSize": dataset_size, + "epochs": epochs_num, + "tokenAmount": str(estimated_publishing_cost), + "isImmutable": DefaultParameters.IMMUTABLE.value, + "paymaster": DefaultParameters.ZERO_ADDRESS.value, + "publisherNodeIdentityId": publisher_node_identity_id, + "publisherNodeR": publisher_node_r, + "publisherNodeVS": publisher_node_vs, + "identityIds": identity_ids, + "r": r, + "vs": vs, + }, + None, + None, + ) + knowledge_collection_id = knowledge_collection_result.knowledge_collection_id + mint_knowledge_asset_receipt = knowledge_collection_result.receipt - # if operation_result["status"] == OperationStatus.COMPLETED: - # operation_id = self._local_store(assertions_list)["operationId"] - # operation_result = self.get_operation_result(operation_id, "local-store") + ual = format_ual( + blockchain_id, content_asset_storage_address, knowledge_collection_id + ) - # result["operation"]["localStore"] = { - # "operationId": operation_id, - # "status": operation_result["status"], - # } + finality_status_result = 0 + if minimum_number_of_finalization_confirmations > 0: + finality_status_result = self.finality_status( + ual, + minimum_number_of_finalization_confirmations, + 300, + 2, + ) - # return result + return json.loads( + Web3.to_json( + { + "UAL": ual, + "datasetRoot": dataset_root, + "signatures": publish_operation_result.get("data", {}).get( + "signatures" + ), + "operation": { + "mintKnowledgeAsset": mint_knowledge_asset_receipt, + "publish": self.get_operation_status_object( + publish_operation_result, publish_operation_id + ), + "finality": { + "status": "FINALIZED" + if finality_status_result + >= minimum_number_of_finalization_confirmations + else "NOT FINALIZED" + }, + "numberOfConfirmations": finality_status_result, + "requiredConfirmations": minimum_number_of_finalization_confirmations, + }, + } + ) + ) def local_store( self, diff --git a/dkg/providers/node_http.py b/dkg/providers/node_http.py index c096ca2..8316d6c 100644 --- a/dkg/providers/node_http.py +++ b/dkg/providers/node_http.py @@ -26,7 +26,7 @@ class NodeHTTPProvider: def __init__( - self, + self, endpoint_uri: URI | str, api_version: str = "v1", auth_token: str | None = None, diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index fc5b379..f351765 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -16,7 +16,7 @@ # under the License. from dataclasses import dataclass, field -from typing import Type +from typing import Type, Dict, Any from dkg.dataclasses import ParanetIncentivizationType from dkg.types import Address, HexStr, Wei @@ -52,6 +52,18 @@ class ContractCall(ContractInteraction): pass +@dataclass +class KnowledgeCollectionResult: + knowledge_collection_id: int + receipt: Dict[str, Any] + + +@dataclass +class AllowanceResult: + allowance_increased: bool + allowance_gap: int + + class BlockchainRequest: chain_id = JSONRPCRequest("chain_id") get_block = JSONRPCRequest("get_block", args={"block_identifier": str | int}) @@ -73,6 +85,24 @@ class BlockchainRequest: args={"identityId": int, "_key": Address, "_purpose": int}, ) + time_until_next_epoch = ContractCall( + contract="Chronos", + function="timeUntilNextEpoch", + args={}, + ) + + epoch_length = ContractCall( + contract="Chronos", + function="epochLength", + args={}, + ) + + get_stake_weighted_average_ask = ContractCall( + contract="AskStorage", + function="getStakeWeightedAverageAsk", + args={}, + ) + allowance = ContractCall( contract="Token", function="allowance", @@ -401,3 +431,40 @@ class BlockchainRequest: function="claimIncentivizationProposalVoterReward", args={}, ) + + create_knowledge_collection = ContractTransaction( + contract="KnowledgeCollection", + function="createKnowledgeCollection", + args={ + "publishOperationId": str, + "merkleRoot": bytes, + "knowledgeAssetsAmount": int, + "byteSize": int, + "epochs": int, + "tokenAmount": int, + "isImmutable": bool, + "paymaster": Address, + "publisherNodeIdentityId": int, + "publisherNodeR": bytes, + "publisherNodeVS": bytes, + "identityIds": list[int], + "r": list[bytes], + "vs": list[bytes], + }, + ) + + mint_knowledge_asset = ContractTransaction( + contract="Paranet", + function="mintKnowledgeAsset", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + "knowledgeAssetArgs": dict, + }, + ) + + decrease_allowance = ContractTransaction( + contract="Token", + function="decreaseAllowance", + args={"spender": Address, "subtractedValue": int}, + ) diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 340c650..ea90f36 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -68,6 +68,13 @@ class NodeRequest: "minimumNumberOfNodeReplications": int, }, ) + + finality_status = NodeCall( + method=HTTPRequestMethod.GET, + path="finality", + params={"ual": str}, + ) + get = NodeCall( method=HTTPRequestMethod.POST, path="get", From ba92b28f1599e8562a8924457f73f40920580a5f Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 15:57:52 +0100 Subject: [PATCH 036/146] Update demo --- examples/demo.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/demo.py b/examples/demo.py index 9bddbf9..61a3538 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -16,6 +16,7 @@ # under the License. import json +import time from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider @@ -130,8 +131,9 @@ def print_json(json_dict: dict): divider() +start_time = time.time() create_asset_result = dkg.asset.create(content, 2, 3, 1, "100") -print("======================== ASSET CREATED") +print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") print_json(create_asset_result) divider() From 54180e6a6263f838ef549d135877704ed9c2d729 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Wed, 8 Jan 2025 16:33:42 +0100 Subject: [PATCH 037/146] Added input service --- dkg/asset.py | 283 +++++----------------------------- dkg/constants.py | 48 +++--- dkg/main.py | 9 +- dkg/providers/node_http.py | 10 +- dkg/services/input_service.py | 162 +++++++++++++++++++ 5 files changed, 244 insertions(+), 268 deletions(-) create mode 100644 dkg/services/input_service.py diff --git a/dkg/asset.py b/dkg/asset.py index 35791a4..d1ead06 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -32,7 +32,6 @@ PRIVATE_ASSERTION_PREDICATE, PRIVATE_CURRENT_REPOSITORY, PRIVATE_HISTORICAL_REPOSITORY, - DEFAULT_PARAMETERS, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -71,8 +70,9 @@ class KnowledgeAsset(Module): - def __init__(self, manager: DefaultRequestManager): + def __init__(self, manager: DefaultRequestManager, input_service): self.manager = manager + self.input_service = input_service _owner = Method(BlockchainRequest.owner_of) @@ -562,20 +562,36 @@ def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: _get = Method(NodeRequest.get) _query = Method(NodeRequest.query) - def get_v8(self, ual: UAL) -> dict: + def get(self, ual: UAL, options=None) -> dict: + if options is None: + options = {} + + arguments = self.input_service.get_asset_get_arguments(options) + + max_number_of_retries = arguments["max_number_of_retries"] + frequency = arguments["frequency"] + state = arguments["state"] + include_metadata = arguments["include_metadata"] + content_type = arguments["content_type"] + validate = arguments["validate"] + output_format = arguments["output_format"] + auth_token = arguments["auth_token"] + hash_function_id = arguments["hash_function_id"] + paranet_ual = arguments["paranet_ual"] + subject_ual = arguments["subject_ual"] + + id_field = f"{ual}:{state}" if state else ual get_public_operation_id: NodeResponseDict = self._get( - ual, - DEFAULT_PARAMETERS["CONTENT_TYPE"], - DEFAULT_PARAMETERS["INCLUDE_METADATA"], - DEFAULT_PARAMETERS["HASH_FUNCTION_ID"], - DEFAULT_PARAMETERS["PARANET_UAL"], - DEFAULT_PARAMETERS["GET_SUBJECT_UAL"], + id_field, + content_type, + include_metadata, + hash_function_id, + paranet_ual, + subject_ual, )["operationId"] get_public_operation_result = self.get_operation_result( - get_public_operation_id, - "get", - DEFAULT_PARAMETERS["MAX_NUMBER_OF_RETRIES"], + get_public_operation_id, "get", max_number_of_retries, frequency ) def get_operation_status_object(self, operation_result, operation_id): @@ -592,7 +608,7 @@ def get_operation_status_object(self, operation_result, operation_id): return {"operationId": operation_id, **operation_data} - if DEFAULT_PARAMETERS["GET_SUBJECT_UAL"]: + if subject_ual: if get_public_operation_result["data"]: return { "operation": { @@ -635,7 +651,7 @@ def get_operation_status_object(self, operation_result, operation_id): }, } - if DEFAULT_PARAMETERS["GET_SUBJECT_UAL"]: + if validate: is_valid = True # #TODO: Implement assertion validation logic if not is_valid: get_public_operation_result["data"] = { @@ -648,18 +664,17 @@ def get_operation_status_object(self, operation_result, operation_id): ) formatted_metadata = None - if DEFAULT_PARAMETERS["OUTPUT_FORMAT"] == "JSON-LD": + if output_format == "JSON-LD": formatted_assertion = self.to_jsonld(formatted_assertion) - if DEFAULT_PARAMETERS["INCLUDE_METADATA"]: - print("USAO") + if include_metadata: formatted_metadata = self.to_jsonld("\n".join(metadata)) - if DEFAULT_PARAMETERS["OUTPUT_FORMAT"] == "N-QUADS": + if output_format == "N-QUADS": formatted_assertion = self.to_nquads( formatted_assertion, "application/n-quads" ) - if DEFAULT_PARAMETERS["INCLUDE_METADATA"]: + if include_metadata: formatted_metadata = self.to_nquads( "\n".join(metadata), "application/n-quads" ) @@ -673,231 +688,11 @@ def get_operation_status_object(self, operation_result, operation_id): }, } - if DEFAULT_PARAMETERS["INCLUDE_METADATA"] and metadata: + if include_metadata and metadata: result["metadata"] = formatted_metadata return result - def get( - self, - ual: UAL, - state: str | HexStr | int = KnowledgeAssetEnumStates.LATEST, - content_visibility: str = KnowledgeAssetContentVisibility.ALL, - output_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - validate: bool = True, - ) -> dict[str, UAL | HexStr | list[JSONLD] | dict[str, str]]: - state = ( - state.upper() - if (isinstance(state, str) and not re.match(r"^0x[a-fA-F0-9]{64}$", state)) - else state - ) - content_visibility = content_visibility.upper() - output_format = output_format.upper() - - token_id = parse_ual(ual)["token_id"] - - def handle_latest_finalized_state(token_id: int) -> tuple[HexStr, bool]: - return Web3.to_hex(self._get_latest_assertion_id(token_id)), True - - is_state_finalized = False - - match state: - case ( - KnowledgeAssetEnumStates.LATEST - | KnowledgeAssetEnumStates.LATEST_FINALIZED - ): - public_assertion_id, is_state_finalized = handle_latest_finalized_state( - token_id - ) - - case _ if isinstance(state, int): - assertion_ids = [ - Web3.to_hex(assertion_id) - for assertion_id in self._get_assertion_ids(token_id) - ] - if 0 <= state < (states_number := len(assertion_ids)): - public_assertion_id = assertion_ids[state] - - if state == states_number - 1: - is_state_finalized = True - else: - raise InvalidStateOption(f"State index {state} is out of range.") - - case _ if isinstance(state, str) and re.match( - r"^0x[a-fA-F0-9]{64}$", state - ): - assertion_ids = [ - Web3.to_hex(assertion_id) - for assertion_id in self._get_assertion_ids(token_id) - ] - - if state in assertion_ids: - public_assertion_id = state - - if state == assertion_ids[-1]: - is_state_finalized = True - else: - raise InvalidStateOption( - f"Given state hash: {state} is not a part of the KA." - ) - - case _: - raise InvalidStateOption(f"Invalid state option: {state}.") - - get_public_operation_id: NodeResponseDict = self._get( - ual, public_assertion_id, hashFunctionId=1 - )["operationId"] - - get_public_operation_result = self.get_operation_result( - get_public_operation_id, "get" - ) - public_assertion = get_public_operation_result["data"].get("assertion", None) - - if public_assertion is None: - raise MissingKnowledgeAssetState("Unable to find state on the network!") - - if validate: - root = MerkleTree( - hash_assertion_with_indexes(public_assertion), sort_pairs=True - ).root - if root != public_assertion_id: - raise InvalidKnowledgeAsset( - f"State: {public_assertion_id}. " f"Merkle Tree Root: {root}" - ) - - result = {"operation": {}} - if content_visibility != KnowledgeAssetContentVisibility.PRIVATE: - formatted_public_assertion = public_assertion - - match output_format: - case "NQUADS" | "N-QUADS": - formatted_public_assertion: list[JSONLD] = jsonld.from_rdf( - "\n".join(public_assertion), - {"algorithm": "URDNA2015", "format": "application/n-quads"}, - ) - case "JSONLD" | "JSON-LD": - formatted_public_assertion = "\n".join(public_assertion) - - case _: - raise DatasetOutputFormatNotSupported( - f"{output_format} isn't supported!" - ) - - if content_visibility == KnowledgeAssetContentVisibility.PUBLIC: - result = { - **result, - "asertion": formatted_public_assertion, - "assertionId": public_assertion_id, - } - else: - result["public"] = { - "assertion": formatted_public_assertion, - "assertionId": public_assertion_id, - } - - result["operation"]["publicGet"] = { - "operationId": get_public_operation_id, - "status": get_public_operation_result["status"], - } - - if content_visibility != KnowledgeAssetContentVisibility.PUBLIC: - private_assertion_link_triples = list( - filter( - lambda element: PRIVATE_ASSERTION_PREDICATE in element, - public_assertion, - ) - ) - - if private_assertion_link_triples: - private_assertion_id = re.search( - r'"(.*?)"', private_assertion_link_triples[0] - ).group(1) - - private_assertion = get_public_operation_result["data"].get( - "privateAssertion", None - ) - - query_private_operation_id: NodeResponseDict | None = None - if private_assertion is None: - query = f""" - CONSTRUCT {{ ?s ?p ?o }} - WHERE {{ - {{ - GRAPH - {{ - ?s ?p ?o . - }} - }} - }} - """ - - query_private_operation_id = self._query( - query, - "CONSTRUCT", - ( - PRIVATE_CURRENT_REPOSITORY - if is_state_finalized - else PRIVATE_HISTORICAL_REPOSITORY - ), - )["operationId"] - - query_private_operation_result = self.get_operation_result( - query_private_operation_id, "query" - ) - - private_assertion = normalize_dataset( - query_private_operation_result["data"], - "N-Quads", - ) - - if validate: - root = MerkleTree( - hash_assertion_with_indexes(private_assertion), - sort_pairs=True, - ).root - if root != private_assertion_id: - raise InvalidKnowledgeAsset( - f"State: {private_assertion_id}. " - f"Merkle Tree Root: {root}" - ) - - match output_format: - case "NQUADS" | "N-QUADS": - formatted_private_assertion: list[JSONLD] = jsonld.from_rdf( - "\n".join(private_assertion), - { - "algorithm": "URDNA2015", - "format": "application/n-quads", - }, - ) - case "JSONLD" | "JSON-LD": - formatted_private_assertion = "\n".join(private_assertion) - - case _: - raise DatasetOutputFormatNotSupported( - f"{output_format} isn't supported!" - ) - - if content_visibility == KnowledgeAssetContentVisibility: - result = { - **result, - "assertion": formatted_private_assertion, - "assertionId": private_assertion_id, - } - else: - result["private"] = { - "assertion": formatted_private_assertion, - "assertionId": private_assertion_id, - } - - if query_private_operation_id is not None: - result["operation"]["queryPrivate"] = { - "operationId": query_private_operation_id, - "status": query_private_operation_result["status"], - } - - return result - _extend_storing_period = Method(BlockchainRequest.extend_asset_storing_period) def extend_storing_period( @@ -1019,17 +814,19 @@ def get_agreement_id(self, contract_address: Address, token_id: int) -> HexStr: _get_operation_result = Method(NodeRequest.get_operation_result) def get_operation_result( - self, operation_id: str, operation: str, max_retries: int = 5 + self, operation_id: str, operation: str, max_retries: int, frequency: int ): @retry( - catch=OperationNotFinished, max_retries=max_retries, base_delay=1, backoff=2 + catch=OperationNotFinished, + max_retries=max_retries, + base_delay=frequency, + backoff=2, ) def _get_opeation_results_(): operation_result = self._get_operation_result( operation_id=operation_id, operation=operation, ) - print(operation_result) validate_operation_status(operation_result) return operation_result diff --git a/dkg/constants.py b/dkg/constants.py index b5b47bd..8999512 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -1,3 +1,5 @@ +from enum import Enum + # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -19,6 +21,30 @@ "https://ontology.origintrail.io/dkg/1.0#privateAssertionID" ) + +class DefaultParameters(Enum): + ENVIRONMENT: str = "mainnet" + PORT: int = 8900 + FREQUENCY: int = 5 + MAX_NUMBER_OF_RETRIES: int = 5 + HASH_FUNCTION_ID: int = 1 + IMMUTABLE: bool = False + VALIDATE: bool = True + OUTPUT_FORMAT: str = "JSON-LD" + STATE: None = None + INCLUDE_METADATA: bool = False + CONTENT_TYPE: str = "all" + GRAPH_LOCATION: str = "LOCAL_KG" + GRAPH_STATE: str = "CURRENT" + HANDLE_NOT_MINED_ERROR: bool = False + SIMULATE_TXS: bool = False + FORCE_REPLACE_TXS: bool = False + GAS_LIMIT_MULTIPLIER: int = 1 + PARANET_UAL: None = None + GET_SUBJECT_UAL: bool = False + + +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" BLOCKCHAINS = { "development": { "hardhat1:31337": { @@ -67,25 +93,3 @@ PRIVATE_HISTORICAL_REPOSITORY = "privateHistory" PRIVATE_CURRENT_REPOSITORY = "privateCurrent" - -DEFAULT_PARAMETERS = { - "ENVIRONMENT": "mainnet", - "PORT": 8900, - "FREQUENCY": 5, - "MAX_NUMBER_OF_RETRIES": 5, - "HASH_FUNCTION_ID": 1, - "IMMUTABLE": False, - "VALIDATE": True, - "OUTPUT_FORMAT": "JSON-LD", - "STATE": None, - "INCLUDE_METADATA": False, - "CONTENT_TYPE": "all", - "GRAPH_LOCATION": "LOCAL_KG", - "GRAPH_STATE": "CURRENT", - "HANDLE_NOT_MINED_ERROR": False, - "SIMULATE_TXS": False, - "FORCE_REPLACE_TXS": False, - "GAS_LIMIT_MULTIPLIER": 1, - "PARANET_UAL": None, - "GET_SUBJECT_UAL": False, -} diff --git a/dkg/main.py b/dkg/main.py index c9c14d4..ec79e91 100644 --- a/dkg/main.py +++ b/dkg/main.py @@ -28,6 +28,7 @@ from dkg.providers import BlockchainProvider, NodeHTTPProvider from dkg.types import UAL, Address, ChecksumAddress from dkg.utils.ual import format_ual, parse_ual +from dkg.services.input_service import InputService class DKG(Module): @@ -56,9 +57,12 @@ def __init__( blockchain_provider: BlockchainProvider, ): self.manager = DefaultRequestManager(node_provider, blockchain_provider) + + self.initialize_services(self.manager) + modules = { "assertion": Assertion(self.manager), - "asset": KnowledgeAsset(self.manager), + "asset": KnowledgeAsset(self.manager, self.input_service), "paranet": Paranet(self.manager), "network": Network(self.manager), "node": Node(self.manager), @@ -66,6 +70,9 @@ def __init__( } self._attach_modules(modules) + def initialize_services(self, manager): + self.input_service = InputService(manager) + @property def node_provider(self) -> NodeHTTPProvider: return self.manager.node_provider diff --git a/dkg/providers/node_http.py b/dkg/providers/node_http.py index 1286655..8316d6c 100644 --- a/dkg/providers/node_http.py +++ b/dkg/providers/node_http.py @@ -25,8 +25,14 @@ class NodeHTTPProvider: - def __init__(self, endpoint_uri: URI | str, auth_token: str | None = None): + def __init__( + self, + endpoint_uri: URI | str, + api_version: str = "v1", + auth_token: str | None = None, + ): self.endpoint_uri = URI(endpoint_uri) + self.api_version = api_version self.auth_token = auth_token def make_request( @@ -36,7 +42,7 @@ def make_request( params: dict[str, Any] = {}, data: dict[str, Any] = {}, ) -> NodeResponseDict: - url = f"{self.endpoint_uri}/{path}" + url = f"{self.endpoint_uri}/{self.api_version}/{path}" headers = ( {"Authorization": f"Bearer {self.auth_token}"} if self.auth_token else {} ) diff --git a/dkg/services/input_service.py b/dkg/services/input_service.py new file mode 100644 index 0000000..a420b77 --- /dev/null +++ b/dkg/services/input_service.py @@ -0,0 +1,162 @@ +from dkg.constants import DefaultParameters, ZERO_ADDRESS + + +class InputService: + def __init__(self, manager): + self.manager = manager + + def get_asset_get_arguments(self, options): + return { + # "blockchain": self.get_blockchain(options), + "endpoint": self.get_endpoint(options), + "port": self.get_port(options), + "max_number_of_retries": self.get_max_number_of_retries(options), + "frequency": self.get_frequency(options), + "state": self.get_state(options), + "include_metadata": self.get_include_metadata(options), + "content_type": self.get_content_type(options), + "validate": self.get_validate(options), + "output_format": self.get_output_format(options), + "auth_token": self.get_auth_token(options), + "hash_function_id": self.get_hash_function_id(options), + "paranet_ual": self.get_paranet_ual(options), + "subject_ual": self.get_subject_ual(options), + } + + def get_asset_create_arguments(self, options): + return { + # "blockchain": self.get_blockchain(options), + "endpoint": self.get_endpoint(options), + "port": self.get_port(options), + "max_number_of_retries": self.get_max_number_of_retries(options), + "frequency": self.get_frequency(options), + "epochs_num": self.get_epochs_num(options), + "hash_function_id": self.get_hash_function_id(options), + "score_function_id": self.get_score_function_id(options), + "immutable": self.get_immutable(options), + "token_amount": self.get_token_amount(options), + "auth_token": self.get_auth_token(options), + "payer": self.get_payer(options), + "minimum_number_of_finalization_confirmations": self.get_minimum_number_of_finalization_confirmations( + options + ) + or 3, + "minimum_number_of_node_replications": self.get_minimum_number_of_node_replications( + options + ), + } + + def get_query_arguments(self, options): + return { + "graph_location": self.get_graph_location(options), + "graph_state": self.get_graph_state(options), + "endpoint": self.get_endpoint(options), + "port": self.get_port(options), + "max_number_of_retries": self.get_max_number_of_retries(options), + "frequency": self.get_frequency(options), + "auth_token": self.get_auth_token(options), + "paranet_ual": self.get_paranet_ual(options), + "repository": self.get_repository(options), + } + + def get_endpoint(self, options): + return ( + options.get("endpoint") or self.manager.node_provider.endpoint_uri or None + ) + + # def get_blockchain(self, options): + # return ( + # options.get("blockchain") + # or self.manager.blockchain_provider.blockchain + # or None + # ) + + def get_port(self, options): + return options.get("port") or DefaultParameters.PORT.value + + def get_max_number_of_retries(self, options): + return ( + options.get("max_number_of_retries") + or DefaultParameters.MAX_NUMBER_OF_RETRIES.value + ) + + def get_frequency(self, options): + return options.get("frequency") or DefaultParameters.FREQUENCY.value + + def get_state(self, options): + return options.get("state") or DefaultParameters.STATE.value + + def get_include_metadata(self, options): + return ( + options.get("include_metadata") or DefaultParameters.INCLUDE_METADATA.value + ) + + def get_content_type(self, options): + return options.get("content_type") or DefaultParameters.CONTENT_TYPE.value + + def get_validate(self, options): + return options.get("validate") or DefaultParameters.VALIDATE.value + + def get_output_format(self, options): + return options.get("output_format") or DefaultParameters.OUTPUT_FORMAT.value + + def get_auth_token(self, options): + return options.get("auth_token") or self.manager.node_provider.auth_token + + def get_hash_function_id(self, options): + return ( + options.get("hash_function_id") or DefaultParameters.HASH_FUNCTION_ID.value + ) + + def get_paranet_ual(self, options): + return options.get("paranet_ual") or DefaultParameters.PARANET_UAL.value + + def get_subject_ual(self, options): + return options.get("subject_ual") or DefaultParameters.GET_SUBJECT_UAL.value + + def get_epochs_num(self, options): + return options.get("epochs_num") or None + + def get_immutable(self, options): + return options.get("immutable") or DefaultParameters.IMMUTABLE.value + + def get_token_amount(self, options): + return options.get("token_amount") or None + + def get_payer(self, options): + return options.get("payer") or ZERO_ADDRESS + + def get_minimum_number_of_finalization_confirmations(self, options): + return options.get("minimum_number_of_finalization_confirmations") or None + + def get_minimum_number_of_node_replications(self, options): + return options.get("minimum_number_of_node_replications") or None + + def get_score_function_id(self, options): + enviroment = ( + options.get("environment") + or self.manager.blockchain_provider.environment + or DefaultParameters.ENVIRONMENT.value + ) + blockchain_name = ( + options.get("immutable") or self.manager.blockchain_provider.blockchain_id + ) + + return ( + DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ + self.manager.blockchain_provider.environment + ][blockchain_id], + ) + + def get_graph_location(self, options): + return ( + options.get("graph_location") + or options.get("paranet_ual") + or DefaultParameters.GRAPH_LOCATION.value + ) + + def get_graph_state(self, options): + return options.get("graph_state") or DefaultParameters.GRAPH_STATE.value + + def get_repository(self, options): + return options.get("repository") or None From ebd411ec40a58d8ec0f9839381a537dddfd542d1 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 17:13:36 +0100 Subject: [PATCH 038/146] Fixes --- dkg/asset.py | 3 --- dkg/utils/node_request.py | 2 +- examples/demo.py | 8 +++++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 1a0fff3..1a9e1ef 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -451,9 +451,6 @@ def create( minimum_number_of_finalization_confirmations: int, minimum_number_of_node_replications: int, token_amount: Wei | None = None, - # immutable: bool = False, - # content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - # paranet_ual: UAL | None = None, ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: blockchain_id = self.manager.blockchain_provider.blockchain_id diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index ea90f36..5346a22 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -72,7 +72,7 @@ class NodeRequest: finality_status = NodeCall( method=HTTPRequestMethod.GET, path="finality", - params={"ual": str}, + params={"ual": UAL}, ) get = NodeCall( diff --git a/examples/demo.py b/examples/demo.py index 61a3538..3cfe80c 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -132,7 +132,13 @@ def print_json(json_dict: dict): divider() start_time = time.time() -create_asset_result = dkg.asset.create(content, 2, 3, 1, "100") +create_asset_result = dkg.asset.create( + content=content, + epochs_num=2, + minimum_number_of_finalization_confirmations=3, + minimum_number_of_node_replications=1, + token_amount=100, +) print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") print_json(create_asset_result) divider() From d9e03a68a5a29b33dd608511500a43f6175c41dd Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Wed, 8 Jan 2025 17:39:36 +0100 Subject: [PATCH 039/146] Removed private key --- examples/demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/demo.py b/examples/demo.py index 2d521fd..18ac712 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -24,7 +24,7 @@ blockchain_provider = BlockchainProvider( "testnet", "base:84532", - private_key="db20be6415f83a8a9f0c129bf20ab99ba15bfb90ac5e34f1848f59c20ea9c068", + private_key="", ) dkg = DKG(node_provider, blockchain_provider) From fdeb5a8026acf2714a57ca4815df9f78345f762a Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 10:02:37 +0100 Subject: [PATCH 040/146] Move private key to .env --- dkg/providers/blockchain.py | 8 ++------ examples/demo.py | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/dkg/providers/blockchain.py b/dkg/providers/blockchain.py index 321b5f1..d7e6d26 100644 --- a/dkg/providers/blockchain.py +++ b/dkg/providers/blockchain.py @@ -49,7 +49,6 @@ def __init__( environment: Environment, blockchain_id: str, rpc_uri: URI | None = None, - private_key: DataHexStr | None = None, gas_price: Wei | None = None, verify: bool = True, ): @@ -106,11 +105,8 @@ def __init__( } self._init_contracts() - if ( - private_key is not None - or (private_key_env := os.environ.get("PRIVATE_KEY", None)) is not None - ): - self.set_account(private_key or private_key_env) + if private_key := os.environ.get("PRIVATE_KEY"): + self.set_account(private_key) def make_json_rpc_request(self, endpoint: str, args: dict[str, Any] = {}) -> Any: web3_method = getattr(self.w3.eth, endpoint) diff --git a/examples/demo.py b/examples/demo.py index 3cfe80c..3dada0f 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -25,7 +25,6 @@ blockchain_provider = BlockchainProvider( "development", "hardhat1:31337", - private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", ) dkg = DKG(node_provider, blockchain_provider) From 31ce77327fc1f93d232737452a6b248a1156edc5 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 9 Jan 2025 10:08:23 +0100 Subject: [PATCH 041/146] Code review changes 1 --- dkg/asset.py | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index d1ead06..38baeb9 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -594,31 +594,17 @@ def get(self, ual: UAL, options=None) -> dict: get_public_operation_id, "get", max_number_of_retries, frequency ) - def get_operation_status_object(self, operation_result, operation_id): - - if "errorType" in operation_result.get("data", {}): - - operation_data = { - "status": operation_result["status"], - **operation_result["data"], - } - else: - - operation_data = {"status": operation_result["status"]} - - return {"operationId": operation_id, **operation_data} - if subject_ual: - if get_public_operation_result["data"]: + if get_public_operation_result.get("data"): return { "operation": { "get": self.get_operation_status_object( get_public_operation_result, get_public_operation_id ), }, - "subjectUALPairs": get_public_operation_result["data"], + "subjectUALPairs": get_public_operation_result.get("data"), } - if get_public_operation_result["status"] != "FAILED": + if get_public_operation_result.get("status") != "FAILED": get_public_operation_result["data"] = { "errorType": "DKG_CLIENT_ERROR", "errorMessage": "Unable to find assertion on the network!", @@ -632,11 +618,11 @@ def get_operation_status_object(self, operation_result, operation_id): ), }, } - metadata = get_public_operation_result["data"] - assertion = get_public_operation_result["data"].get("assertion", None) + metadata = get_public_operation_result.get("data") + assertion = get_public_operation_result.get("data").get("assertion", None) if not assertion: - if get_public_operation_result["status"] != "FAILED": + if get_public_operation_result.get("status") != "FAILED": get_public_operation_result["data"] = { "errorType": "DKG_CLIENT_ERROR", "errorMessage": "Unable to find assertion on the network!", From b90875fd77bbb63422949bf1ebcfbc459563ff5c Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 11:49:08 +0100 Subject: [PATCH 042/146] Update hubs --- dkg/constants.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dkg/constants.py b/dkg/constants.py index 0d12f10..1752645 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -54,13 +54,13 @@ class DefaultParameters(Enum): }, "devnet": { "base:84532": { - "hub": "0xaA849CAC4FA86f6b7484503f3c7a314772AED6d4", + "hub": "0xE043daF4cC8ae2c720ef95fc82574a37a429c40A", "rpc": "https://sepolia.base.org", } }, "testnet": { "base:84532": { - "hub": "0xCca0eA14540588A09c85cD6A6Fc53eA3A7010692", + "hub": "0xf21CE8f8b01548D97DCFb36869f1ccB0814a4e05", "rpc": "https://sepolia.base.org", } }, From c452b0d280658cc4a4391e8a863568ca2cc9fb04 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 11:49:20 +0100 Subject: [PATCH 043/146] Add abis --- dkg/data/interfaces/AskStorage.json | 366 ++++++++++++++++++++++++++++ dkg/data/interfaces/Chronos.json | 202 +++++++++++++++ 2 files changed, 568 insertions(+) create mode 100644 dkg/data/interfaces/AskStorage.json create mode 100644 dkg/data/interfaces/Chronos.json diff --git a/dkg/data/interfaces/AskStorage.json b/dkg/data/interfaces/AskStorage.json new file mode 100644 index 0000000..db93d48 --- /dev/null +++ b/dkg/data/interfaces/AskStorage.json @@ -0,0 +1,366 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "decreaseTotalActiveStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "decreaseWeightedActiveAskSum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAskBounds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAskLowerBound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAskUpperBound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPrevPricePerKbEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPrevStakeWeightedAverageAsk", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPricePerKbEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStakeWeightedAverageAsk", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "increaseTotalActiveStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "increaseWeightedActiveAskSum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "parametersStorage", + "outputs": [ + { + "internalType": "contract ParametersStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prevTotalActiveStake", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prevWeightedActiveAskSum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "_prevTotalActiveStake", + "type": "uint96" + } + ], + "name": "setPrevTotalActiveStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_prevWeightedActiveAskSum", + "type": "uint256" + } + ], + "name": "setPrevWeightedActiveAskSum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_status", + "type": "bool" + } + ], + "name": "setStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "_totalActiveStake", + "type": "uint96" + } + ], + "name": "setTotalActiveStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_weightedActiveAskSum", + "type": "uint256" + } + ], + "name": "setWeightedActiveAskSum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalActiveStake", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "weightedActiveAskSum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/dkg/data/interfaces/Chronos.json b/dkg/data/interfaces/Chronos.json new file mode 100644 index 0000000..0824716 --- /dev/null +++ b/dkg/data/interfaces/Chronos.json @@ -0,0 +1,202 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_epochLength", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidEpochLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidStartTime", + "type": "error" + }, + { + "inputs": [], + "name": "EPOCH_LENGTH", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "START_TIME", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "elapsedTimeInCurrentEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "epochAtTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + } + ], + "name": "hasEpochElapsed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isChronosActive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timeUntilNextEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + } + ], + "name": "timestampForEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalElapsedTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] From 61d31a3f8c6565052cfa7f8a5937842f6d31adab Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 11:49:40 +0100 Subject: [PATCH 044/146] PR suggesstions --- dkg/asset.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 1a9e1ef..1c858d0 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -266,24 +266,26 @@ def finality_status( finality = 0 while finality < required_confirmations and retries <= max_number_of_retries: + try: + response = self._finality_status(ual) + finality = response.get("finality", 0) + if finality >= required_confirmations: + break + except Exception: + finality = 0 + + retries += 1 + if retries > max_number_of_retries: raise Exception( f"Unable to achieve required confirmations. " f"Max number of retries ({max_number_of_retries}) reached." ) - retries += 1 - # Sleep between attempts (except for first try) if retries > 1: time.sleep(frequency) - try: - response = self._finality_status(ual) - finality = response.get("finality", 0) - except Exception: - finality = 0 - return finality def increase_knowledge_collection_allowance( @@ -630,18 +632,17 @@ def create( stake_weighted_average_ask = self._get_stake_weighted_average_ask() # Convert to integers and perform calculation - # Note: In Python we use regular int as it handles arbitrary precision automatically estimated_publishing_cost = ( ( int(stake_weighted_average_ask) * ( int(epochs_num) * int(1e18) - + (int(time_until_next_epoch) * int(1e18)) / int(epoch_length) + + (int(time_until_next_epoch) * int(1e18)) // int(epoch_length) ) * int(dataset_size) ) - / 1024 - / int(1e18) + // 1024 + // int(1e18) ) knowledge_collection_id = None From f1c9d4123db3e27f70a063e72aec203289f3c6e2 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 9 Jan 2025 13:13:45 +0100 Subject: [PATCH 045/146] Code review 2 --- dkg/asset.py | 15 ++-- dkg/constants.py | 19 ++++- dkg/services/input_service.py | 11 +-- examples/demo.py | 140 ++-------------------------------- 4 files changed, 31 insertions(+), 154 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 38baeb9..413a2a8 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -32,6 +32,7 @@ PRIVATE_ASSERTION_PREDICATE, PRIVATE_CURRENT_REPOSITORY, PRIVATE_HISTORICAL_REPOSITORY, + OutputTypes, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -580,9 +581,9 @@ def get(self, ual: UAL, options=None) -> dict: paranet_ual = arguments["paranet_ual"] subject_ual = arguments["subject_ual"] - id_field = f"{ual}:{state}" if state else ual + ual_with_state = f"{ual}:{state}" if state else ual get_public_operation_id: NodeResponseDict = self._get( - id_field, + ual_with_state, content_type, include_metadata, hash_function_id, @@ -602,7 +603,7 @@ def get(self, ual: UAL, options=None) -> dict: get_public_operation_result, get_public_operation_id ), }, - "subjectUALPairs": get_public_operation_result.get("data"), + "subject_ual_pairs": get_public_operation_result.get("data"), } if get_public_operation_result.get("status") != "FAILED": get_public_operation_result["data"] = { @@ -650,13 +651,13 @@ def get(self, ual: UAL, options=None) -> dict: ) formatted_metadata = None - if output_format == "JSON-LD": + if output_format == OutputTypes.JSONLD.value: formatted_assertion = self.to_jsonld(formatted_assertion) if include_metadata: formatted_metadata = self.to_jsonld("\n".join(metadata)) - if output_format == "N-QUADS": + if output_format == OutputTypes.NQUADS.value: formatted_assertion = self.to_nquads( formatted_assertion, "application/n-quads" ) @@ -808,7 +809,7 @@ def get_operation_result( base_delay=frequency, backoff=2, ) - def _get_opeation_results_(): + def _get_operation_results_(): operation_result = self._get_operation_result( operation_id=operation_id, operation=operation, @@ -817,7 +818,7 @@ def _get_opeation_results_(): return operation_result - return _get_opeation_results_() + return _get_operation_results_() def to_jsonld(self, nquads: str): options = { diff --git a/dkg/constants.py b/dkg/constants.py index 8999512..b0352ff 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -23,7 +23,7 @@ class DefaultParameters(Enum): - ENVIRONMENT: str = "mainnet" + ENVIRONMENT: str = "testnet" PORT: int = 8900 FREQUENCY: int = 5 MAX_NUMBER_OF_RETRIES: int = 5 @@ -44,6 +44,11 @@ class DefaultParameters(Enum): GET_SUBJECT_UAL: bool = False +class OutputTypes(Enum): + NQUADS: str = "N-QUADS" + JSONLD: str = "JSON-LD" + + ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" BLOCKCHAINS = { "development": { @@ -64,9 +69,17 @@ class DefaultParameters(Enum): }, "testnet": { "base:84532": { - "hub": "0xCca0eA14540588A09c85cD6A6Fc53eA3A7010692", + "hub": "0xf21CE8f8b01548D97DCFb36869f1ccB0814a4e05", "rpc": "https://sepolia.base.org", - } + }, + "gnosis:10200": { + "hub": "0x2c08AC4B630c009F709521e56Ac385A6af70650f", + "rpc": "https://rpc.chiadochain.net", + }, + "otp:20430": { + "hub": "0xd7d073b560412c6A7F33dD670d323D01061E5DEb", + "rpc": "https://lofar-testnet.origin-trail.network", + }, }, "mainnet": {}, } diff --git a/dkg/services/input_service.py b/dkg/services/input_service.py index a420b77..5213097 100644 --- a/dkg/services/input_service.py +++ b/dkg/services/input_service.py @@ -7,7 +7,6 @@ def __init__(self, manager): def get_asset_get_arguments(self, options): return { - # "blockchain": self.get_blockchain(options), "endpoint": self.get_endpoint(options), "port": self.get_port(options), "max_number_of_retries": self.get_max_number_of_retries(options), @@ -25,7 +24,6 @@ def get_asset_get_arguments(self, options): def get_asset_create_arguments(self, options): return { - # "blockchain": self.get_blockchain(options), "endpoint": self.get_endpoint(options), "port": self.get_port(options), "max_number_of_retries": self.get_max_number_of_retries(options), @@ -64,13 +62,6 @@ def get_endpoint(self, options): options.get("endpoint") or self.manager.node_provider.endpoint_uri or None ) - # def get_blockchain(self, options): - # return ( - # options.get("blockchain") - # or self.manager.blockchain_provider.blockchain - # or None - # ) - def get_port(self, options): return options.get("port") or DefaultParameters.PORT.value @@ -159,4 +150,4 @@ def get_graph_state(self, options): return options.get("graph_state") or DefaultParameters.GRAPH_STATE.value def get_repository(self, options): - return options.get("repository") or None + return options.get("repository") or "dkg" diff --git a/examples/demo.py b/examples/demo.py index 18ac712..4903b79 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -23,7 +23,9 @@ node_provider = NodeHTTPProvider("https://v6-pegasus-node-04.origin-trail.network:8900") blockchain_provider = BlockchainProvider( "testnet", - "base:84532", + # "base:84532", + # "gnosis:10200", + "otp:20430", private_key="", ) @@ -40,146 +42,16 @@ def print_json(json_dict: dict): print(json.dumps(json_dict, indent=4)) -content = { - "public": { - "@context": ["http://schema.org"], - "@id": "uuid:1", - "company": "OT", - "user": {"@id": "uuid:user:1"}, - "city": {"@id": "uuid:belgrade"}, - }, - "private": { - "@context": ["http://schema.org"], - "@graph": [ - {"@id": "uuid:user:1", "name": "Adam", "lastname": "Smith"}, - {"@id": "uuid:belgrade", "title": "Belgrade", "postCode": "11000"}, - ], - }, -} +content = {} -# divider() - -# info_result = dkg.node.info - -# print("======================== NODE INFO RECEIVED") -# print_json(info_result) - divider() -# formatted_assertions = dkg.assertion.format_graph(content) -# print("======================== ASSET FORMATTED") -# print_json(formatted_assertions) - -# divider() - -# public_assertion_id = dkg.assertion.get_public_assertion_id(content) -# print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") -# print(public_assertion_id) - -# divider() - -# public_assertion_size = dkg.assertion.get_size(content) -# print("======================== PUBLIC ASSERTION SIZE CALCULATED") -# print(public_assertion_size) - -# divider() - -# public_assertion_triples_number = dkg.assertion.get_triples_number(content) -# print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") -# print(public_assertion_triples_number) - -# divider() - -# public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) -# print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") -# print(public_assertion_chunks_number) - -# divider() - -# bid_suggestion = dkg.network.get_bid_suggestion( -# public_assertion_id, -# public_assertion_size, -# 2, -# ) -# print("======================== BID SUGGESTION CALCULATED") -# print(bid_suggestion) - -# divider() - -# current_allowance = dkg.asset.get_current_allowance() -# print("======================== GET CURRENT ALLOWANCE") -# print(current_allowance) -# divider() - -# allowance_increase = dkg.asset.increase_allowance(bid_suggestion) -# print("======================== INCREASE ALLOWANCE") -# print(allowance_increase) - -# divider() - -# allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) -# print("======================== DECREASE ALLOWANCE") -# print(allowance_decrease) - -# divider() - -# allowance_set = dkg.asset.set_allowance(bid_suggestion) -# print("======================== SET ALLOWANCE") -# print(allowance_set) - -# divider() - -# create_asset_result = dkg.asset.create(content, 2) -# print("======================== ASSET CREATED") -# print_json(create_asset_result) -# divider() - -# validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) -# print("======================== VALIDATE UAL") -# print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") -# divider() - -# owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) -# print("======================== GET ASSET OWNER") -# print(owner_result) -# divider() - -# get_asset_result = dkg.asset.get(create_asset_result["UAL"]) -# print("======================== ASSET RESOLVED") -# print_json(get_asset_result) -# divider() - -# get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") -# print("======================== ASSET LATEST RESOLVED") -# print_json(get_latest_asset_result) -# divider() - -# get_latest_finalized_asset_result = dkg.asset.get( -# create_asset_result["UAL"], "latest_finalized", "all" -# ) -# print("======================== ASSET LATEST FINALIZED RESOLVED") -# print_json(get_latest_finalized_asset_result) -# divider() - -get_v8_test = dkg.asset.get_v8( - "did:dkg:base:84532/0xd5550173b0f7b8766ab2770e4ba86caf714a5af5/10176" +get_v8_test = dkg.asset.get( + "did:dkg:otp:20430/0xb4c24fc54bc811c2659c477b65da8648e499fd39/2353" ) print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") print(get_v8_test) # print_json(get_v8_test) divider() - -# get_first_state_by_hash = dkg.asset.get( -# create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" -# ) -# print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") -# print_json(get_first_state_by_hash) -# divider() - -# query_result = dkg.graph.query( -# "construct { ?s ?p ?o } where { ?s ?p ?o . ?p ?o }", "privateCurrent" -# ) -# print("======================== QUERY LOCAL CURRENT RESULT") -# print(query_result) From 21571c24ffef9cede938133eaad11416545ecb74 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 9 Jan 2025 14:42:20 +0100 Subject: [PATCH 046/146] Code changes 3 --- dkg/asset.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dkg/asset.py b/dkg/asset.py index 413a2a8..b2f4e65 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -647,7 +647,12 @@ def get(self, ual: UAL, options=None) -> dict: } formatted_assertion = "\n".join( - assertion.get("public", []) + assertion.get("private", []) + assertion.get("public", []) + + ( + assertion.get("private", []) + if isinstance(assertion.get("private", []), list) + else [] + ) ) formatted_metadata = None From 7b4e1687b8114ced618c38a0d4948bfa619b8bde Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 15:35:07 +0100 Subject: [PATCH 047/146] Update demo --- dkg/asset.py | 4 +- examples/demo.py | 104 +---------------------------------------------- 2 files changed, 3 insertions(+), 105 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 1c858d0..48afc4a 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -360,7 +360,7 @@ def create_knowledge_collection( request.get("knowledgeAssetsAmount"), request.get("byteSize"), request.get("epochs"), - int(request.get("tokenAmount")), + request.get("tokenAmount"), request.get("isImmutable"), request.get("paymaster"), request.get("publisherNodeIdentityId"), @@ -657,7 +657,7 @@ def create( ), "byteSize": dataset_size, "epochs": epochs_num, - "tokenAmount": str(estimated_publishing_cost), + "tokenAmount": estimated_publishing_cost, "isImmutable": DefaultParameters.IMMUTABLE.value, "paymaster": DefaultParameters.ZERO_ADDRESS.value, "publisherNodeIdentityId": publisher_node_identity_id, diff --git a/examples/demo.py b/examples/demo.py index 3dada0f..4d3a2e7 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -66,70 +66,6 @@ def print_json(json_dict: dict): divider() -# formatted_assertions = dkg.assertion.format_graph(content) -# print("======================== ASSET FORMATTED") -# print_json(formatted_assertions) - -# divider() - -# public_assertion_id = dkg.assertion.get_public_assertion_id(content) -# print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") -# print(public_assertion_id) - -# divider() - -# public_assertion_size = dkg.assertion.get_size(content) -# print("======================== PUBLIC ASSERTION SIZE CALCULATED") -# print(public_assertion_size) - -# divider() - -# public_assertion_triples_number = dkg.assertion.get_triples_number(content) -# print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") -# print(public_assertion_triples_number) - -# divider() - -# public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) -# print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") -# print(public_assertion_chunks_number) - -# divider() - -# bid_suggestion = dkg.network.get_bid_suggestion( -# public_assertion_id, -# public_assertion_size, -# 2, -# ) -# print("======================== BID SUGGESTION CALCULATED") -# print(bid_suggestion) - -# divider() - -# current_allowance = dkg.asset.get_current_allowance() -# print("======================== GET CURRENT ALLOWANCE") -# print(current_allowance) - -# divider() - -# allowance_increase = dkg.asset.increase_allowance(bid_suggestion) -# print("======================== INCREASE ALLOWANCE") -# print(allowance_increase) - -# divider() - -# allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) -# print("======================== DECREASE ALLOWANCE") -# print(allowance_decrease) - -# divider() - -# allowance_set = dkg.asset.set_allowance(bid_suggestion) -# print("======================== SET ALLOWANCE") -# print(allowance_set) - -divider() - start_time = time.time() create_asset_result = dkg.asset.create( content=content, @@ -140,46 +76,8 @@ def print_json(json_dict: dict): ) print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") print_json(create_asset_result) -divider() -# validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) -# print("======================== VALIDATE UAL") -# print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") -# divider() - -# owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) -# print("======================== GET ASSET OWNER") -# print(owner_result) -# divider() - -# get_asset_result = dkg.asset.get(create_asset_result["UAL"]) -# print("======================== ASSET RESOLVED") -# print_json(get_asset_result) -# divider() - -# get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") -# print("======================== ASSET LATEST RESOLVED") -# print_json(get_latest_asset_result) -# divider() - -# get_latest_finalized_asset_result = dkg.asset.get( -# create_asset_result["UAL"], "latest_finalized", "all" -# ) -# print("======================== ASSET LATEST FINALIZED RESOLVED") -# print_json(get_latest_finalized_asset_result) -# divider() - -# get_first_state_by_index = dkg.asset.get(create_asset_result["UAL"], 0, "all") -# print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") -# print_json(get_first_state_by_index) -# divider() - -# get_first_state_by_hash = dkg.asset.get( -# create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" -# ) -# print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") -# print_json(get_first_state_by_hash) -# divider() +divider() query_operation_result = dkg.graph.query( """ From aa2d662d0e7b79e82a7b8f5efef60591998dea91 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 16:57:52 +0100 Subject: [PATCH 048/146] Merge create query get --- dkg/asset.py | 109 +++++++++++++++------------------- dkg/constants.py | 14 ++++- dkg/graph.py | 47 ++++++++++----- dkg/main.py | 2 +- dkg/services/input_service.py | 44 +++----------- examples/demo.py | 17 +++--- 6 files changed, 109 insertions(+), 124 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index f05ee10..84173df 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -18,7 +18,6 @@ import json import time import math -import re import hashlib from typing import Literal, Type, Dict, Optional, Any from pyld import jsonld @@ -36,28 +35,20 @@ DEFAULT_HASH_FUNCTION_ID, DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS, PRIVATE_ASSERTION_PREDICATE, - PRIVATE_CURRENT_REPOSITORY, - PRIVATE_HISTORICAL_REPOSITORY, PRIVATE_RESOURCE_PREDICATE, PRIVATE_HASH_SUBJECT_PREFIX, CHUNK_BYTE_SIZE, MAX_FILE_SIZE, + DEFAULT_RDF_FORMAT, Operations, - DefaultParameters, OutputTypes, ) from dkg.dataclasses import ( BidSuggestionRange, - KnowledgeAssetContentVisibility, - KnowledgeAssetEnumStates, NodeResponseDict, ) from dkg.exceptions import ( - DatasetOutputFormatNotSupported, - InvalidKnowledgeAsset, - InvalidStateOption, InvalidTokenAmount, - MissingKnowledgeAssetState, OperationNotFinished, ) from dkg.manager import DefaultRequestManager @@ -82,10 +73,7 @@ StoreTypes, validate_operation_status, ) -from dkg.utils.rdf import ( - format_content, - normalize_dataset, -) +from dkg.utils.rdf import format_content from dkg.utils.ual import format_ual, parse_ual import dkg.utils.knowledge_collection_tools as kc_tools import dkg.utils.knowledge_asset_tools as ka_tools @@ -451,11 +439,23 @@ def get_message_signer_address(self, dataset_root: str, signature: dict): def create( self, content: dict[Literal["public", "private"], JSONLD], - epochs_num: int, - minimum_number_of_finalization_confirmations: int, - minimum_number_of_node_replications: int, - token_amount: Wei | None = None, + options: dict = {}, ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: + arguments = self.input_service.get_asset_create_arguments(options) + + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + epochs_num = arguments.get("epochs_num") + hash_function_id = arguments.get("hash_function_id") + immutable = arguments.get("immutable") + token_amount = arguments.get("token_amount") + payer = arguments.get("payer") + minimum_number_of_finalization_confirmations = arguments.get( + "minimum_number_of_finalization_confirmations" + ) + minimum_number_of_node_replications = arguments.get( + "minimum_number_of_node_replications" + ) blockchain_id = self.manager.blockchain_provider.blockchain_id dataset = {} @@ -573,12 +573,14 @@ def create( dataset_root, dataset, blockchain_id, - DEFAULT_HASH_FUNCTION_ID, + hash_function_id, minimum_number_of_node_replications, )["operationId"] publish_operation_result = self.get_operation_result( - Operations.PUBLISH.value, publish_operation_id, + Operations.PUBLISH.value, + max_number_of_retries, + frequency, ) if publish_operation_result.get( @@ -660,8 +662,8 @@ def create( "byteSize": dataset_size, "epochs": epochs_num, "tokenAmount": estimated_publishing_cost, - "isImmutable": DefaultParameters.IMMUTABLE.value, - "paymaster": DefaultParameters.ZERO_ADDRESS.value, + "isImmutable": immutable, + "paymaster": payer, "publisherNodeIdentityId": publisher_node_identity_id, "publisherNodeR": publisher_node_r, "publisherNodeVS": publisher_node_vs, @@ -914,23 +916,19 @@ def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: _get = Method(NodeRequest.get) _query = Method(NodeRequest.query) - def get(self, ual: UAL, options=None) -> dict: - if options is None: - options = {} - + def get(self, ual: UAL, options: dict = {}) -> dict: arguments = self.input_service.get_asset_get_arguments(options) - max_number_of_retries = arguments["max_number_of_retries"] - frequency = arguments["frequency"] - state = arguments["state"] - include_metadata = arguments["include_metadata"] - content_type = arguments["content_type"] - validate = arguments["validate"] - output_format = arguments["output_format"] - auth_token = arguments["auth_token"] - hash_function_id = arguments["hash_function_id"] - paranet_ual = arguments["paranet_ual"] - subject_ual = arguments["subject_ual"] + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + state = arguments.get("state") + include_metadata = arguments.get("include_metadata") + content_type = arguments.get("content_type") + validate = arguments.get("validate") + output_format = arguments.get("output_format") + hash_function_id = arguments.get("hash_function_id") + paranet_ual = arguments.get("paranet_ual") + subject_ual = arguments.get("subject_ual") ual_with_state = f"{ual}:{state}" if state else ual get_public_operation_id: NodeResponseDict = self._get( @@ -943,7 +941,10 @@ def get(self, ual: UAL, options=None) -> dict: )["operationId"] get_public_operation_result = self.get_operation_result( - get_public_operation_id, "get", max_number_of_retries, frequency + get_public_operation_id, + Operations.GET.value, + max_number_of_retries, + frequency, ) if subject_ual: @@ -971,7 +972,7 @@ def get(self, ual: UAL, options=None) -> dict: }, } metadata = get_public_operation_result.get("data") - assertion = get_public_operation_result.get("data").get("assertion", None) + assertion = get_public_operation_result.get("data", {}).get("assertion", None) if not assertion: if get_public_operation_result.get("status") != "FAILED": @@ -993,15 +994,15 @@ def get(self, ual: UAL, options=None) -> dict: is_valid = True # #TODO: Implement assertion validation logic if not is_valid: get_public_operation_result["data"] = { - "errorType": "DKG_CLIENT_ERROR", - "errorMessage": "Calculated root hashes don't match!", + "error_type": "DKG_CLIENT_ERROR", + "error_message": "Calculated root hashes don't match!", } formatted_assertion = "\n".join( assertion.get("public", []) + ( - assertion.get("private", []) - if isinstance(assertion.get("private", []), list) + assertion.get("private") + if isinstance(assertion.get("private"), list) else [] ) ) @@ -1015,11 +1016,11 @@ def get(self, ual: UAL, options=None) -> dict: if output_format == OutputTypes.NQUADS.value: formatted_assertion = self.to_nquads( - formatted_assertion, "application/n-quads" + formatted_assertion, DEFAULT_RDF_FORMAT ) if include_metadata: formatted_metadata = self.to_nquads( - "\n".join(metadata), "application/n-quads" + "\n".join(metadata), DEFAULT_RDF_FORMAT ) result = { @@ -1165,7 +1166,7 @@ def get_operation_result( base_delay=frequency, backoff=2, ) - def _get_operation_results_(): + def retry_get_operation_result(): operation_result = self._get_operation_result( operation_id=operation_id, operation=operation, @@ -1174,7 +1175,7 @@ def _get_operation_results_(): return operation_result - return _get_operation_results_() + return retry_get_operation_result() def to_jsonld(self, nquads: str): options = { @@ -1201,17 +1202,3 @@ def to_nquads(self, content, input_format): except Exception as e: raise ValueError(f"Error processing content: {e}") - - def get_operation_status_object(self, operation_result, operation_id): - if operation_result.get("data", {}).get("errorType"): - operation_data = { - "status": operation_result["status"], - **operation_result["data"], - } - else: - operation_data = {"status": operation_result["status"]} - - return { - "operationId": operation_id, - **operation_data, - } diff --git a/dkg/constants.py b/dkg/constants.py index a318e5d..7aa10a7 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -23,6 +23,16 @@ "https://ontology.origintrail.io/dkg/1.0#privateMerkleRoot" ) +PRIVATE_HASH_SUBJECT_PREFIX = "https://ontology.origintrail.io/dkg/1.0#metadata-hash:" + +PRIVATE_RESOURCE_PREDICATE = ( + "https://ontology.origintrail.io/dkg/1.0#representsPrivateResource" +) + +CHUNK_BYTE_SIZE = 32 + +MAX_FILE_SIZE = 10000000 + class DefaultParameters(Enum): ENVIRONMENT: str = "testnet" @@ -36,14 +46,13 @@ class DefaultParameters(Enum): STATE: None = None INCLUDE_METADATA: bool = False CONTENT_TYPE: str = "all" - GRAPH_LOCATION: str = "LOCAL_KG" - GRAPH_STATE: str = "CURRENT" HANDLE_NOT_MINED_ERROR: bool = False SIMULATE_TXS: bool = False FORCE_REPLACE_TXS: bool = False GAS_LIMIT_MULTIPLIER: int = 1 PARANET_UAL: None = None GET_SUBJECT_UAL: bool = False + REPOSITORY: str = "dkg" class OutputTypes(Enum): @@ -86,7 +95,6 @@ class OutputTypes(Enum): "mainnet": {}, } -DEFAULT_HASH_FUNCTION_ID = 1 DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS = { "development": {"hardhat1:31337": 2, "hardhat2:31337": 2, "otp:2043": 2}, "devnet": { diff --git a/dkg/graph.py b/dkg/graph.py index 025b0fb..3c7fa28 100644 --- a/dkg/graph.py +++ b/dkg/graph.py @@ -25,11 +25,13 @@ from dkg.types import NQuads from dkg.utils.decorators import retry from dkg.utils.node_request import NodeRequest, validate_operation_status +from dkg.constants import Operations class Graph(Module): - def __init__(self, manager: DefaultRequestManager): + def __init__(self, manager: DefaultRequestManager, input_service): self.manager = manager + self.input_service = input_service _query = Method(NodeRequest.query) _get_operation_result = Method(NodeRequest.get_operation_result) @@ -37,28 +39,43 @@ def __init__(self, manager: DefaultRequestManager): def query( self, query: str, - repository: str | None = None, - paranet_ual: str | None = None, + options: dict = {}, ) -> NQuads: + arguments = self.input_service.get_query_arguments(options) + + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + paranet_ual = arguments.get("paranet_ual") + repository = arguments.get("repository") + parsed_query = parseQuery(query) query_type = parsed_query[1].name.replace("Query", "").upper() - operation_id: NodeResponseDict = self._query(query, query_type, repository, paranet_ual)[ - "operationId" - ] - operation_result = self.get_operation_result(operation_id, "query") + operation_id: NodeResponseDict = self._query( + query, query_type, repository, paranet_ual + )["operationId"] + operation_result = self.get_operation_result( + operation_id, Operations.QUERY.value, max_number_of_retries, frequency + ) return operation_result["data"] - @retry(catch=OperationNotFinished, max_retries=5, base_delay=1, backoff=2) def get_operation_result( - self, operation_id: str, operation: str - ) -> NodeResponseDict: - operation_result = self._get_operation_result( - operation_id=operation_id, - operation=operation, + self, operation_id: str, operation: str, max_retries: int, frequency: int + ): + @retry( + catch=OperationNotFinished, + max_retries=max_retries, + base_delay=frequency, + backoff=2, ) + def retry_get_operation_result(): + operation_result = self._get_operation_result( + operation_id=operation_id, + operation=operation, + ) + validate_operation_status(operation_result) - validate_operation_status(operation_result) + return operation_result - return operation_result + return retry_get_operation_result() diff --git a/dkg/main.py b/dkg/main.py index ec79e91..00fd427 100644 --- a/dkg/main.py +++ b/dkg/main.py @@ -66,7 +66,7 @@ def __init__( "paranet": Paranet(self.manager), "network": Network(self.manager), "node": Node(self.manager), - "graph": Graph(self.manager), + "graph": Graph(self.manager, self.input_service), } self._attach_modules(modules) diff --git a/dkg/services/input_service.py b/dkg/services/input_service.py index 5213097..9efb31a 100644 --- a/dkg/services/input_service.py +++ b/dkg/services/input_service.py @@ -1,4 +1,8 @@ -from dkg.constants import DefaultParameters, ZERO_ADDRESS +from dkg.constants import ( + DefaultParameters, + ZERO_ADDRESS, + DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS, +) class InputService: @@ -7,8 +11,6 @@ def __init__(self, manager): def get_asset_get_arguments(self, options): return { - "endpoint": self.get_endpoint(options), - "port": self.get_port(options), "max_number_of_retries": self.get_max_number_of_retries(options), "frequency": self.get_frequency(options), "state": self.get_state(options), @@ -16,7 +18,6 @@ def get_asset_get_arguments(self, options): "content_type": self.get_content_type(options), "validate": self.get_validate(options), "output_format": self.get_output_format(options), - "auth_token": self.get_auth_token(options), "hash_function_id": self.get_hash_function_id(options), "paranet_ual": self.get_paranet_ual(options), "subject_ual": self.get_subject_ual(options), @@ -24,8 +25,6 @@ def get_asset_get_arguments(self, options): def get_asset_create_arguments(self, options): return { - "endpoint": self.get_endpoint(options), - "port": self.get_port(options), "max_number_of_retries": self.get_max_number_of_retries(options), "frequency": self.get_frequency(options), "epochs_num": self.get_epochs_num(options), @@ -33,7 +32,6 @@ def get_asset_create_arguments(self, options): "score_function_id": self.get_score_function_id(options), "immutable": self.get_immutable(options), "token_amount": self.get_token_amount(options), - "auth_token": self.get_auth_token(options), "payer": self.get_payer(options), "minimum_number_of_finalization_confirmations": self.get_minimum_number_of_finalization_confirmations( options @@ -46,25 +44,12 @@ def get_asset_create_arguments(self, options): def get_query_arguments(self, options): return { - "graph_location": self.get_graph_location(options), - "graph_state": self.get_graph_state(options), - "endpoint": self.get_endpoint(options), - "port": self.get_port(options), "max_number_of_retries": self.get_max_number_of_retries(options), "frequency": self.get_frequency(options), - "auth_token": self.get_auth_token(options), "paranet_ual": self.get_paranet_ual(options), "repository": self.get_repository(options), } - def get_endpoint(self, options): - return ( - options.get("endpoint") or self.manager.node_provider.endpoint_uri or None - ) - - def get_port(self, options): - return options.get("port") or DefaultParameters.PORT.value - def get_max_number_of_retries(self, options): return ( options.get("max_number_of_retries") @@ -91,9 +76,6 @@ def get_validate(self, options): def get_output_format(self, options): return options.get("output_format") or DefaultParameters.OUTPUT_FORMAT.value - def get_auth_token(self, options): - return options.get("auth_token") or self.manager.node_provider.auth_token - def get_hash_function_id(self, options): return ( options.get("hash_function_id") or DefaultParameters.HASH_FUNCTION_ID.value @@ -134,20 +116,8 @@ def get_score_function_id(self, options): ) return ( - DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ - self.manager.blockchain_provider.environment - ][blockchain_id], + DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[enviroment][blockchain_name], ) - def get_graph_location(self, options): - return ( - options.get("graph_location") - or options.get("paranet_ual") - or DefaultParameters.GRAPH_LOCATION.value - ) - - def get_graph_state(self, options): - return options.get("graph_state") or DefaultParameters.GRAPH_STATE.value - def get_repository(self, options): - return options.get("repository") or "dkg" + return options.get("repository") or DefaultParameters.REPOSITORY.value diff --git a/examples/demo.py b/examples/demo.py index d07eaa4..ea2ab80 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -69,19 +69,22 @@ def print_json(json_dict: dict): start_time = time.time() create_asset_result = dkg.asset.create( content=content, - epochs_num=2, - minimum_number_of_finalization_confirmations=3, - minimum_number_of_node_replications=1, - token_amount=100, + options={ + "epochs_num": 2, + "minimum_number_of_finalization_confirmations": 3, + "minimum_number_of_node_replications": 1, + "token_amount": 100, + }, ) print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") print_json(create_asset_result) divider() -get_v8_test = dkg.asset.get( - "did:dkg:otp:20430/0xb4c24fc54bc811c2659c477b65da8648e499fd39/2353" -) +start_time = time.time() +get_v8_test = dkg.asset.get(create_asset_result.get("UAL")) +print(f"======================== ASSET GET in {time.time() - start_time} seconds") +print_json(get_v8_test) divider() From 089f5dd6af19e682fdb7587faa66cdaf557965aa Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 17:34:50 +0100 Subject: [PATCH 049/146] Add constants --- dkg/asset.py | 8 ++++---- dkg/constants.py | 18 ++++++++++++++++++ dkg/network.py | 4 ++-- dkg/utils/blockchain_request.py | 6 ------ 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 84173df..fe6b601 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -32,7 +32,6 @@ from hexbytes import HexBytes from dkg.constants import ( - DEFAULT_HASH_FUNCTION_ID, DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS, PRIVATE_ASSERTION_PREDICATE, PRIVATE_RESOURCE_PREDICATE, @@ -42,6 +41,7 @@ DEFAULT_RDF_FORMAT, Operations, OutputTypes, + DefaultParameters, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -746,7 +746,7 @@ def local_store( public_assertion_metadata["size"], content_asset_storage_address, public_assertion_id, - DEFAULT_HASH_FUNCTION_ID, + DefaultParameters.HASH_FUNCTION_ID.value, token_amount or BidSuggestionRange.LOW, )["bidSuggestion"] ) @@ -1065,7 +1065,7 @@ def extend_storing_period( latest_finalized_state_size, content_asset_storage_address, latest_finalized_state, - DEFAULT_HASH_FUNCTION_ID, + DefaultParameters.HASH_FUNCTION_ID.value, token_amount or BidSuggestionRange.LOW, )["bidSuggestion"] ) @@ -1124,7 +1124,7 @@ def add_tokens( latest_finalized_state_size, content_asset_storage_address, latest_finalized_state, - DEFAULT_HASH_FUNCTION_ID, + DefaultParameters.HASH_FUNCTION_ID.value, token_amount or BidSuggestionRange.LOW, )["bidSuggestion"] ) - sum(agreement_data.tokensInfo) diff --git a/dkg/constants.py b/dkg/constants.py index 7aa10a7..ceef7eb 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -60,6 +60,24 @@ class OutputTypes(Enum): JSONLD: str = "JSON-LD" +class Environments(Enum): + DEVELOPMENT: str = "development" + DEVNET: str = "devnet" + TESTNET: str = "testnet" + MAINNET: str = "mainnet" + + +class Blockchains(Enum): + HARDHAT_1: str = "hardhat1:31337" + HARDHAT_2: str = "hardhat2:31337" + BASE_DEVNET: str = "base:84532" + GNOSIS_DEVNET: str = "gnosis:10200" + NEUROWEB_DEVNET: str = "otp:20430" + BASE_TESTNET: str = "base:84532" + GNOSIS_TESTNET: str = "gnosis:10200" + NEUROWEB_TESTNET: str = "otp:20430" + + ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" BLOCKCHAINS = { "development": { diff --git a/dkg/network.py b/dkg/network.py index 47f4fbc..405baa2 100644 --- a/dkg/network.py +++ b/dkg/network.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -from dkg.constants import DEFAULT_HASH_FUNCTION_ID +from dkg.constants import DefaultParameters from dkg.dataclasses import BidSuggestionRange from dkg.manager import DefaultRequestManager from dkg.method import Method @@ -50,7 +50,7 @@ def get_bid_suggestion( size_in_bytes, content_asset_storage_address, public_assertion_id, - DEFAULT_HASH_FUNCTION_ID, + DefaultParameters.HASH_FUNCTION_ID.value, range, ) diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index f351765..f8d1bd8 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -462,9 +462,3 @@ class BlockchainRequest: "knowledgeAssetArgs": dict, }, ) - - decrease_allowance = ContractTransaction( - contract="Token", - function="decreaseAllowance", - args={"spender": Address, "subtractedValue": int}, - ) From e2278165cb2002685a14919cd805397b71825912 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 09:33:51 +0100 Subject: [PATCH 050/146] Update demo --- examples/demo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/demo.py b/examples/demo.py index ea2ab80..77e35f4 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -20,11 +20,12 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider +from dkg.constants import Environments, Blockchains node_provider = NodeHTTPProvider(endpoint_uri="http://localhost:8900", api_version="v1") blockchain_provider = BlockchainProvider( - "development", - "hardhat1:31337", + Environments.DEVELOPMENT.value, + Blockchains.HARDHAT_1.value, ) dkg = DKG(node_provider, blockchain_provider) From 4c5e9e88479e24fe817f8cdf390cae7f6dcf2460 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 11:15:00 +0100 Subject: [PATCH 051/146] Fix decrease allowance issue --- dkg/asset.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index fe6b601..09b1f45 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -42,6 +42,7 @@ Operations, OutputTypes, DefaultParameters, + ZERO_ADDRESS, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -279,7 +280,7 @@ def finality_status( return finality def increase_knowledge_collection_allowance( - self, sender: str, token_amount: str + self, sender: str, token_amount: str, knowledge_collection_address: str ) -> AllowanceResult: """ Increases the allowance for knowledge collection if necessary. @@ -291,8 +292,6 @@ def increase_knowledge_collection_allowance( Returns: AllowanceResult containing whether allowance was increased and the gap """ - knowledge_collection_address = self._get_contract_address("KnowledgeCollection") - allowance = self._get_current_allowance(sender, knowledge_collection_address) allowance_gap = int(token_amount) - int(allowance) @@ -327,18 +326,19 @@ def create_knowledge_collection( BlockchainError: If the collection creation fails """ sender = self.manager.blockchain_provider.account.address - service_agreement_v1_address = None + knowledge_collection_address = self._get_contract_address("KnowledgeCollection") allowance_increased = False allowance_gap = 0 try: # Handle allowance - if request.get("payer"): + if request.get("paymaster") and request.get("paymaster") != ZERO_ADDRESS: pass else: allowance_result = self.increase_knowledge_collection_allowance( sender=sender, token_amount=request.get("tokenAmount"), + knowledge_collection_address=knowledge_collection_address, ) allowance_increased = allowance_result.allowance_increased allowance_gap = allowance_result.allowance_gap @@ -384,7 +384,7 @@ def create_knowledge_collection( except Exception as e: if allowance_increased: - self._decrease_allowance(service_agreement_v1_address, allowance_gap) + self._decrease_allowance(knowledge_collection_address, allowance_gap) raise e def process_content(self, content: str) -> list: From 1397a896ebc93b20682755e1aa851daeb61a7205 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 12:55:15 +0100 Subject: [PATCH 052/146] remove local store from constants --- dkg/constants.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dkg/constants.py b/dkg/constants.py index ceef7eb..515b108 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -139,7 +139,6 @@ class Blockchains(Enum): class Operations(Enum): PUBLISH = "publish" GET = "get" - LOCAL_STORE = "local-store" QUERY = "query" PUBLISH_PARANET = "publishParanet" FINALITY = "finality" From 4f6534db822b357da1711019d2d06f10646e6f58 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 13:32:37 +0100 Subject: [PATCH 053/146] Update demo jsonld and query --- examples/demo.py | 84 ++++++++++++++---------------------------------- 1 file changed, 25 insertions(+), 59 deletions(-) diff --git a/examples/demo.py b/examples/demo.py index 77e35f4..4b56b6e 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -42,22 +42,30 @@ def print_json(json_dict: dict): content = { - "private": { - "@context": "https://www.schema.org", - "@id": "urn:eu-pp:safety-test:3oRIwPtUOJapwNSAGZTzCOWR9bEo", - "@type": "ProductSafetyTest", - "testType": "Functional Safety Test", - "testResults": "Fail", - "relatedProduct": [ - { - "@id": "urn:epc:id:sgtin:59G1yu8uivSRKLLu", - "name": "59G1yu8uivSRKLLu", + "public": { + "@context": "https://schema.org", + "@id": "https://ford.mustang/2024", + "@type": "Car", + "name": "Ford Mustang", + "brand": {"@type": "Brand", "name": "Ford"}, + "model": "Mustang", + "manufacturer": {"@type": "Organization", "name": "Ford Motor Company"}, + "fuelType": "Gasoline", + "numberOfDoors": 2, + "vehicleEngine": { + "@type": "EngineSpecification", + "engineType": "V8", + "enginePower": { + "@type": "QuantitativeValue", + "value": "450", + "unitCode": "BHP", }, - ], - }, + }, + "driveWheelConfiguration": "RWD", + "speed": {"@type": "QuantitativeValue", "value": "240", "unitCode": "KMH"}, + } } - divider() info_result = dkg.node.info @@ -91,54 +99,12 @@ def print_json(json_dict: dict): query_operation_result = dkg.graph.query( """ - PREFIX gs1: - PREFIX schema: - SELECT ?recipeNameRaw ?baseUal - WHERE { - ?recipe a schema:Recipe ; - GRAPH ?ual { - ?recipe schema:name ?recipeNameRaw ; - } - FILTER (STRSTARTS(STR(?ual), "did:dkg:base:84532/0x4e8ebfce9a0f4be374709f1ef2791e8ca6371ecb/")) - BIND (REPLACE(STR(?ual), "(did:dkg:base:[^/]+/[^/]+/[^/]+)(/.*)?", "$1") AS ?baseUal) - } - """ -) -print("======================== ASSET QUERY") -print(query_operation_result) - -divider() - -query_operation_result = dkg.graph.query( - """ - CONSTRUCT { ?s ?p ?o .} - WHERE { - GRAPH ?g { ?s ?p ?o . } - VALUES ?g { - - - } - } - """ -) -print("======================== ASSET QUERY") -print(query_operation_result) - -divider() - -query_operation_result = dkg.graph.query( - """ - CONSTRUCT { ?s ?p ?o . } + PREFIX SCHEMA: + SELECT ?s ?modelName WHERE { - { - GRAPH { ?s ?p ?o . } - } - UNION - { - GRAPH { ?s ?p ?o . } - } + ?s schema:model ?modelName . } """ ) print("======================== ASSET QUERY") -print(query_operation_result) +print_json(query_operation_result) From f22a5c2baf3a9142ca6b1647a59fa65fd600bac4 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 13:59:07 +0100 Subject: [PATCH 054/146] Update demo --- examples/demo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/demo.py b/examples/demo.py index 4b56b6e..b802045 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -91,9 +91,9 @@ def print_json(json_dict: dict): divider() start_time = time.time() -get_v8_test = dkg.asset.get(create_asset_result.get("UAL")) +get_result = dkg.asset.get(create_asset_result.get("UAL")) print(f"======================== ASSET GET in {time.time() - start_time} seconds") -print_json(get_v8_test) +print_json(get_result) divider() From 4ee73c0beb37a743cfff6eada8de6adab75f78c5 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 15:25:19 +0100 Subject: [PATCH 055/146] Remove local_store, service_agreeement functions and add_tokens --- dkg/asset.py | 265 +------------------------------- dkg/utils/blockchain_request.py | 21 --- dkg/utils/node_request.py | 7 +- 3 files changed, 3 insertions(+), 290 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 09b1f45..70b57d9 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -17,13 +17,11 @@ import json import time -import math import hashlib -from typing import Literal, Type, Dict, Optional, Any +from typing import Literal, Dict, Optional, Any from pyld import jsonld from web3 import Web3 from web3.constants import ADDRESS_ZERO -from web3.exceptions import ContractLogicError from web3.types import TxReceipt from itertools import chain from eth_abi.packed import encode_packed @@ -32,7 +30,6 @@ from hexbytes import HexBytes from dkg.constants import ( - DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS, PRIVATE_ASSERTION_PREDICATE, PRIVATE_RESOURCE_PREDICATE, PRIVATE_HASH_SUBJECT_PREFIX, @@ -49,32 +46,23 @@ NodeResponseDict, ) from dkg.exceptions import ( - InvalidTokenAmount, OperationNotFinished, ) from dkg.manager import DefaultRequestManager from dkg.method import Method from dkg.module import Module -from dkg.types import JSONLD, UAL, Address, AgreementData, HexStr, Wei +from dkg.types import JSONLD, UAL, Address, HexStr, Wei from dkg.utils.blockchain_request import ( BlockchainRequest, KnowledgeCollectionResult, AllowanceResult, ) from dkg.utils.decorators import retry -from dkg.utils.merkle import MerkleTree, hash_assertion_with_indexes -from dkg.utils.metadata import ( - generate_agreement_id, - generate_assertion_metadata, - generate_keyword, -) from dkg.utils.node_request import ( NodeRequest, OperationStatus, - StoreTypes, validate_operation_status, ) -from dkg.utils.rdf import format_content from dkg.utils.ual import format_ual, parse_ual import dkg.utils.knowledge_collection_tools as kc_tools import dkg.utils.knowledge_asset_tools as ka_tools @@ -152,62 +140,10 @@ def is_valid_ual(self, ual: UAL) -> bool: _get_contract_address = Method(BlockchainRequest.get_contract_address) _get_current_allowance = Method(BlockchainRequest.allowance) - - def get_current_allowance(self, spender: Address | None = None) -> Wei: - if spender is None: - spender = self._get_contract_address("ServiceAgreementV1") - - return int( - self._get_current_allowance( - self.manager.blockchain_provider.account.address, spender - ) - ) - _increase_allowance = Method(BlockchainRequest.increase_allowance) _decrease_allowance = Method(BlockchainRequest.decrease_allowance) - - def set_allowance(self, token_amount: Wei, spender: Address | None = None) -> Wei: - if spender is None: - spender = self._get_contract_address("ServiceAgreementV1") - - current_allowance = self.get_current_allowance(spender) - - allowance_difference = token_amount - current_allowance - - if allowance_difference > 0: - self._increase_allowance(spender, allowance_difference) - elif allowance_difference < 0: - self._decrease_allowance(spender, -allowance_difference) - - return allowance_difference - - def increase_allowance( - self, token_amount: Wei, spender: Address | None = None - ) -> Wei: - if spender is None: - spender = self._get_contract_address("ServiceAgreementV1") - - self._increase_allowance(spender, token_amount) - - return token_amount - - def decrease_allowance( - self, token_amount: Wei, spender: Address | None = None - ) -> Wei: - if spender is None: - spender = self._get_contract_address("ServiceAgreementV1") - - current_allowance = self.get_current_allowance(spender) - subtracted_value = min(token_amount, current_allowance) - - self._decrease_allowance(spender, subtracted_value) - - return subtracted_value - _chain_id = Method(BlockchainRequest.chain_id) - _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) - _create = Method(BlockchainRequest.create_asset) _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) @@ -216,13 +152,10 @@ def decrease_allowance( BlockchainRequest.get_stake_weighted_average_ask ) _get_bid_suggestion = Method(NodeRequest.bid_suggestion) - _local_store = Method(NodeRequest.local_store) _publish = Method(NodeRequest.publish) _finality_status = Method(NodeRequest.finality_status) - _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) - _decrease_allowance = Method(BlockchainRequest.decrease_allowance) def get_operation_status_object( self, operation_result: Dict[str, Any], operation_id: str @@ -716,133 +649,6 @@ def create( ) ) - def local_store( - self, - content: dict[Literal["public", "private"], JSONLD], - epochs_number: int, - token_amount: Wei | None = None, - immutable: bool = False, - content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - paranet_ual: UAL | None = None, - ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: - blockchain_id = self.manager.blockchain_provider.blockchain_id - assertions = format_content(content, content_type) - - public_assertion_id = MerkleTree( - hash_assertion_with_indexes(assertions["public"]), - sort_pairs=True, - ).root - public_assertion_metadata = generate_assertion_metadata(assertions["public"]) - - content_asset_storage_address = self._get_asset_storage_address( - "ContentAssetStorage" - ) - - if token_amount is None: - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - epochs_number, - public_assertion_metadata["size"], - content_asset_storage_address, - public_assertion_id, - DefaultParameters.HASH_FUNCTION_ID.value, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] - ) - - current_allowance = self.get_current_allowance() - if is_allowance_increased := current_allowance < token_amount: - self.increase_allowance(token_amount) - - result = {"publicAssertionId": public_assertion_id, "operation": {}} - - try: - receipt: TxReceipt = self._create( - { - "assertionId": Web3.to_bytes(hexstr=public_assertion_id), - "size": public_assertion_metadata["size"], - "triplesNumber": public_assertion_metadata["triples_number"], - "chunksNumber": public_assertion_metadata["chunks_number"], - "tokenAmount": token_amount, - "epochsNumber": epochs_number, - "scoreFunctionId": DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ - self.manager.blockchain_provider.environment - ][blockchain_id], - "immutable_": immutable, - } - ) - except ContractLogicError as err: - if is_allowance_increased: - self.decrease_allowance(token_amount) - raise err - - events = self.manager.blockchain_provider.decode_logs_event( - receipt, - "ContentAsset", - "AssetMinted", - ) - token_id = events[0].args["tokenId"] - - result["UAL"] = format_ual( - blockchain_id, content_asset_storage_address, token_id - ) - result["operation"]["mintKnowledgeAsset"] = json.loads(Web3.to_json(receipt)) - - assertions_list = [ - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": public_assertion_id, - "assertion": assertions["public"], - "storeType": StoreTypes.TRIPLE_PARANET, - "paranetUAL": paranet_ual, - } - ] - - if content.get("private", None): - assertions_list.append( - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": MerkleTree( - hash_assertion_with_indexes(assertions["private"]), - sort_pairs=True, - ).root, - "assertion": assertions["private"], - "storeType": StoreTypes.TRIPLE_PARANET, - "paranetUAL": paranet_ual, - } - ) - - operation_id = self._local_store(assertions_list)["operationId"] - operation_result = self.get_operation_result(operation_id, "local-store") - - result["operation"]["localStore"] = { - "operationId": operation_id, - "status": operation_result["status"], - } - - if operation_result["status"] == OperationStatus.COMPLETED: - parsed_paranet_ual = parse_ual(paranet_ual) - paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( - parsed_paranet_ual["contract_address"], - parsed_paranet_ual["token_id"], - ) - - receipt: TxReceipt = self._submit_knowledge_asset( - paranet_knowledge_asset_storage, - paranet_knowledge_asset_token_id, - content_asset_storage_address, - token_id, - ) - - result["operation"]["submitToParanet"] = json.loads(Web3.to_json(receipt)) - - return result - _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) def submit_to_paranet( @@ -1081,80 +887,13 @@ def extend_storing_period( _get_block = Method(BlockchainRequest.get_block) - _get_service_agreement_data = Method(BlockchainRequest.get_service_agreement_data) _get_assertion_size = Method(BlockchainRequest.get_assertion_size) - _add_tokens = Method(BlockchainRequest.increase_asset_token_amount) - - def add_tokens( - self, - ual: UAL, - token_amount: Wei | None = None, - ) -> dict[str, UAL | TxReceipt]: - parsed_ual = parse_ual(ual) - blockchain_id, content_asset_storage_address, token_id = ( - parsed_ual["blockchain"], - parsed_ual["contract_address"], - parsed_ual["token_id"], - ) - - if token_amount is None: - agreement_id = self.get_agreement_id( - content_asset_storage_address, token_id - ) - # TODO: Dynamic types for namedtuples? - agreement_data: Type[AgreementData] = self._get_service_agreement_data( - agreement_id - ) - - timestamp_now = self._get_block("latest")["timestamp"] - current_epoch = math.floor( - (timestamp_now - agreement_data.startTime) / agreement_data.epochLength - ) - epochs_left = agreement_data.epochsNumber - current_epoch - - latest_finalized_state = self._get_latest_assertion_id(token_id) - latest_finalized_state_size = self._get_assertion_size( - latest_finalized_state - ) - - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - epochs_left, - latest_finalized_state_size, - content_asset_storage_address, - latest_finalized_state, - DefaultParameters.HASH_FUNCTION_ID.value, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] - ) - sum(agreement_data.tokensInfo) - - if token_amount <= 0: - raise InvalidTokenAmount( - "Token amount is bigger than default suggested amount, " - "please specify exact token_amount if you still want to add " - "more tokens!" - ) - - receipt: TxReceipt = self._add_tokens(token_id, token_amount) - - return { - "UAL": ual, - "operation": json.loads(Web3.to_json(receipt)), - } def get_owner(self, ual: UAL) -> Address: token_id = parse_ual(ual)["token_id"] return self._owner(token_id) - _get_assertion_id_by_index = Method(BlockchainRequest.get_assertion_id_by_index) - - def get_agreement_id(self, contract_address: Address, token_id: int) -> HexStr: - first_assertion_id = self._get_assertion_id_by_index(token_id, 0) - keyword = generate_keyword(contract_address, first_assertion_id) - return generate_agreement_id(contract_address, token_id, keyword) - _get_operation_result = Method(NodeRequest.get_operation_result) def get_operation_result( diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index f8d1bd8..3b4beda 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -119,11 +119,6 @@ class BlockchainRequest: args={"spender": Address, "subtractedValue": Wei}, ) - create_asset = ContractTransaction( - contract="ContentAsset", - function="createAsset", - args={"args": dict[str, bytes | int | Wei | bool]}, - ) burn_asset = ContractTransaction( contract="ContentAsset", function="burnAsset", @@ -134,11 +129,6 @@ class BlockchainRequest: function="extendAssetStoringPeriod", args={"tokenId": int, "epochsNumber": int, "tokenAmount": int}, ) - increase_asset_token_amount = ContractTransaction( - contract="ContentAsset", - function="increaseAssetTokenAmount", - args={"tokenId": int, "tokenAmount": int}, - ) transfer_asset = ContractTransaction( contract="ContentAssetStorage", @@ -150,11 +140,6 @@ class BlockchainRequest: function="getAssertionIds", args={"tokenId": int}, ) - get_assertion_id_by_index = ContractCall( - contract="ContentAssetStorage", - function="getAssertionIdByIndex", - args={"tokenId": int, "index": int}, - ) get_latest_assertion_id = ContractCall( contract="ContentAssetStorage", function="getLatestAssertionId", @@ -172,12 +157,6 @@ class BlockchainRequest: args={"tokenId": int}, ) - get_service_agreement_data = ContractCall( - contract="ServiceAgreementStorageProxy", - function="getAgreementData", - args={"agreementId": bytes | HexStr}, - ) - get_assertion_size = ContractCall( contract="AssertionStorage", function="getAssertionSize", diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index a95d983..e7f937f 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -21,7 +21,7 @@ from dkg.dataclasses import BidSuggestionRange, HTTPRequestMethod from dkg.exceptions import OperationFailed, OperationNotFinished -from dkg.types import AutoStrEnumUpperCase, UAL, Address, DataHexStr, NQuads +from dkg.types import AutoStrEnumUpperCase, UAL, Address, DataHexStr @dataclass @@ -52,11 +52,6 @@ class NodeRequest: path="{operation}/{operation_id}", ) - local_store = NodeCall( - method=HTTPRequestMethod.POST, - path="local-store", - data=list[dict[str, str | Address | NQuads]], - ) publish = NodeCall( method=HTTPRequestMethod.POST, path="publish", From 8579b92ef2b14849b6c8aee9f86863ac09ecfb0e Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 15:33:52 +0100 Subject: [PATCH 056/146] Add mainnet info to constants --- dkg/constants.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/dkg/constants.py b/dkg/constants.py index 515b108..2f0dfdf 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -76,6 +76,9 @@ class Blockchains(Enum): BASE_TESTNET: str = "base:84532" GNOSIS_TESTNET: str = "gnosis:10200" NEUROWEB_TESTNET: str = "otp:20430" + BASE_MAINNET: str = "base:8453" + GNOSIS_MAINNET: str = "gnosis:100" + NEUROWEB_MAINNET: str = "otp:2043" ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" @@ -110,7 +113,20 @@ class Blockchains(Enum): "rpc": "https://lofar-testnet.origin-trail.network", }, }, - "mainnet": {}, + "mainnet": { + "base:8453": { + "hub": "0x99Aa571fD5e681c2D27ee08A7b7989DB02541d13", + "rpc": "https://mainnet.base.org", + }, + "gnosis:100": { + "hub": "0x882D0BF07F956b1b94BBfe9E77F47c6fc7D4EC8f", + "rpc": "https://rpc.gnosischain.com/", + }, + "otp:2043": { + "hub": "0x0957e25BD33034948abc28204ddA54b6E1142D6F", + "rpc": "https://astrosat-parachain-rpc.origin-trail.network", + }, + }, } DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS = { From 110be089a82df69c90d5c9d51cea76dcc17bc873 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 15:36:21 +0100 Subject: [PATCH 057/146] change default environment from testnet to mainnet --- dkg/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dkg/constants.py b/dkg/constants.py index 2f0dfdf..277b9bd 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -35,7 +35,7 @@ class DefaultParameters(Enum): - ENVIRONMENT: str = "testnet" + ENVIRONMENT: str = "mainnet" PORT: int = 8900 FREQUENCY: int = 5 MAX_NUMBER_OF_RETRIES: int = 5 From b70eb571e07224bd9e32524918487899d011505c Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 16:00:08 +0100 Subject: [PATCH 058/146] bind graph.create and graph.get to asset --- dkg/main.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dkg/main.py b/dkg/main.py index 00fd427..bf417b0 100644 --- a/dkg/main.py +++ b/dkg/main.py @@ -70,6 +70,10 @@ def __init__( } self._attach_modules(modules) + # Backwards compatibility + self.graph.get = self.asset.get.__get__(self.asset) + self.graph.create = self.asset.create.__get__(self.asset) + def initialize_services(self, manager): self.input_service = InputService(manager) From 6861cecab6e6c57b6f7d4ef1f7f72a680a0e28a9 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Sun, 12 Jan 2025 12:09:39 +0100 Subject: [PATCH 059/146] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 14d8c04..3f15b5f 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ Inside of previously generated folder you will find activate script in bin folde source /path/to/folder/bin/activate ``` -Install dependencies: +Install dependencies and configure pre-commit hooks: ```bash make install From cd37a86b06c56972fca2d531fe05c10f19827aef Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Sun, 12 Jan 2025 12:42:46 +0100 Subject: [PATCH 060/146] Run github ruff action on PRs only --- .github/workflows/ruff.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml index 2c327fc..36c51b4 100644 --- a/.github/workflows/ruff.yml +++ b/.github/workflows/ruff.yml @@ -1,5 +1,5 @@ name: Ruff -on: [push, pull_request] +on: [pull_request] jobs: ruff: runs-on: ubuntu-latest From 3ac73ffdef6a4c4fc62375894160ed13d440bf1d Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 13 Jan 2025 08:57:55 +0100 Subject: [PATCH 061/146] bump version num --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b48f6ab..d8dffaf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.0a3" +version = "8.0.0a4" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar "] license = "Apache-2.0" From 052d9276ee3c65d3de04dde1a46281c02ff73603 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 13 Jan 2025 09:08:50 +0100 Subject: [PATCH 062/146] lint and format --- dkg/types/__init__.py | 22 +++++++++++----------- examples/curated_paranets_demo.py | 9 ++++----- examples/paranets_demo.py | 3 ++- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/dkg/types/__init__.py b/dkg/types/__init__.py index 416728b..c9ad40e 100644 --- a/dkg/types/__init__.py +++ b/dkg/types/__init__.py @@ -1,17 +1,17 @@ from .general import ( - AutoStrEnum, - AutoStrEnumCapitalize, - AutoStrEnumUpperCase, -) # NOQA: F401 + AutoStrEnum, # NOQA: F401 + AutoStrEnumCapitalize, # NOQA: F401 + AutoStrEnumUpperCase, # NOQA: F401 +) from .blockchain import ( - ABI, - ABIElement, - ABIError, + ABI, # NOQA: F401 + ABIElement, # NOQA: F401 + ABIError, # NOQA: F401 ABIEvent, # NOQA: F401 - ABIFunction, - ABIParameter, - AgreementData, - Environment, + ABIFunction, # NOQA: F401 + ABIParameter, # NOQA: F401 + AgreementData, # NOQA: F401 + Environment, # NOQA: F401 ) from .dkg_node import UAL # NOQA: F401 from .encoding import BytesLike, DataHexStr, HexStr # NOQA: F401 diff --git a/examples/curated_paranets_demo.py b/examples/curated_paranets_demo.py index 600059c..b328afa 100644 --- a/examples/curated_paranets_demo.py +++ b/examples/curated_paranets_demo.py @@ -16,13 +16,11 @@ # under the License. import json -import time from hexbytes import HexBytes from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider -from dkg.dataclasses import ParanetNodesAccessPolicy, ParanetMinersAccessPolicy node_provider = NodeHTTPProvider("http://localhost:8900") blockchain_provider = BlockchainProvider( @@ -61,6 +59,7 @@ node2_identity_id = dkg.node.get_identity_id(dkg2.blockchain_provider.account.address) node3_identity_id = dkg.node.get_identity_id(dkg3.blockchain_provider.account.address) + def divider(): print("==================================================") print("==================================================") @@ -73,7 +72,7 @@ def convert_hexbytes(data): return {k: convert_hexbytes(v) for k, v in data.items()} elif isinstance(data, list): return [convert_hexbytes(i) for i in data] - elif isinstance(data, tuple) and hasattr(data, '_asdict'): + elif isinstance(data, tuple) and hasattr(data, "_asdict"): return convert_hexbytes(data._asdict()) elif isinstance(data, bytes): return data.decode("utf-8") @@ -211,7 +210,7 @@ def convert_hexbytes(data): # divider() -paranet_ual = 'did:dkg:hardhat2:31337/0x8aafc28174bb6c3bdc7be92f18c2f134e876c05e/1' +paranet_ual = "did:dkg:hardhat2:31337/0x8aafc28174bb6c3bdc7be92f18c2f134e876c05e/1" local_store_first_asset_result = dkg3.asset.local_store( paranet_data, @@ -241,4 +240,4 @@ def convert_hexbytes(data): ) print(local_store_second_asset_result) -divider() \ No newline at end of file +divider() diff --git a/examples/paranets_demo.py b/examples/paranets_demo.py index b4e64cc..c089176 100644 --- a/examples/paranets_demo.py +++ b/examples/paranets_demo.py @@ -32,6 +32,7 @@ dkg = DKG(node_provider, blockchain_provider) + def divider(): print("==================================================") print("==================================================") @@ -77,7 +78,7 @@ def convert_hexbytes(data): "TestParanet", "TestParanetDescription", ParanetNodesAccessPolicy.OPEN, - ParanetMinersAccessPolicy.OPEN + ParanetMinersAccessPolicy.OPEN, ) print("======================== PARANET CREATED") From 03754a46ebb05e8f0a921748eed03c03092463ae Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 13 Jan 2025 13:04:29 +0100 Subject: [PATCH 063/146] Rename variable in constants and remove duplicate functions --- dkg/constants.py | 4 ++-- dkg/utils/blockchain_request.py | 9 --------- examples/demo.py | 4 ++-- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/dkg/constants.py b/dkg/constants.py index 277b9bd..523ae1b 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -67,12 +67,12 @@ class Environments(Enum): MAINNET: str = "mainnet" -class Blockchains(Enum): +class BlockchainIds(Enum): HARDHAT_1: str = "hardhat1:31337" HARDHAT_2: str = "hardhat2:31337" BASE_DEVNET: str = "base:84532" GNOSIS_DEVNET: str = "gnosis:10200" - NEUROWEB_DEVNET: str = "otp:20430" + NEUROWEB_DEVNET: str = "otp:2160" BASE_TESTNET: str = "base:84532" GNOSIS_TESTNET: str = "gnosis:10200" NEUROWEB_TESTNET: str = "otp:20430" diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index 3b4beda..a1f87f8 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -314,15 +314,6 @@ class BlockchainRequest: "paranetServiceAddresses": list[Address], }, ) - mint_knowledge_asset = ContractTransaction( - contract="Paranet", - function="mintKnowledgeAsset", - args={ - "paranetKAStorageContract": Address, - "paranetKATokenId": int, - "knowledgeAssetArgs": dict[str, bytes | int | Wei | bool], - }, - ) submit_knowledge_asset = ContractTransaction( contract="Paranet", function="submitKnowledgeAsset", diff --git a/examples/demo.py b/examples/demo.py index b802045..d6e99ce 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -20,12 +20,12 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider -from dkg.constants import Environments, Blockchains +from dkg.constants import Environments, BlockchainIds node_provider = NodeHTTPProvider(endpoint_uri="http://localhost:8900", api_version="v1") blockchain_provider = BlockchainProvider( Environments.DEVELOPMENT.value, - Blockchains.HARDHAT_1.value, + BlockchainIds.HARDHAT_1.value, ) dkg = DKG(node_provider, blockchain_provider) From 2f7c6c0983853111db3dff1fd37200c8b230c84d Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 13 Jan 2025 13:50:29 +0100 Subject: [PATCH 064/146] PR suggestions --- dkg/asset.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 70b57d9..c3bd7e1 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -212,6 +212,13 @@ def finality_status( return finality + def decrease_knowledge_collection_allowance( + self, + allowance_gap: int, + ): + knowledge_collection_address = self._get_contract_address("KnowledgeCollection") + self._decrease_allowance(knowledge_collection_address, allowance_gap) + def increase_knowledge_collection_allowance( self, sender: str, token_amount: str, knowledge_collection_address: str ) -> AllowanceResult: @@ -225,6 +232,8 @@ def increase_knowledge_collection_allowance( Returns: AllowanceResult containing whether allowance was increased and the gap """ + knowledge_collection_address = self._get_contract_address("KnowledgeCollection") + allowance = self._get_current_allowance(sender, knowledge_collection_address) allowance_gap = int(token_amount) - int(allowance) @@ -259,7 +268,6 @@ def create_knowledge_collection( BlockchainError: If the collection creation fails """ sender = self.manager.blockchain_provider.account.address - knowledge_collection_address = self._get_contract_address("KnowledgeCollection") allowance_increased = False allowance_gap = 0 @@ -271,7 +279,6 @@ def create_knowledge_collection( allowance_result = self.increase_knowledge_collection_allowance( sender=sender, token_amount=request.get("tokenAmount"), - knowledge_collection_address=knowledge_collection_address, ) allowance_increased = allowance_result.allowance_increased allowance_gap = allowance_result.allowance_gap @@ -317,7 +324,7 @@ def create_knowledge_collection( except Exception as e: if allowance_increased: - self._decrease_allowance(knowledge_collection_address, allowance_gap) + self.decrease_knowledge_collection_allowance(allowance_gap) raise e def process_content(self, content: str) -> list: From b744c3b9170c445a8e556a722e0c85068a3f3692 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 13 Jan 2025 15:04:57 +0100 Subject: [PATCH 065/146] remove knowledge_collection_address as a param from increase_knowledge_collection_allowance --- dkg/asset.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dkg/asset.py b/dkg/asset.py index c3bd7e1..21c5da3 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -220,7 +220,9 @@ def decrease_knowledge_collection_allowance( self._decrease_allowance(knowledge_collection_address, allowance_gap) def increase_knowledge_collection_allowance( - self, sender: str, token_amount: str, knowledge_collection_address: str + self, + sender: str, + token_amount: str, ) -> AllowanceResult: """ Increases the allowance for knowledge collection if necessary. From b65f2fd585087305d0c81e45735b06b42ee5703b Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 14 Jan 2025 17:23:51 +0100 Subject: [PATCH 066/146] Decrease get operation speed + other improvements --- dkg/asset.py | 26 ++++++++++++-------------- dkg/providers/node_http.py | 14 +++++--------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 21c5da3..03e04f5 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -190,16 +190,6 @@ def finality_status( finality = 0 while finality < required_confirmations and retries <= max_number_of_retries: - try: - response = self._finality_status(ual) - finality = response.get("finality", 0) - if finality >= required_confirmations: - break - except Exception: - finality = 0 - - retries += 1 - if retries > max_number_of_retries: raise Exception( f"Unable to achieve required confirmations. " @@ -207,9 +197,17 @@ def finality_status( ) # Sleep between attempts (except for first try) - if retries > 1: + if retries > 0: time.sleep(frequency) + retries += 1 + + try: + response = self._finality_status(ual) + finality = response.get("finality", 0) + except Exception: + finality = 0 + return finality def decrease_knowledge_collection_allowance( @@ -628,8 +626,8 @@ def create( finality_status_result = self.finality_status( ual, minimum_number_of_finalization_confirmations, - 300, - 2, + max_number_of_retries, + frequency, ) return json.loads( @@ -912,7 +910,7 @@ def get_operation_result( catch=OperationNotFinished, max_retries=max_retries, base_delay=frequency, - backoff=2, + backoff=1, ) def retry_get_operation_result(): operation_result = self._get_operation_result( diff --git a/dkg/providers/node_http.py b/dkg/providers/node_http.py index 8316d6c..f8a122d 100644 --- a/dkg/providers/node_http.py +++ b/dkg/providers/node_http.py @@ -31,9 +31,8 @@ def __init__( api_version: str = "v1", auth_token: str | None = None, ): - self.endpoint_uri = URI(endpoint_uri) - self.api_version = api_version - self.auth_token = auth_token + self.url = f"{URI(endpoint_uri)}/{api_version}" + self.headers = {"Authorization": f"Bearer {auth_token}"} if auth_token else {} def make_request( self, @@ -42,16 +41,13 @@ def make_request( params: dict[str, Any] = {}, data: dict[str, Any] = {}, ) -> NodeResponseDict: - url = f"{self.endpoint_uri}/{self.api_version}/{path}" - headers = ( - {"Authorization": f"Bearer {self.auth_token}"} if self.auth_token else {} - ) + url = f"{self.url}/{path}" try: if method == HTTPRequestMethod.GET: - response = requests.get(url, params=params, headers=headers) + response = requests.get(url, params=params, headers=self.headers) elif method == HTTPRequestMethod.POST: - response = requests.post(url, json=data, headers=headers) + response = requests.post(url, json=data, headers=self.headers) else: raise HTTPRequestMethodNotSupported( f"{method.name} method isn't supported" From ae1d59c8adeec63600ac674dcb2721fd2c0181a3 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 16 Jan 2025 13:32:41 +0100 Subject: [PATCH 067/146] Added publish finality --- dkg/asset.py | 79 ++++------------------- dkg/constants.py | 8 +++ dkg/graph.py | 87 +++++++++++++++++-------- dkg/main.py | 8 ++- dkg/services/input_service.py | 18 +++++- dkg/services/node_service.py | 116 ++++++++++++++++++++++++++++++++++ dkg/utils/node_request.py | 10 +++ 7 files changed, 228 insertions(+), 98 deletions(-) create mode 100644 dkg/services/node_service.py diff --git a/dkg/asset.py b/dkg/asset.py index 03e04f5..c3642a9 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -16,7 +16,6 @@ # under the License. import json -import time import hashlib from typing import Literal, Dict, Optional, Any from pyld import jsonld @@ -45,9 +44,6 @@ BidSuggestionRange, NodeResponseDict, ) -from dkg.exceptions import ( - OperationNotFinished, -) from dkg.manager import DefaultRequestManager from dkg.method import Method from dkg.module import Module @@ -57,11 +53,9 @@ KnowledgeCollectionResult, AllowanceResult, ) -from dkg.utils.decorators import retry from dkg.utils.node_request import ( NodeRequest, OperationStatus, - validate_operation_status, ) from dkg.utils.ual import format_ual, parse_ual import dkg.utils.knowledge_collection_tools as kc_tools @@ -69,9 +63,10 @@ class KnowledgeAsset(Module): - def __init__(self, manager: DefaultRequestManager, input_service): + def __init__(self, manager: DefaultRequestManager, input_service, node_service): self.manager = manager self.input_service = input_service + self.node_service = node_service _owner = Method(BlockchainRequest.owner_of) @@ -153,7 +148,6 @@ def is_valid_ual(self, ual: UAL) -> bool: ) _get_bid_suggestion = Method(NodeRequest.bid_suggestion) _publish = Method(NodeRequest.publish) - _finality_status = Method(NodeRequest.finality_status) _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) @@ -179,37 +173,6 @@ def get_operation_status_object( return {"operationId": operation_id, **operation_data} - def finality_status( - self, - ual: str, - required_confirmations: int, - max_number_of_retries: int, - frequency: int, - ): - retries = 0 - finality = 0 - - while finality < required_confirmations and retries <= max_number_of_retries: - if retries > max_number_of_retries: - raise Exception( - f"Unable to achieve required confirmations. " - f"Max number of retries ({max_number_of_retries}) reached." - ) - - # Sleep between attempts (except for first try) - if retries > 0: - time.sleep(frequency) - - retries += 1 - - try: - response = self._finality_status(ual) - finality = response.get("finality", 0) - except Exception: - finality = 0 - - return finality - def decrease_knowledge_collection_allowance( self, allowance_gap: int, @@ -516,7 +479,7 @@ def create( hash_function_id, minimum_number_of_node_replications, )["operationId"] - publish_operation_result = self.get_operation_result( + publish_operation_result = self.node_service.get_operation_result( publish_operation_id, Operations.PUBLISH.value, max_number_of_retries, @@ -623,7 +586,7 @@ def create( finality_status_result = 0 if minimum_number_of_finalization_confirmations > 0: - finality_status_result = self.finality_status( + finality_status_result = self.node_service.finality_status( ual, minimum_number_of_finalization_confirmations, max_number_of_retries, @@ -644,10 +607,12 @@ def create( publish_operation_result, publish_operation_id ), "finality": { - "status": "FINALIZED" - if finality_status_result - >= minimum_number_of_finalization_confirmations - else "NOT FINALIZED" + "status": ( + "FINALIZED" + if finality_status_result + >= minimum_number_of_finalization_confirmations + else "NOT FINALIZED" + ) }, "numberOfConfirmations": finality_status_result, "requiredConfirmations": minimum_number_of_finalization_confirmations, @@ -753,7 +718,7 @@ def get(self, ual: UAL, options: dict = {}) -> dict: subject_ual, )["operationId"] - get_public_operation_result = self.get_operation_result( + get_public_operation_result = self.node_service.get_operation_result( get_public_operation_id, Operations.GET.value, max_number_of_retries, @@ -901,28 +866,6 @@ def get_owner(self, ual: UAL) -> Address: return self._owner(token_id) - _get_operation_result = Method(NodeRequest.get_operation_result) - - def get_operation_result( - self, operation_id: str, operation: str, max_retries: int, frequency: int - ): - @retry( - catch=OperationNotFinished, - max_retries=max_retries, - base_delay=frequency, - backoff=1, - ) - def retry_get_operation_result(): - operation_result = self._get_operation_result( - operation_id=operation_id, - operation=operation, - ) - validate_operation_status(operation_result) - - return operation_result - - return retry_get_operation_result() - def to_jsonld(self, nquads: str): options = { "algorithm": "URDNA2015", diff --git a/dkg/constants.py b/dkg/constants.py index 523ae1b..b3d7a07 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -1,4 +1,5 @@ from enum import Enum + # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -40,6 +41,7 @@ class DefaultParameters(Enum): FREQUENCY: int = 5 MAX_NUMBER_OF_RETRIES: int = 5 HASH_FUNCTION_ID: int = 1 + MIN_NUMBER_OF_FINALIZATION_CONF: int = 3 IMMUTABLE: bool = False VALIDATE: bool = True OUTPUT_FORMAT: str = "JSON-LD" @@ -81,6 +83,12 @@ class BlockchainIds(Enum): NEUROWEB_MAINNET: str = "otp:2043" +class OperationStatuses(str, Enum): + PENDING = "PENDING" + COMPLETED = "COMPLETED" + FAILED = "FAILED" + + ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" BLOCKCHAINS = { "development": { diff --git a/dkg/graph.py b/dkg/graph.py index 3c7fa28..55ebd19 100644 --- a/dkg/graph.py +++ b/dkg/graph.py @@ -17,24 +17,31 @@ from rdflib.plugins.sparql.parser import parseQuery -from dkg.dataclasses import NodeResponseDict -from dkg.exceptions import OperationNotFinished + from dkg.manager import DefaultRequestManager from dkg.method import Method from dkg.module import Module from dkg.types import NQuads -from dkg.utils.decorators import retry -from dkg.utils.node_request import NodeRequest, validate_operation_status +from dkg.utils.node_request import ( + NodeRequest, +) +from dkg.services.node_service import NodeService +from dkg.services.input_service import InputService from dkg.constants import Operations class Graph(Module): - def __init__(self, manager: DefaultRequestManager, input_service): + def __init__( + self, + manager: DefaultRequestManager, + input_service: InputService, + node_service: NodeService, + ): self.manager = manager self.input_service = input_service + self.node_service = node_service _query = Method(NodeRequest.query) - _get_operation_result = Method(NodeRequest.get_operation_result) def query( self, @@ -51,31 +58,61 @@ def query( parsed_query = parseQuery(query) query_type = parsed_query[1].name.replace("Query", "").upper() - operation_id: NodeResponseDict = self._query( - query, query_type, repository, paranet_ual - )["operationId"] - operation_result = self.get_operation_result( + result = self._query(query, query_type, repository, paranet_ual) + operation_id = result.get("operationId") + operation_result = self.node_service.get_operation_result( operation_id, Operations.QUERY.value, max_number_of_retries, frequency ) return operation_result["data"] - def get_operation_result( - self, operation_id: str, operation: str, max_retries: int, frequency: int - ): - @retry( - catch=OperationNotFinished, - max_retries=max_retries, - base_delay=frequency, - backoff=2, + def publish_finality(self, UAL, options=None): + if options is None: + options = {} + + arguments = self.input_service.get_publish_finality_arguments(options) + max_number_of_retries = arguments.get("max_number_of_retries") + minimum_number_of_finalization_confirmations = arguments.get( + "minimum_number_of_finalization_confirmations" ) - def retry_get_operation_result(): - operation_result = self._get_operation_result( - operation_id=operation_id, - operation=operation, + frequency = arguments.get("frequency") + try: + finality_status_result = self.node_service.finality_status( + UAL, + minimum_number_of_finalization_confirmations, + max_number_of_retries, + frequency, ) - validate_operation_status(operation_result) + except Exception as e: + return {"status": "ERROR", "error": str(e)} + + if finality_status_result == 0: + try: + finality_operation_id = self.node_service.finality( + UAL, + minimum_number_of_finalization_confirmations, + max_number_of_retries, + frequency, + ) + except Exception as e: + return {"status": "ERROR", "error": str(e)} - return operation_result + try: + return self.node_service.get_operation_result( + finality_operation_id, "finality", max_number_of_retries, frequency + ) + except Exception as e: + return {"status": "NOT FINALIZED", "error": str(e)} - return retry_get_operation_result() + elif finality_status_result >= minimum_number_of_finalization_confirmations: + return { + "status": "FINALIZED", + "numberOfConfirmations": finality_status_result, + "requiredConfirmations": minimum_number_of_finalization_confirmations, + } + else: + return { + "status": "NOT FINALIZED", + "numberOfConfirmations": finality_status_result, + "requiredConfirmations": minimum_number_of_finalization_confirmations, + } diff --git a/dkg/main.py b/dkg/main.py index bf417b0..71f1cce 100644 --- a/dkg/main.py +++ b/dkg/main.py @@ -29,6 +29,7 @@ from dkg.types import UAL, Address, ChecksumAddress from dkg.utils.ual import format_ual, parse_ual from dkg.services.input_service import InputService +from dkg.services.node_service import NodeService class DKG(Module): @@ -62,11 +63,13 @@ def __init__( modules = { "assertion": Assertion(self.manager), - "asset": KnowledgeAsset(self.manager, self.input_service), + "asset": KnowledgeAsset( + self.manager, self.input_service, self.node_service + ), "paranet": Paranet(self.manager), "network": Network(self.manager), "node": Node(self.manager), - "graph": Graph(self.manager, self.input_service), + "graph": Graph(self.manager, self.input_service, self.node_service), } self._attach_modules(modules) @@ -76,6 +79,7 @@ def __init__( def initialize_services(self, manager): self.input_service = InputService(manager) + self.node_service = NodeService(manager) @property def node_provider(self) -> NodeHTTPProvider: diff --git a/dkg/services/input_service.py b/dkg/services/input_service.py index 9efb31a..0864475 100644 --- a/dkg/services/input_service.py +++ b/dkg/services/input_service.py @@ -35,8 +35,7 @@ def get_asset_create_arguments(self, options): "payer": self.get_payer(options), "minimum_number_of_finalization_confirmations": self.get_minimum_number_of_finalization_confirmations( options - ) - or 3, + ), "minimum_number_of_node_replications": self.get_minimum_number_of_node_replications( options ), @@ -50,6 +49,15 @@ def get_query_arguments(self, options): "repository": self.get_repository(options), } + def get_publish_finality_arguments(self, options): + return { + "max_number_of_retries": self.get_max_number_of_retries(options), + "frequency": self.get_frequency(options), + "minimum_number_of_finalization_confirmations": self.get_minimum_number_of_finalization_confirmations( + options + ), + } + def get_max_number_of_retries(self, options): return ( options.get("max_number_of_retries") @@ -100,7 +108,11 @@ def get_payer(self, options): return options.get("payer") or ZERO_ADDRESS def get_minimum_number_of_finalization_confirmations(self, options): - return options.get("minimum_number_of_finalization_confirmations") or None + return ( + options.get("minimum_number_of_finalization_confirmations") + or DefaultParameters.MIN_NUMBER_OF_FINALIZATION_CONF.value + or None + ) def get_minimum_number_of_node_replications(self, options): return options.get("minimum_number_of_node_replications") or None diff --git a/dkg/services/node_service.py b/dkg/services/node_service.py new file mode 100644 index 0000000..c9f0eb7 --- /dev/null +++ b/dkg/services/node_service.py @@ -0,0 +1,116 @@ +from dkg.manager import DefaultRequestManager +from dkg.method import Method +from dkg.module import Module +import time +from dkg.utils.decorators import retry +from dkg.exceptions import ( + OperationNotFinished, +) +from dkg.utils.node_request import ( + NodeRequest, + validate_operation_status, +) + + +class NodeService(Module): + def __init__(self, manager: DefaultRequestManager): + self.manager = manager + + _get_operation_result = Method(NodeRequest.get_operation_result) + _finality_status = Method(NodeRequest.finality_status) + _finality = Method(NodeRequest.finality) + + def get_operation_result( + self, operation_id: str, operation: str, max_retries: int, frequency: int + ): + @retry( + catch=OperationNotFinished, + max_retries=max_retries, + base_delay=frequency, + backoff=1, + ) + def retry_get_operation_result(): + operation_result = self._get_operation_result( + operation_id=operation_id, + operation=operation, + ) + validate_operation_status(operation_result) + + return operation_result + + return retry_get_operation_result() + + def finality_status( + self, + ual: str, + required_confirmations: int, + max_number_of_retries: int, + frequency: int, + ): + retries = 0 + finality = 0 + + while finality < required_confirmations and retries <= max_number_of_retries: + if retries > max_number_of_retries: + raise Exception( + f"Unable to achieve required confirmations. " + f"Max number of retries ({max_number_of_retries}) reached." + ) + + if retries > 0: + time.sleep(frequency) + + retries += 1 + + try: + try: + response = self._finality_status(ual=ual) + except Exception as e: + response = None + print(f"failed: {e}") + + if response is not None: + finality = response.get("finality", 0) + if finality >= required_confirmations: + break + + except Exception: + finality = 0 + + return finality + + def finality(self, ual, required_confirmations, max_number_of_retries, frequency): + finality_id = 0 + retries = 0 + + while finality_id < required_confirmations and retries < max_number_of_retries: + if retries > max_number_of_retries: + raise Exception( + f"Unable to achieve required confirmations. " + f"Max number of retries ({max_number_of_retries}) reached." + ) + + if retries > 0: + time.sleep(frequency) + + retries += 1 + + try: + try: + response = self._finality( + ual=ual, minimumNumberOfNodeReplications=required_confirmations + ) + except Exception as e: + response = None + print(f"failed: {e}") + + if response is not None: + operation_id = response.json().get("operationId", 0) + if operation_id >= required_confirmations: + finality_id = operation_id + + except Exception as e: + finality_id = 0 + print(f"Retry {retries + 1}/{max_number_of_retries} failed: {e}") + + return finality_id diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index e7f937f..abb8e7d 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -64,6 +64,15 @@ class NodeRequest: }, ) + finality = NodeCall( + method=HTTPRequestMethod.POST, + path="ask", + params={ + "ual": UAL, + "minimumNumberOfNodeReplications": int, + }, + ) + finality_status = NodeCall( method=HTTPRequestMethod.GET, path="finality", @@ -82,6 +91,7 @@ class NodeRequest: "subjectUAL": UAL, }, ) + query = NodeCall( method=HTTPRequestMethod.POST, path="query", From 10199e6849ba989f9bb68f45231828752bd237ec Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 16 Jan 2025 13:50:25 +0100 Subject: [PATCH 068/146] Added comment to demo.py --- examples/demo.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/demo.py b/examples/demo.py index d6e99ce..8babe2f 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -23,6 +23,7 @@ from dkg.constants import Environments, BlockchainIds node_provider = NodeHTTPProvider(endpoint_uri="http://localhost:8900", api_version="v1") +# make sure that you have PRIVATE_KEY in .env so the blockchain provider can load it blockchain_provider = BlockchainProvider( Environments.DEVELOPMENT.value, BlockchainIds.HARDHAT_1.value, From 4d4e2457ac77ffaf8eda31d0f780a134c2ad39d2 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 16 Jan 2025 13:57:48 +0100 Subject: [PATCH 069/146] Added publish finality to demo --- examples/demo.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/demo.py b/examples/demo.py index 8babe2f..5a87625 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -109,3 +109,10 @@ def print_json(json_dict: dict): ) print("======================== ASSET QUERY") print_json(query_operation_result) + +start_time = time.time() +publish_finality_result = dkg.graph.publish_finality(create_asset_result.get("UAL")) +print( + f"======================== PUBLISH FINALITY in {time.time() - start_time} seconds" +) +print_json(publish_finality_result) From 5c5c676185a06692fca958d6af10c59bd54f217a Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 16 Jan 2025 15:09:44 +0100 Subject: [PATCH 070/146] Added options to create --- examples/demo.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/demo.py b/examples/demo.py index 5a87625..dff8b91 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -84,6 +84,9 @@ def print_json(json_dict: dict): "minimum_number_of_finalization_confirmations": 3, "minimum_number_of_node_replications": 1, "token_amount": 100, + "max_number_of_retries": 300, + "frequency": 2, + "content_type": "all", }, ) print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") From 4738923d5d9aa6993d9ff7500b9acf53f1d06e03 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 16 Jan 2025 15:15:43 +0100 Subject: [PATCH 071/146] Removed content type from create --- examples/demo.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/demo.py b/examples/demo.py index dff8b91..89febf9 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -86,7 +86,6 @@ def print_json(json_dict: dict): "token_amount": 100, "max_number_of_retries": 300, "frequency": 2, - "content_type": "all", }, ) print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") From cbb3180376f1b32516ef4dbc7ea3bee3f327f424 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 16 Jan 2025 16:21:22 +0100 Subject: [PATCH 072/146] Added config and added python-dotenv to dependecies --- dkg/main.py | 7 +-- dkg/providers/blockchain.py | 2 + dkg/services/input_service.py | 90 +++++++++++++++++++++++++++-------- examples/demo.py | 10 ++-- poetry.lock | 16 ++++++- pyproject.toml | 1 + 6 files changed, 97 insertions(+), 29 deletions(-) diff --git a/dkg/main.py b/dkg/main.py index 71f1cce..35d45b8 100644 --- a/dkg/main.py +++ b/dkg/main.py @@ -56,10 +56,11 @@ def __init__( self, node_provider: NodeHTTPProvider, blockchain_provider: BlockchainProvider, + config: dict = {}, ): self.manager = DefaultRequestManager(node_provider, blockchain_provider) - self.initialize_services(self.manager) + self.initialize_services(self.manager, config) modules = { "assertion": Assertion(self.manager), @@ -77,8 +78,8 @@ def __init__( self.graph.get = self.asset.get.__get__(self.asset) self.graph.create = self.asset.create.__get__(self.asset) - def initialize_services(self, manager): - self.input_service = InputService(manager) + def initialize_services(self, manager, config): + self.input_service = InputService(manager, config) self.node_service = NodeService(manager) @property diff --git a/dkg/providers/blockchain.py b/dkg/providers/blockchain.py index d7e6d26..9cdd5ff 100644 --- a/dkg/providers/blockchain.py +++ b/dkg/providers/blockchain.py @@ -17,6 +17,7 @@ import json import os +from dotenv import load_dotenv from collections import namedtuple from functools import wraps from pathlib import Path @@ -105,6 +106,7 @@ def __init__( } self._init_contracts() + load_dotenv() if private_key := os.environ.get("PRIVATE_KEY"): self.set_account(private_key) diff --git a/dkg/services/input_service.py b/dkg/services/input_service.py index 0864475..1f1184a 100644 --- a/dkg/services/input_service.py +++ b/dkg/services/input_service.py @@ -6,8 +6,9 @@ class InputService: - def __init__(self, manager): + def __init__(self, manager, config): self.manager = manager + self.config = config def get_asset_get_arguments(self, options): return { @@ -61,75 +62,122 @@ def get_publish_finality_arguments(self, options): def get_max_number_of_retries(self, options): return ( options.get("max_number_of_retries") + or self.config.get("max_number_of_retries") or DefaultParameters.MAX_NUMBER_OF_RETRIES.value ) def get_frequency(self, options): - return options.get("frequency") or DefaultParameters.FREQUENCY.value + return ( + options.get("frequency") + or self.config.get("frequency") + or DefaultParameters.FREQUENCY.value + ) def get_state(self, options): - return options.get("state") or DefaultParameters.STATE.value + return ( + options.get("state") + or self.config.get("state") + or DefaultParameters.STATE.value + ) def get_include_metadata(self, options): return ( - options.get("include_metadata") or DefaultParameters.INCLUDE_METADATA.value + options.get("include_metadata") + or self.config.get("include_metadata") + or DefaultParameters.INCLUDE_METADATA.value ) def get_content_type(self, options): - return options.get("content_type") or DefaultParameters.CONTENT_TYPE.value + return ( + options.get("content_type") + or self.config.get("content_type") + or DefaultParameters.CONTENT_TYPE.value + ) def get_validate(self, options): - return options.get("validate") or DefaultParameters.VALIDATE.value + return ( + options.get("validate") + or self.config.get("validate") + or DefaultParameters.VALIDATE.value + ) def get_output_format(self, options): - return options.get("output_format") or DefaultParameters.OUTPUT_FORMAT.value + return ( + options.get("output_format") + or self.config.get("output_format") + or DefaultParameters.OUTPUT_FORMAT.value + ) def get_hash_function_id(self, options): return ( - options.get("hash_function_id") or DefaultParameters.HASH_FUNCTION_ID.value + options.get("hash_function_id") + or self.config.get("hash_function_id") + or DefaultParameters.HASH_FUNCTION_ID.value ) def get_paranet_ual(self, options): - return options.get("paranet_ual") or DefaultParameters.PARANET_UAL.value + return ( + options.get("paranet_ual") + or self.config.get("paranet_ual") + or DefaultParameters.PARANET_UAL.value + ) def get_subject_ual(self, options): - return options.get("subject_ual") or DefaultParameters.GET_SUBJECT_UAL.value + return ( + options.get("subject_ual") + or self.config.get("subject_ual") + or DefaultParameters.GET_SUBJECT_UAL.value + ) def get_epochs_num(self, options): - return options.get("epochs_num") or None + return options.get("epochs_num") or self.config.get("epochs_num") or None def get_immutable(self, options): - return options.get("immutable") or DefaultParameters.IMMUTABLE.value + return ( + options.get("immutable") + or self.config.get("immutable") + or DefaultParameters.IMMUTABLE.value + ) def get_token_amount(self, options): - return options.get("token_amount") or None + return options.get("token_amount") or self.config.get("token_amount") or None def get_payer(self, options): - return options.get("payer") or ZERO_ADDRESS + return options.get("payer") or self.config.get("payer") or ZERO_ADDRESS def get_minimum_number_of_finalization_confirmations(self, options): return ( options.get("minimum_number_of_finalization_confirmations") + or self.config.get("minimum_number_of_finalization_confirmations") or DefaultParameters.MIN_NUMBER_OF_FINALIZATION_CONF.value or None ) def get_minimum_number_of_node_replications(self, options): - return options.get("minimum_number_of_node_replications") or None + return ( + options.get("minimum_number_of_node_replications") + or self.config.get("minimum_number_of_node_replications") + or None + ) def get_score_function_id(self, options): - enviroment = ( + environment = ( options.get("environment") + or self.config.get("environment") or self.manager.blockchain_provider.environment or DefaultParameters.ENVIRONMENT.value ) blockchain_name = ( - options.get("immutable") or self.manager.blockchain_provider.blockchain_id + options.get("blockchain") + or self.config.get("blockchain") + or self.manager.blockchain_provider.blockchain_id ) - return ( - DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[enviroment][blockchain_name], - ) + return DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[environment][blockchain_name] def get_repository(self, options): - return options.get("repository") or DefaultParameters.REPOSITORY.value + return ( + options.get("repository") + or self.config.get("repository") + or DefaultParameters.REPOSITORY.value + ) diff --git a/examples/demo.py b/examples/demo.py index 89febf9..47774c8 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -28,8 +28,12 @@ Environments.DEVELOPMENT.value, BlockchainIds.HARDHAT_1.value, ) - -dkg = DKG(node_provider, blockchain_provider) +# here you can create your own custom values that will be applied to all the functions +config = { + "max_number_of_retries": 300, + "frequency": 2, +} +dkg = DKG(node_provider, blockchain_provider, config) def divider(): @@ -84,8 +88,6 @@ def print_json(json_dict: dict): "minimum_number_of_finalization_confirmations": 3, "minimum_number_of_node_replications": 1, "token_amount": 100, - "max_number_of_retries": 300, - "frequency": 2, }, ) print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") diff --git a/poetry.lock b/poetry.lock index a356006..d705237 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1604,6 +1604,20 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "pytz" version = "2023.3.post1" @@ -2193,4 +2207,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "813bd256188ce10066e839eb8a7d52f34cc54270c106011fa3504e158bb807eb" +content-hash = "2bd261f92e6198e0e7c08d6c5dfa8a4a7852dd59a2119c7c0b453cbaa31612bd" diff --git a/pyproject.toml b/pyproject.toml index d8dffaf..791af38 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ ot-pyld = "^2.1.1" hexbytes = "^1.2.1" eth-account = "^0.13.4" eth-typing = "^5.0.0" +python-dotenv = "^1.0.1" [tool.poetry.group.dev.dependencies] From 3329e230e4e15e38656d6b0f71d4dd1ea8320102 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 12:06:51 +0100 Subject: [PATCH 073/146] merge sync and async client --- dkg/__init__.py | 2 +- dkg/assertion.py | 4 +- dkg/asset/__init__.py | 4 + dkg/{ => asset}/asset.py | 4 +- dkg/asset/async_asset.py | 923 ++++++++++++++++++ dkg/clients/__init__.py | 4 + dkg/clients/async_dkg.py | 101 ++ dkg/{main.py => clients/dkg.py} | 44 +- dkg/graph.py | 6 +- dkg/graph/__init__.py | 4 + dkg/graph/async_graph.py | 118 +++ dkg/graph/graph.py | 118 +++ dkg/managers/__init__.py | 0 dkg/managers/async_manager.py | 69 ++ dkg/{ => managers}/manager.py | 8 +- dkg/method.py | 7 +- dkg/modules/__init__.py | 0 dkg/modules/async_module.py | 66 ++ dkg/{ => modules}/module.py | 2 +- dkg/network.py | 4 +- dkg/node/__init__.py | 4 + dkg/node/async_node.py | 39 + dkg/{ => node}/node.py | 4 +- dkg/paranet.py | 4 +- dkg/providers/__init__.py | 11 +- dkg/providers/blockchain/__init__.py | 4 + dkg/providers/blockchain/async_blockchain.py | 245 +++++ dkg/providers/blockchain/base_blockchain.py | 102 ++ dkg/providers/{ => blockchain}/blockchain.py | 92 +- dkg/providers/node/__init__.py | 4 + dkg/providers/node/async_node_http.py | 72 ++ dkg/providers/node/base_node_http.py | 25 + dkg/providers/{ => node}/node_http.py | 6 +- dkg/services/__init__.py | 0 dkg/services/node_services/__init__.py | 0 .../node_services/async_node_service.py | 205 ++++ .../{ => node_services}/node_service.py | 4 +- examples/async_demo.py | 123 +++ examples/demo.py | 28 +- 39 files changed, 2316 insertions(+), 144 deletions(-) create mode 100644 dkg/asset/__init__.py rename dkg/{ => asset}/asset.py (99%) create mode 100644 dkg/asset/async_asset.py create mode 100644 dkg/clients/__init__.py create mode 100644 dkg/clients/async_dkg.py rename dkg/{main.py => clients/dkg.py} (86%) create mode 100644 dkg/graph/__init__.py create mode 100644 dkg/graph/async_graph.py create mode 100644 dkg/graph/graph.py create mode 100644 dkg/managers/__init__.py create mode 100644 dkg/managers/async_manager.py rename dkg/{ => managers}/manager.py (93%) create mode 100644 dkg/modules/__init__.py create mode 100644 dkg/modules/async_module.py rename dkg/{ => modules}/module.py (97%) create mode 100644 dkg/node/__init__.py create mode 100644 dkg/node/async_node.py rename dkg/{ => node}/node.py (93%) create mode 100644 dkg/providers/blockchain/__init__.py create mode 100644 dkg/providers/blockchain/async_blockchain.py create mode 100644 dkg/providers/blockchain/base_blockchain.py rename dkg/providers/{ => blockchain}/blockchain.py (69%) create mode 100644 dkg/providers/node/__init__.py create mode 100644 dkg/providers/node/async_node_http.py create mode 100644 dkg/providers/node/base_node_http.py rename dkg/providers/{ => node}/node_http.py (92%) create mode 100644 dkg/services/__init__.py create mode 100644 dkg/services/node_services/__init__.py create mode 100644 dkg/services/node_services/async_node_service.py rename dkg/services/{ => node_services}/node_service.py (97%) create mode 100644 examples/async_demo.py diff --git a/dkg/__init__.py b/dkg/__init__.py index 780842a..041fa3b 100644 --- a/dkg/__init__.py +++ b/dkg/__init__.py @@ -1,3 +1,3 @@ from . import providers # NOQA: F401 from . import utils # NOQA: F401 -from .main import DKG # NOQA: F401 +from .clients import DKG, AsyncDKG # NOQA: F401 diff --git a/dkg/assertion.py b/dkg/assertion.py index e9e036b..8c38f01 100644 --- a/dkg/assertion.py +++ b/dkg/assertion.py @@ -17,8 +17,8 @@ from typing import Literal -from dkg.manager import DefaultRequestManager -from dkg.module import Module +from dkg.managers.manager import DefaultRequestManager +from dkg.modules.module import Module from dkg.types import JSONLD, HexStr from dkg.utils.merkle import MerkleTree, hash_assertion_with_indexes from dkg.utils.metadata import generate_assertion_metadata diff --git a/dkg/asset/__init__.py b/dkg/asset/__init__.py new file mode 100644 index 0000000..374697e --- /dev/null +++ b/dkg/asset/__init__.py @@ -0,0 +1,4 @@ +from .asset import KnowledgeAsset +from .async_asset import AsyncKnowledgeAsset + +__all__ = ["KnowledgeAsset", "AsyncKnowledgeAsset"] diff --git a/dkg/asset.py b/dkg/asset/asset.py similarity index 99% rename from dkg/asset.py rename to dkg/asset/asset.py index c3642a9..f177727 100644 --- a/dkg/asset.py +++ b/dkg/asset/asset.py @@ -44,9 +44,9 @@ BidSuggestionRange, NodeResponseDict, ) -from dkg.manager import DefaultRequestManager +from dkg.managers.manager import DefaultRequestManager from dkg.method import Method -from dkg.module import Module +from dkg.modules.module import Module from dkg.types import JSONLD, UAL, Address, HexStr, Wei from dkg.utils.blockchain_request import ( BlockchainRequest, diff --git a/dkg/asset/async_asset.py b/dkg/asset/async_asset.py new file mode 100644 index 0000000..14eed9f --- /dev/null +++ b/dkg/asset/async_asset.py @@ -0,0 +1,923 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import json +import hashlib +import asyncio +from typing import Literal, Dict, Optional, Any +from pyld import jsonld +from web3 import Web3 +from web3.constants import ADDRESS_ZERO +from web3.types import TxReceipt +from itertools import chain +from eth_abi.packed import encode_packed +from eth_account.messages import encode_defunct +from eth_account import Account +from hexbytes import HexBytes + +from dkg.constants import ( + PRIVATE_ASSERTION_PREDICATE, + PRIVATE_RESOURCE_PREDICATE, + PRIVATE_HASH_SUBJECT_PREFIX, + CHUNK_BYTE_SIZE, + MAX_FILE_SIZE, + DEFAULT_RDF_FORMAT, + Operations, + OutputTypes, + DefaultParameters, + ZERO_ADDRESS, +) +from dkg.dataclasses import ( + BidSuggestionRange, +) +from dkg.managers.async_manager import AsyncRequestManager +from dkg.method import Method +from dkg.modules.async_module import AsyncModule +from dkg.types import JSONLD, UAL, Address, HexStr, Wei +from dkg.utils.blockchain_request import ( + BlockchainRequest, + KnowledgeCollectionResult, + AllowanceResult, +) +from dkg.utils.node_request import ( + OperationStatus, +) +from dkg.utils.ual import format_ual, parse_ual +import dkg.utils.knowledge_collection_tools as kc_tools +import dkg.utils.knowledge_asset_tools as ka_tools +from dkg.services.input_service import InputService +from dkg.services.node_services.async_node_service import AsyncNodeService + + +class AsyncKnowledgeAsset(AsyncModule): + def __init__( + self, + manager: AsyncRequestManager, + input_service: InputService, + node_service: AsyncNodeService, + ): + self.manager = manager + self.input_service = input_service + self.node_service = node_service + + _owner = Method(BlockchainRequest.owner_of) + + def is_valid_ual(self, ual: UAL) -> bool: + if not ual or not isinstance(ual, str): + raise ValueError("UAL must be a non-empty string.") + + parts = ual.split("/") + if len(parts) != 3: + raise ValueError("UAL format is incorrect.") + + prefixes = parts[0].split(":") + prefixes_number = len(prefixes) + if prefixes_number != 3 and prefixes_number != 4: + raise ValueError("Prefix format in UAL is incorrect.") + + if prefixes[0] != "did": + raise ValueError( + f"Invalid DID prefix. Expected: 'did'. Received: '{prefixes[0]}'." + ) + + if prefixes[1] != "dkg": + raise ValueError( + f"Invalid DKG prefix. Expected: 'dkg'. Received: '{prefixes[1]}'." + ) + + if prefixes[2] != ( + blockchain_name := ( + self.manager.blockchain_provider.blockchain_id.split(":")[0] + ) + ): + raise ValueError( + "Invalid blockchain name in the UAL prefix. " + f"Expected: '{blockchain_name}'. Received: '${prefixes[2]}'." + ) + + if prefixes_number == 4: + chain_id = self.manager.blockchain_provider.blockchain_id.split(":")[1] + + if int(prefixes[3]) != int(chain_id): + raise ValueError( + "Chain ID in UAL does not match the blockchain. " + f"Expected: '${chain_id}'. Received: '${prefixes[3]}'." + ) + + contract_address = self.manager.blockchain_provider.contracts[ + "ContentAssetStorage" + ].address + + if parts[1].lower() != contract_address.lower(): + raise ValueError( + "Contract address in UAL does not match. " + f"Expected: '${contract_address.lower()}'. " + f"Received: '${parts[1].lower()}'." + ) + + try: + owner = self._owner(int(parts[2])) + + if not owner or owner == ADDRESS_ZERO: + raise ValueError("Token does not exist or has no owner.") + + return True + except Exception as err: + raise ValueError(f"Error fetching asset owner: {err}") + + _get_contract_address = Method(BlockchainRequest.get_contract_address) + _get_current_allowance = Method(BlockchainRequest.allowance) + _increase_allowance = Method(BlockchainRequest.increase_allowance) + _decrease_allowance = Method(BlockchainRequest.decrease_allowance) + _chain_id = Method(BlockchainRequest.chain_id) + _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) + _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) + _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) + _epoch_length = Method(BlockchainRequest.epoch_length) + _get_stake_weighted_average_ask = Method( + BlockchainRequest.get_stake_weighted_average_ask + ) + _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) + _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + + def get_operation_status_object( + self, operation_result: Dict[str, Any], operation_id: str + ) -> Dict[str, Any]: + """ + Creates an operation status object from operation result and ID. + + Args: + operation_result: Dictionary containing operation result data + operation_id: The ID of the operation + + Returns: + Dictionary containing operation status information + """ + # Check if error_type exists in operation_result.data + operation_data = ( + {"status": operation_result.get("status"), **operation_result.get("data")} + if operation_result.get("data", {}).get("errorType") + else {"status": operation_result.get("status")} + ) + + return {"operationId": operation_id, **operation_data} + + async def decrease_knowledge_collection_allowance( + self, + allowance_gap: int, + ): + knowledge_collection_address = await self._get_contract_address( + "KnowledgeCollection" + ) + await self._decrease_allowance(knowledge_collection_address, allowance_gap) + + async def increase_knowledge_collection_allowance( + self, + sender: str, + token_amount: str, + ) -> AllowanceResult: + """ + Increases the allowance for knowledge collection if necessary. + + Args: + sender: The address of the sender + token_amount: The amount of tokens to check/increase allowance for + + Returns: + AllowanceResult containing whether allowance was increased and the gap + """ + knowledge_collection_address = await self._get_contract_address( + "KnowledgeCollection" + ) + + allowance = await self._get_current_allowance( + sender, knowledge_collection_address + ) + allowance_gap = int(token_amount) - int(allowance) + + if allowance_gap > 0: + await self._increase_allowance(knowledge_collection_address, allowance_gap) + + return AllowanceResult( + allowance_increased=True, allowance_gap=allowance_gap + ) + + return AllowanceResult(allowance_increased=False, allowance_gap=allowance_gap) + + async def create_knowledge_collection( + self, + request: dict, + paranet_ka_contract: Optional[Address] = None, + paranet_token_id: Optional[int] = None, + ) -> KnowledgeCollectionResult: + """ + Creates a knowledge collection on the blockchain. + + Args: + request: dict containing all collection parameters + paranet_ka_contract: Optional paranet contract address + paranet_token_id: Optional paranet token ID + blockchain: Blockchain configuration + + Returns: + KnowledgeCollectionResult containing collection ID and transaction receipt + + Raises: + BlockchainError: If the collection creation fails + """ + sender = self.manager.blockchain_provider.account.address + allowance_increased = False + allowance_gap = 0 + + try: + # Handle allowance + if request.get("paymaster") and request.get("paymaster") != ZERO_ADDRESS: + pass + else: + allowance_result = await self.increase_knowledge_collection_allowance( + sender=sender, + token_amount=request.get("tokenAmount"), + ) + allowance_increased = allowance_result.allowance_increased + allowance_gap = allowance_result.allowance_gap + + if not paranet_ka_contract and not paranet_token_id: + receipt = await self._create_knowledge_collection( + request.get("publishOperationId"), + Web3.to_bytes(hexstr=request.get("merkleRoot")), + request.get("knowledgeAssetsAmount"), + request.get("byteSize"), + request.get("epochs"), + request.get("tokenAmount"), + request.get("isImmutable"), + request.get("paymaster"), + request.get("publisherNodeIdentityId"), + Web3.to_bytes(hexstr=request.get("publisherNodeR")), + Web3.to_bytes(hexstr=request.get("publisherNodeVS")), + request.get("identityIds"), + [Web3.to_bytes(hexstr=x) for x in request.get("r")], + [Web3.to_bytes(hexstr=x) for x in request.get("vs")], + ) + else: + receipt = await self._mint_knowledge_asset( + paranet_ka_contract, + paranet_token_id, + list(request.values()), + ) + + event_data = self.manager.blockchain_provider.decode_logs_event( + receipt=receipt, + contract_name="KnowledgeCollectionStorage", + event_name="KnowledgeCollectionCreated", + ) + collection_id = ( + int(getattr(event_data[0].get("args", {}), "id", None)) + if event_data + else None + ) + + return KnowledgeCollectionResult( + knowledge_collection_id=collection_id, receipt=receipt + ) + + except Exception as e: + if allowance_increased: + await self.decrease_knowledge_collection_allowance(allowance_gap) + raise e + + def process_content(self, content: str) -> list: + return [line.strip() for line in content.split("\n") if line.strip() != ""] + + def solidity_packed_sha256(self, types: list[str], values: list) -> str: + # Encode the values using eth_abi's encode_packed + packed_data = encode_packed(types, values) + + # Calculate SHA256 + sha256_hash = hashlib.sha256(packed_data).hexdigest() + + return f"0x{sha256_hash}" + + def insert_triple_sorted(self, triples_list: list, new_triple: str) -> int: + # Assuming triples_list is already sorted + left = 0 + right = len(triples_list) + + while left < right: + mid = (left + right) // 2 + if triples_list[mid] < new_triple: + left = mid + 1 + else: + right = mid + + # Insert the new triple at the correct position + triples_list.insert(left, new_triple) + return left + + def get_operation_status_dict(self, operation_result, operation_id): + # Check if data exists and has errorType + operation_data = ( + {"status": operation_result.get("status"), **operation_result.get("data")} + if operation_result.get("data") + and operation_result.get("data", {}).get("errorType") + else {"status": operation_result.get("status")} + ) + + return {"operationId": operation_id, **operation_data} + + def get_message_signer_address(self, dataset_root: str, signature: dict): + message = encode_defunct(HexBytes(dataset_root)) + r, s, v = signature.get("r"), signature.get("s"), signature.get("v") + r = r[2:] if r.startswith("0x") else r + s = s[2:] if s.startswith("0x") else s + + sig = "0x" + r + s + hex(v)[2:].zfill(2) + + return Account.recover_message(message, signature=sig) + + async def process_signatures(self, signatures, dataset_root): + async def process_signature(signature): + try: + signer_address = self.get_message_signer_address( + dataset_root, signature + ) + + key_is_operational_wallet = await self._key_is_operational_wallet( + signature.get("identityId"), + Web3.solidity_keccak(["address"], [signer_address]), + 2, # IdentityLib.OPERATIONAL_KEY + ) + + if key_is_operational_wallet: + return { + "identityId": signature.get("identityId"), + "r": signature.get("r"), + "vs": signature.get("vs"), + } + + except Exception: + pass + return None + + # Run all signature processing concurrently + results = await asyncio.gather( + *(process_signature(sig) for sig in signatures), return_exceptions=False + ) + + # Filter out None results and organize the data + valid_results = [r for r in results if r is not None] + + return { + "identity_ids": [r["identityId"] for r in valid_results], + "r": [r["r"] for r in valid_results], + "vs": [r["vs"] for r in valid_results], + } + + async def create( + self, + content: dict[Literal["public", "private"], JSONLD], + options: dict = None, + ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: + if options is None: + options = {} + + arguments = self.input_service.get_asset_create_arguments(options) + + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + epochs_num = arguments.get("epochs_num") + hash_function_id = arguments.get("hash_function_id") + immutable = arguments.get("immutable") + token_amount = arguments.get("token_amount") + payer = arguments.get("payer") + minimum_number_of_finalization_confirmations = arguments.get( + "minimum_number_of_finalization_confirmations" + ) + minimum_number_of_node_replications = arguments.get( + "minimum_number_of_node_replications" + ) + blockchain_id = self.manager.blockchain_provider.blockchain_id + + dataset = {} + public_content = dataset.get("public") + private_content = dataset.get("private") + if isinstance(content, str): + dataset["public"] = self.process_content(content) + elif isinstance(public_content, str) or ( + not public_content and private_content and isinstance(private_content, str) + ): + if public_content: + dataset["public"] = self.process_content(public_content) + else: + dataset["public"] = [] + + if private_content and isinstance(private_content, str): + dataset["private"] = self.process_content(private_content) + else: + dataset = kc_tools.format_dataset(content) + + public_triples_grouped = [] + + dataset["public"] = kc_tools.generate_missing_ids_for_blank_nodes( + dataset.get("public") + ) + + if dataset.get("private") and len(dataset.get("private")): + dataset["private"] = kc_tools.generate_missing_ids_for_blank_nodes( + dataset.get("private") + ) + + # Group private triples by subject and flatten + private_triples_grouped = kc_tools.group_nquads_by_subject( + dataset.get("private"), True + ) + + dataset["private"] = list(chain.from_iterable(private_triples_grouped)) + + # Compute private root and add to public + private_root = kc_tools.calculate_merkle_root(dataset.get("private")) + dataset["public"].append( + f'<{ka_tools.generate_named_node()}> <{PRIVATE_ASSERTION_PREDICATE}> "{private_root}" .' + ) + + # Compute private root and add to public + public_triples_grouped = kc_tools.group_nquads_by_subject( + dataset.get("public"), True + ) + + # Create a dictionary for public subject -> index for quick lookup + public_subject_dict = {} + for i in range(len(public_triples_grouped)): + public_subject = public_triples_grouped[i][0].split(" ")[0] + public_subject_dict[public_subject] = i + + private_triple_subject_hashes_grouped_without_public_pair = [] + + # Integrate private subjects into public or store separately if no match to be appended later + for private_triples in private_triples_grouped: + private_subject = private_triples[0].split(" ")[ + 0 + ] # Extract the private subject + + private_subject_hash = self.solidity_packed_sha256( + types=["string"], + values=[private_subject[1:-1]], + ) + + if ( + private_subject in public_subject_dict + ): # Check if there's a public pair + # If there's a public pair, insert a representation in that group + public_index = public_subject_dict.get(private_subject) + self.insert_triple_sorted( + public_triples_grouped[public_index], + f"{private_subject} <{PRIVATE_RESOURCE_PREDICATE}> <{ka_tools.generate_named_node()}> .", + ) + else: + # If no public pair, maintain separate list, inserting sorted by hash + self.insert_triple_sorted( + private_triple_subject_hashes_grouped_without_public_pair, + f"<{PRIVATE_HASH_SUBJECT_PREFIX}{private_subject_hash}> <{PRIVATE_RESOURCE_PREDICATE}> <{ka_tools.generate_named_node()}> .", + ) + + for triple in private_triple_subject_hashes_grouped_without_public_pair: + public_triples_grouped.append([triple]) + + dataset["public"] = list(chain.from_iterable(public_triples_grouped)) + else: + # No private triples, just group and flatten public + public_triples_grouped = kc_tools.group_nquads_by_subject( + dataset.get("public"), True + ) + dataset["public"] = list(chain.from_iterable(public_triples_grouped)) + + # Calculate the number of chunks + number_of_chunks = kc_tools.calculate_number_of_chunks( + dataset.get("public"), CHUNK_BYTE_SIZE + ) + dataset_size = number_of_chunks * CHUNK_BYTE_SIZE + + # Validate the assertion size in bytes + if dataset_size > MAX_FILE_SIZE: + raise ValueError(f"File size limit is {MAX_FILE_SIZE / (1024 * 1024)}MB.") + + # Calculate the Merkle root + dataset_root = kc_tools.calculate_merkle_root(dataset.get("public")) + + # Get the contract address for KnowledgeCollectionStorage + content_asset_storage_address = await self._get_asset_storage_address( + "KnowledgeCollectionStorage" + ) + + result = await self.node_service.publish( + dataset_root, + dataset, + blockchain_id, + hash_function_id, + minimum_number_of_node_replications, + ) + publish_operation_id = result.get("operationId") + publish_operation_result = await self.node_service.get_operation_result( + publish_operation_id, + Operations.PUBLISH.value, + max_number_of_retries, + frequency, + ) + + if publish_operation_result.get( + "status" + ) != OperationStatus.COMPLETED and not publish_operation_result.get( + "data", {} + ).get("minAcksReached"): + return { + "datasetRoot": dataset_root, + "operation": { + "publish": self.get_operation_status_dict( + publish_operation_result, publish_operation_id + ) + }, + } + + data = publish_operation_result.get("data", {}) + signatures = data.get("signatures") + + publisher_node_signature = data.get("publisherNodeSignature", {}) + publisher_node_identity_id = publisher_node_signature.get("identityId") + publisher_node_r = publisher_node_signature.get("r") + publisher_node_vs = publisher_node_signature.get("vs") + + results = await self.process_signatures(signatures, dataset_root) + identity_ids = results["identity_ids"] + r = results["r"] + vs = results["vs"] + + if token_amount: + estimated_publishing_cost = token_amount + else: + time_until_next_epoch = await self._time_until_next_epoch() + epoch_length = await self._epoch_length() + stake_weighted_average_ask = await self._get_stake_weighted_average_ask() + + # Convert to integers and perform calculation + estimated_publishing_cost = ( + ( + int(stake_weighted_average_ask) + * ( + int(epochs_num) * int(1e18) + + (int(time_until_next_epoch) * int(1e18)) // int(epoch_length) + ) + * int(dataset_size) + ) + // 1024 + // int(1e18) + ) + + knowledge_collection_id = None + mint_knowledge_asset_receipt = None + + knowledge_collection_result = await self.create_knowledge_collection( + { + "publishOperationId": publish_operation_id, + "merkleRoot": dataset_root, + "knowledgeAssetsAmount": kc_tools.count_distinct_subjects( + dataset.get("public") + ), + "byteSize": dataset_size, + "epochs": epochs_num, + "tokenAmount": estimated_publishing_cost, + "isImmutable": immutable, + "paymaster": payer, + "publisherNodeIdentityId": publisher_node_identity_id, + "publisherNodeR": publisher_node_r, + "publisherNodeVS": publisher_node_vs, + "identityIds": identity_ids, + "r": r, + "vs": vs, + }, + None, + None, + ) + knowledge_collection_id = knowledge_collection_result.knowledge_collection_id + mint_knowledge_asset_receipt = knowledge_collection_result.receipt + + ual = format_ual( + blockchain_id, content_asset_storage_address, knowledge_collection_id + ) + + finality_status_result = 0 + if minimum_number_of_finalization_confirmations > 0: + finality_status_result = await self.node_service.finality_status( + ual, + minimum_number_of_finalization_confirmations, + max_number_of_retries, + frequency, + ) + + return json.loads( + Web3.to_json( + { + "UAL": ual, + "datasetRoot": dataset_root, + "signatures": publish_operation_result.get("data", {}).get( + "signatures" + ), + "operation": { + "mintKnowledgeAsset": mint_knowledge_asset_receipt, + "publish": self.get_operation_status_object( + publish_operation_result, publish_operation_id + ), + "finality": { + "status": "FINALIZED" + if finality_status_result + >= minimum_number_of_finalization_confirmations + else "NOT FINALIZED" + }, + "numberOfConfirmations": finality_status_result, + "requiredConfirmations": minimum_number_of_finalization_confirmations, + }, + } + ) + ) + + _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) + + def submit_to_paranet( + self, ual: UAL, paranet_ual: UAL + ) -> dict[str, UAL | Address | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + parsed_paranet_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( + parsed_paranet_ual["contract_address"], + parsed_paranet_ual["token_id"], + ) + + receipt: TxReceipt = self._submit_knowledge_asset( + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, + knowledge_asset_storage, + knowledge_asset_token_id, + ) + + return { + "UAL": ual, + "paranetUAL": paranet_ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": json.loads(Web3.to_json(receipt)), + } + + _transfer = Method(BlockchainRequest.transfer_asset) + + def transfer( + self, + ual: UAL, + new_owner: Address, + ) -> dict[str, UAL | Address | TxReceipt]: + token_id = parse_ual(ual)["token_id"] + + receipt: TxReceipt = self._transfer( + self.manager.blockchain_provider.account, + new_owner, + token_id, + ) + + return { + "UAL": ual, + "owner": new_owner, + "operation": json.loads(Web3.to_json(receipt)), + } + + _burn_asset = Method(BlockchainRequest.burn_asset) + + def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: + token_id = parse_ual(ual)["token_id"] + + receipt: TxReceipt = self._burn_asset(token_id) + + return {"UAL": ual, "operation": json.loads(Web3.to_json(receipt))} + + _get_assertion_ids = Method(BlockchainRequest.get_assertion_ids) + _get_latest_assertion_id = Method(BlockchainRequest.get_latest_assertion_id) + _get_unfinalized_state = Method(BlockchainRequest.get_unfinalized_state) + + async def get(self, ual: UAL, options: dict = None) -> dict: + if options is None: + options = {} + + arguments = self.input_service.get_asset_get_arguments(options) + + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + state = arguments.get("state") + include_metadata = arguments.get("include_metadata") + content_type = arguments.get("content_type") + validate = arguments.get("validate") + output_format = arguments.get("output_format") + hash_function_id = arguments.get("hash_function_id") + paranet_ual = arguments.get("paranet_ual") + subject_ual = arguments.get("subject_ual") + + ual_with_state = f"{ual}:{state}" if state else ual + result = await self.node_service.get( + ual_with_state, + content_type, + include_metadata, + hash_function_id, + paranet_ual, + subject_ual, + ) + get_public_operation_id = result.get("operationId") + get_public_operation_result = await self.node_service.get_operation_result( + get_public_operation_id, + Operations.GET.value, + max_number_of_retries, + frequency, + ) + + if subject_ual: + if get_public_operation_result.get("data"): + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + "subject_ual_pairs": get_public_operation_result.get("data"), + } + if get_public_operation_result.get("status") != "FAILED": + get_public_operation_result["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Unable to find assertion on the network!", + } + get_public_operation_result["status"] = "FAILED" + + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + metadata = get_public_operation_result.get("data") + assertion = get_public_operation_result.get("data", {}).get("assertion", None) + + if not assertion: + if get_public_operation_result.get("status") != "FAILED": + get_public_operation_result["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Unable to find assertion on the network!", + } + get_public_operation_result["status"] = "FAILED" + + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + + if validate: + is_valid = True # #TODO: Implement assertion validation logic + if not is_valid: + get_public_operation_result["data"] = { + "error_type": "DKG_CLIENT_ERROR", + "error_message": "Calculated root hashes don't match!", + } + + formatted_assertion = "\n".join( + assertion.get("public", []) + + ( + assertion.get("private") + if isinstance(assertion.get("private"), list) + else [] + ) + ) + + formatted_metadata = None + if output_format == OutputTypes.JSONLD.value: + formatted_assertion = self.to_jsonld(formatted_assertion) + + if include_metadata: + formatted_metadata = self.to_jsonld("\n".join(metadata)) + + if output_format == OutputTypes.NQUADS.value: + formatted_assertion = self.to_nquads( + formatted_assertion, DEFAULT_RDF_FORMAT + ) + if include_metadata: + formatted_metadata = self.to_nquads( + "\n".join(metadata), DEFAULT_RDF_FORMAT + ) + + result = { + "assertion": formatted_assertion, + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + + if include_metadata and metadata: + result["metadata"] = formatted_metadata + + return result + + _extend_storing_period = Method(BlockchainRequest.extend_asset_storing_period) + + async def extend_storing_period( + self, + ual: UAL, + additional_epochs: int, + token_amount: Wei | None = None, + ) -> dict[str, UAL | TxReceipt]: + parsed_ual = parse_ual(ual) + blockchain_id, content_asset_storage_address, token_id = ( + parsed_ual["blockchain"], + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + if token_amount is None: + latest_finalized_state = self._get_latest_assertion_id(token_id) + latest_finalized_state_size = self._get_assertion_size( + latest_finalized_state + ) + + token_amount = await self.node_service.get_bid_suggestion( + blockchain_id, + additional_epochs, + latest_finalized_state_size, + content_asset_storage_address, + latest_finalized_state, + DefaultParameters.HASH_FUNCTION_ID.value, + token_amount or BidSuggestionRange.LOW, + ) + + receipt: TxReceipt = self._extend_storing_period( + token_id, additional_epochs, token_amount + ) + + return { + "UAL": ual, + "operation": json.loads(Web3.to_json(receipt)), + } + + _get_block = Method(BlockchainRequest.get_block) + + _get_assertion_size = Method(BlockchainRequest.get_assertion_size) + + def get_owner(self, ual: UAL) -> Address: + token_id = parse_ual(ual)["token_id"] + + return self._owner(token_id) + + def to_jsonld(self, nquads: str): + options = { + "algorithm": "URDNA2015", + "format": "application/n-quads", + } + + return jsonld.from_rdf(nquads, options) + + def to_nquads(self, content, input_format): + options = { + "algorithm": "URDNA2015", + "format": "application/n-quads", + } + + if input_format: + options["inputFormat"] = input_format + try: + jsonld_data = jsonld.from_rdf(content, options) + canonized = jsonld.to_rdf(jsonld_data, options) + + if isinstance(canonized, str): + return [line for line in canonized.split("\n") if line.strip()] + + except Exception as e: + raise ValueError(f"Error processing content: {e}") diff --git a/dkg/clients/__init__.py b/dkg/clients/__init__.py new file mode 100644 index 0000000..18f1bba --- /dev/null +++ b/dkg/clients/__init__.py @@ -0,0 +1,4 @@ +from .dkg import DKG +from .async_dkg import AsyncDKG + +__all__ = ["DKG", "AsyncDKG"] diff --git a/dkg/clients/async_dkg.py b/dkg/clients/async_dkg.py new file mode 100644 index 0000000..a1aff11 --- /dev/null +++ b/dkg/clients/async_dkg.py @@ -0,0 +1,101 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from functools import wraps + + +from dkg.assertion import Assertion +from dkg.asset.async_asset import AsyncKnowledgeAsset +from dkg.graph.async_graph import AsyncGraph +from dkg.managers.async_manager import AsyncRequestManager +from dkg.modules.async_module import AsyncModule +from dkg.network import Network +from dkg.node.async_node import AsyncNode +from dkg.paranet import Paranet +from dkg.types import UAL, Address, ChecksumAddress +from dkg.utils.ual import format_ual, parse_ual +from dkg.services.input_service import InputService +from dkg.providers.blockchain.async_blockchain import AsyncBlockchainProvider +from dkg.providers.node.async_node_http import AsyncNodeHTTPProvider +from dkg.services.node_services.async_node_service import AsyncNodeService + + +class AsyncDKG(AsyncModule): + assertion: Assertion + asset: AsyncKnowledgeAsset + paranet: Paranet + network: Network + node: AsyncNode + graph: AsyncGraph + + def __init__( + self, + node_provider: AsyncNodeHTTPProvider, + blockchain_provider: AsyncBlockchainProvider, + config: dict = {}, + ): + self.manager = AsyncRequestManager(node_provider, blockchain_provider) + + self.initialize_services(config) + + modules = { + "assertion": Assertion(self.manager), + "asset": AsyncKnowledgeAsset( + self.manager, self.input_service, self.node_service + ), + "paranet": Paranet(self.manager), + "network": Network(self.manager), + "node": AsyncNode(self.manager, self.node_service), + "graph": AsyncGraph(self.manager, self.input_service, self.node_service), + } + self._attach_modules(modules) + + # Backwards compatibility + self.graph.get = self.asset.get.__get__(self.asset) + self.graph.create = self.asset.create.__get__(self.asset) + + def initialize_services(self, config: dict = {}): + self.input_service = InputService(self.manager, config) + self.node_service = AsyncNodeService(self.manager) + + @staticmethod + @wraps(format_ual) + def format_ual( + blockchain: str, contract_address: Address | ChecksumAddress, token_id: int + ) -> UAL: + return format_ual(blockchain, contract_address, token_id) + + @staticmethod + @wraps(parse_ual) + def parse_ual(ual: UAL) -> dict[str, str | Address | int]: + return parse_ual(ual) + + @property + def node_provider(self) -> AsyncNodeHTTPProvider: + return self.manager.node_provider + + @node_provider.setter + def node_provider(self, node_provider: AsyncNodeHTTPProvider) -> None: + self.manager.node_provider = node_provider + + @property + def blockchain_provider(self) -> AsyncBlockchainProvider: + return self.manager.blockchain_provider + + @blockchain_provider.setter + def blockchain_provider(self, blockchain_provider: AsyncBlockchainProvider) -> None: + self.manager.blockchain_provider = blockchain_provider diff --git a/dkg/main.py b/dkg/clients/dkg.py similarity index 86% rename from dkg/main.py rename to dkg/clients/dkg.py index 35d45b8..92763ea 100644 --- a/dkg/main.py +++ b/dkg/clients/dkg.py @@ -18,18 +18,18 @@ from functools import wraps from dkg.assertion import Assertion -from dkg.asset import KnowledgeAsset -from dkg.graph import Graph -from dkg.manager import DefaultRequestManager -from dkg.module import Module +from dkg.asset.asset import KnowledgeAsset +from dkg.graph.graph import Graph +from dkg.managers.manager import DefaultRequestManager +from dkg.modules.module import Module from dkg.network import Network -from dkg.node import Node +from dkg.node.node import Node from dkg.paranet import Paranet from dkg.providers import BlockchainProvider, NodeHTTPProvider from dkg.types import UAL, Address, ChecksumAddress from dkg.utils.ual import format_ual, parse_ual from dkg.services.input_service import InputService -from dkg.services.node_service import NodeService +from dkg.services.node_services.node_service import NodeService class DKG(Module): @@ -40,18 +40,6 @@ class DKG(Module): node: Node graph: Graph - @staticmethod - @wraps(format_ual) - def format_ual( - blockchain: str, contract_address: Address | ChecksumAddress, token_id: int - ) -> UAL: - return format_ual(blockchain, contract_address, token_id) - - @staticmethod - @wraps(parse_ual) - def parse_ual(ual: UAL) -> dict[str, str | Address | int]: - return parse_ual(ual) - def __init__( self, node_provider: NodeHTTPProvider, @@ -60,7 +48,7 @@ def __init__( ): self.manager = DefaultRequestManager(node_provider, blockchain_provider) - self.initialize_services(self.manager, config) + self.initialize_services(config) modules = { "assertion": Assertion(self.manager), @@ -78,9 +66,21 @@ def __init__( self.graph.get = self.asset.get.__get__(self.asset) self.graph.create = self.asset.create.__get__(self.asset) - def initialize_services(self, manager, config): - self.input_service = InputService(manager, config) - self.node_service = NodeService(manager) + def initialize_services(self, config): + self.input_service = InputService(self.manager, config) + self.node_service = NodeService(self.manager) + + @staticmethod + @wraps(format_ual) + def format_ual( + blockchain: str, contract_address: Address | ChecksumAddress, token_id: int + ) -> UAL: + return format_ual(blockchain, contract_address, token_id) + + @staticmethod + @wraps(parse_ual) + def parse_ual(ual: UAL) -> dict[str, str | Address | int]: + return parse_ual(ual) @property def node_provider(self) -> NodeHTTPProvider: diff --git a/dkg/graph.py b/dkg/graph.py index 55ebd19..b73695a 100644 --- a/dkg/graph.py +++ b/dkg/graph.py @@ -18,14 +18,14 @@ from rdflib.plugins.sparql.parser import parseQuery -from dkg.manager import DefaultRequestManager +from dkg.managers.manager import DefaultRequestManager from dkg.method import Method -from dkg.module import Module +from dkg.modules.module import Module from dkg.types import NQuads from dkg.utils.node_request import ( NodeRequest, ) -from dkg.services.node_service import NodeService +from dkg.services.node_services.node_service import NodeService from dkg.services.input_service import InputService from dkg.constants import Operations diff --git a/dkg/graph/__init__.py b/dkg/graph/__init__.py new file mode 100644 index 0000000..70c3b2a --- /dev/null +++ b/dkg/graph/__init__.py @@ -0,0 +1,4 @@ +from .graph import Graph +from .async_graph import AsyncGraph + +__all__ = ["Graph", "AsyncGraph"] diff --git a/dkg/graph/async_graph.py b/dkg/graph/async_graph.py new file mode 100644 index 0000000..e39e462 --- /dev/null +++ b/dkg/graph/async_graph.py @@ -0,0 +1,118 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + +from rdflib.plugins.sparql.parser import parseQuery + +from dkg.managers.async_manager import AsyncRequestManager +from dkg.modules.async_module import AsyncModule +from dkg.types import NQuads +from dkg.constants import Operations +from dkg.services.input_service import InputService +from dkg.services.node_services.async_node_service import AsyncNodeService +from dkg.types import UAL + + +class AsyncGraph(AsyncModule): + def __init__( + self, + manager: AsyncRequestManager, + input_service: InputService, + node_service: AsyncNodeService, + ): + self.manager = manager + self.input_service = input_service + self.node_service = node_service + + async def query( + self, + query: str, + options: dict = None, + ) -> NQuads: + if options is None: + options = {} + + arguments = self.input_service.get_query_arguments(options) + + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + paranet_ual = arguments.get("paranet_ual") + repository = arguments.get("repository") + + parsed_query = parseQuery(query) + query_type = parsed_query[1].name.replace("Query", "").upper() + + result = await self.node_service.query( + query, query_type, repository, paranet_ual + ) + operation_id = result.get("operationId") + operation_result = await self.node_service.get_operation_result( + operation_id, Operations.QUERY.value, max_number_of_retries, frequency + ) + + return operation_result["data"] + + async def publish_finality(self, UAL: UAL, options=None): + if options is None: + options = {} + + arguments = self.input_service.get_publish_finality_arguments(options) + max_number_of_retries = arguments.get("max_number_of_retries") + minimum_number_of_finalization_confirmations = arguments.get( + "minimum_number_of_finalization_confirmations" + ) + frequency = arguments.get("frequency") + try: + finality_status_result = await self.node_service.finality_status( + UAL, + minimum_number_of_finalization_confirmations, + max_number_of_retries, + frequency, + ) + except Exception as e: + return {"status": "ERROR", "error": str(e)} + + if finality_status_result == 0: + try: + finality_operation_id = await self.node_service.finality( + UAL, + minimum_number_of_finalization_confirmations, + max_number_of_retries, + frequency, + ) + except Exception as e: + return {"status": "ERROR", "error": str(e)} + + try: + return await self.node_service.get_operation_result( + finality_operation_id, "finality", max_number_of_retries, frequency + ) + except Exception as e: + return {"status": "NOT FINALIZED", "error": str(e)} + + elif finality_status_result >= minimum_number_of_finalization_confirmations: + return { + "status": "FINALIZED", + "numberOfConfirmations": finality_status_result, + "requiredConfirmations": minimum_number_of_finalization_confirmations, + } + else: + return { + "status": "NOT FINALIZED", + "numberOfConfirmations": finality_status_result, + "requiredConfirmations": minimum_number_of_finalization_confirmations, + } diff --git a/dkg/graph/graph.py b/dkg/graph/graph.py new file mode 100644 index 0000000..b73695a --- /dev/null +++ b/dkg/graph/graph.py @@ -0,0 +1,118 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from rdflib.plugins.sparql.parser import parseQuery + + +from dkg.managers.manager import DefaultRequestManager +from dkg.method import Method +from dkg.modules.module import Module +from dkg.types import NQuads +from dkg.utils.node_request import ( + NodeRequest, +) +from dkg.services.node_services.node_service import NodeService +from dkg.services.input_service import InputService +from dkg.constants import Operations + + +class Graph(Module): + def __init__( + self, + manager: DefaultRequestManager, + input_service: InputService, + node_service: NodeService, + ): + self.manager = manager + self.input_service = input_service + self.node_service = node_service + + _query = Method(NodeRequest.query) + + def query( + self, + query: str, + options: dict = {}, + ) -> NQuads: + arguments = self.input_service.get_query_arguments(options) + + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + paranet_ual = arguments.get("paranet_ual") + repository = arguments.get("repository") + + parsed_query = parseQuery(query) + query_type = parsed_query[1].name.replace("Query", "").upper() + + result = self._query(query, query_type, repository, paranet_ual) + operation_id = result.get("operationId") + operation_result = self.node_service.get_operation_result( + operation_id, Operations.QUERY.value, max_number_of_retries, frequency + ) + + return operation_result["data"] + + def publish_finality(self, UAL, options=None): + if options is None: + options = {} + + arguments = self.input_service.get_publish_finality_arguments(options) + max_number_of_retries = arguments.get("max_number_of_retries") + minimum_number_of_finalization_confirmations = arguments.get( + "minimum_number_of_finalization_confirmations" + ) + frequency = arguments.get("frequency") + try: + finality_status_result = self.node_service.finality_status( + UAL, + minimum_number_of_finalization_confirmations, + max_number_of_retries, + frequency, + ) + except Exception as e: + return {"status": "ERROR", "error": str(e)} + + if finality_status_result == 0: + try: + finality_operation_id = self.node_service.finality( + UAL, + minimum_number_of_finalization_confirmations, + max_number_of_retries, + frequency, + ) + except Exception as e: + return {"status": "ERROR", "error": str(e)} + + try: + return self.node_service.get_operation_result( + finality_operation_id, "finality", max_number_of_retries, frequency + ) + except Exception as e: + return {"status": "NOT FINALIZED", "error": str(e)} + + elif finality_status_result >= minimum_number_of_finalization_confirmations: + return { + "status": "FINALIZED", + "numberOfConfirmations": finality_status_result, + "requiredConfirmations": minimum_number_of_finalization_confirmations, + } + else: + return { + "status": "NOT FINALIZED", + "numberOfConfirmations": finality_status_result, + "requiredConfirmations": minimum_number_of_finalization_confirmations, + } diff --git a/dkg/managers/__init__.py b/dkg/managers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dkg/managers/async_manager.py b/dkg/managers/async_manager.py new file mode 100644 index 0000000..67ea01a --- /dev/null +++ b/dkg/managers/async_manager.py @@ -0,0 +1,69 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from typing import Any, Type + +from dkg.dataclasses import BlockchainResponseDict, NodeResponseDict +from dkg.exceptions import InvalidRequest +from dkg.utils.blockchain_request import ContractInteraction, JSONRPCRequest +from dkg.utils.node_request import NodeCall +from dkg.providers.node.async_node_http import AsyncNodeHTTPProvider +from dkg.providers.blockchain.async_blockchain import AsyncBlockchainProvider + + +class AsyncRequestManager: + def __init__( + self, + node_provider: AsyncNodeHTTPProvider, + blockchain_provider: AsyncBlockchainProvider, + ): + self._node_provider = node_provider + self._blockchain_provider = blockchain_provider + + @property + def node_provider(self) -> AsyncNodeHTTPProvider: + return self._node_provider + + @node_provider.setter + def node_provider(self, node_provider: AsyncNodeHTTPProvider) -> None: + self._node_provider = node_provider + + @property + def blockchain_provider(self) -> AsyncBlockchainProvider: + return self._blockchain_provider + + @blockchain_provider.setter + def blockchain_provider(self, blockchain_provider: AsyncBlockchainProvider) -> None: + self._blockchain_provider = blockchain_provider + + async def blocking_request( + self, + request_type: Type[JSONRPCRequest | ContractInteraction | NodeCall], + request_params: dict[str, Any], + ) -> BlockchainResponseDict | NodeResponseDict: + if issubclass(request_type, JSONRPCRequest): + return await self.blockchain_provider.make_json_rpc_request( + **request_params + ) + elif issubclass(request_type, ContractInteraction): + return await self.blockchain_provider.call_function(**request_params) + elif issubclass(request_type, NodeCall): + return await self.node_provider.make_request(**request_params) + else: + raise InvalidRequest( + "Invalid Request. Manager can only process Blockchain/Node requests." + ) diff --git a/dkg/manager.py b/dkg/managers/manager.py similarity index 93% rename from dkg/manager.py rename to dkg/managers/manager.py index 8dce342..922d15c 100644 --- a/dkg/manager.py +++ b/dkg/managers/manager.py @@ -28,8 +28,8 @@ class DefaultRequestManager: def __init__( self, node_provider: NodeHTTPProvider, blockchain_provider: BlockchainProvider ): - self._node_provider = node_provider - self._blockchain_provider = blockchain_provider + self.node_provider = node_provider + self.blockchain_provider = blockchain_provider @property def node_provider(self) -> NodeHTTPProvider: @@ -40,7 +40,9 @@ def node_provider(self, node_provider: NodeHTTPProvider) -> None: self._node_provider = node_provider @property - def blockchain_provider(self) -> BlockchainProvider: + def blockchain_provider( + self, + ) -> BlockchainProvider: return self._blockchain_provider @blockchain_provider.setter diff --git a/dkg/method.py b/dkg/method.py index b149de8..5e7f517 100644 --- a/dkg/method.py +++ b/dkg/method.py @@ -30,7 +30,8 @@ from dkg.utils.string_transformations import snake_to_camel if TYPE_CHECKING: - from dkg.module import Module + from dkg.modules.module import Module + from dkg.modules.async_module import AsyncModule class Method(Generic[TFunc]): @@ -38,7 +39,9 @@ def __init__(self, action: JSONRPCRequest | ContractInteraction | NodeCall): self.action = action def __get__( - self, obj: "Module | None" = None, _: Type["Module"] | None = None + self, + obj: "Module | AsyncModule | None" = None, + _: Type["Module | AsyncModule"] | None = None, ) -> TFunc: if obj is None: raise TypeError( diff --git a/dkg/modules/__init__.py b/dkg/modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dkg/modules/async_module.py b/dkg/modules/async_module.py new file mode 100644 index 0000000..5d05dec --- /dev/null +++ b/dkg/modules/async_module.py @@ -0,0 +1,66 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from dataclasses import asdict +from typing import Any, Callable, Sequence + +from dkg.exceptions import ValidationError +from dkg.managers.async_manager import AsyncRequestManager +from dkg.method import Method +from dkg.types import TReturn + + +class AsyncModule: + manager: AsyncRequestManager + + def retrieve_caller_fn( + self, method: Method[Callable[..., TReturn]] + ) -> Callable[..., TReturn]: + async def caller(*args: Any, **kwargs: Any) -> TReturn: + processed_args = method.process_args(*args, **kwargs) + request_params = asdict(method.action) + request_params.update(processed_args) + + return await self.manager.blocking_request( + type(method.action), request_params + ) + + return caller + + def _attach_modules(self, module_definitions: dict[str, Any]) -> None: + for module_name, module_info in module_definitions.items(): + module_info_is_list_like = isinstance(module_info, Sequence) + + module = module_info[0] if module_info_is_list_like else module_info + + if hasattr(self, module_name): + raise AttributeError( + f"Cannot set {self} module named '{module_name}'. " + " The dkg object already has an attribute with that name" + ) + + setattr(self, module_name, module) + + if module_info_is_list_like: + if len(module_info) == 2: + submodule_definitions = module_info[1] + module: "AsyncModule" = getattr(self, module_name) + module._attach_modules(submodule_definitions) + elif len(module_info) != 1: + raise ValidationError( + "Module definitions can only have 1 or 2 elements." + ) diff --git a/dkg/module.py b/dkg/modules/module.py similarity index 97% rename from dkg/module.py rename to dkg/modules/module.py index d215308..966251b 100644 --- a/dkg/module.py +++ b/dkg/modules/module.py @@ -19,7 +19,7 @@ from typing import Any, Callable, Sequence from dkg.exceptions import ValidationError -from dkg.manager import DefaultRequestManager +from dkg.managers.manager import DefaultRequestManager from dkg.method import Method from dkg.types import TReturn diff --git a/dkg/network.py b/dkg/network.py index 405baa2..50ebff7 100644 --- a/dkg/network.py +++ b/dkg/network.py @@ -17,9 +17,9 @@ from dkg.constants import DefaultParameters from dkg.dataclasses import BidSuggestionRange -from dkg.manager import DefaultRequestManager +from dkg.managers.manager import DefaultRequestManager from dkg.method import Method -from dkg.module import Module +from dkg.modules.module import Module from dkg.types import DataHexStr from dkg.utils.blockchain_request import BlockchainRequest from dkg.utils.node_request import NodeRequest diff --git a/dkg/node/__init__.py b/dkg/node/__init__.py new file mode 100644 index 0000000..beb2789 --- /dev/null +++ b/dkg/node/__init__.py @@ -0,0 +1,4 @@ +from dkg.node.node import Node +from dkg.node.async_node import AsyncNode + +__all__ = ["Node", "AsyncNode"] diff --git a/dkg/node/async_node.py b/dkg/node/async_node.py new file mode 100644 index 0000000..6cc834d --- /dev/null +++ b/dkg/node/async_node.py @@ -0,0 +1,39 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from dkg.dataclasses import NodeResponseDict +from dkg.managers.async_manager import AsyncRequestManager +from dkg.method import Method +from dkg.modules.async_module import AsyncModule +from dkg.utils.blockchain_request import BlockchainRequest +from dkg.types import Address +from dkg.services.node_services.async_node_service import AsyncNodeService + + +class AsyncNode(AsyncModule): + def __init__(self, manager: AsyncRequestManager, node_service: AsyncNodeService): + self.manager = manager + self.node_service = node_service + + @property + async def info(self) -> NodeResponseDict: + return await self.node_service.info() + + _get_identity_id = Method(BlockchainRequest.get_identity_id) + + async def get_identity_id(self, operational: Address) -> int: + return await self._get_identity_id(operational) diff --git a/dkg/node.py b/dkg/node/node.py similarity index 93% rename from dkg/node.py rename to dkg/node/node.py index c25038f..54de5f8 100644 --- a/dkg/node.py +++ b/dkg/node/node.py @@ -16,9 +16,9 @@ # under the License. from dkg.dataclasses import NodeResponseDict -from dkg.manager import DefaultRequestManager +from dkg.managers.manager import DefaultRequestManager from dkg.method import Method -from dkg.module import Module +from dkg.modules.module import Module from dkg.utils.node_request import NodeRequest from dkg.utils.blockchain_request import BlockchainRequest from dkg.types import Address diff --git a/dkg/paranet.py b/dkg/paranet.py index c26ea5b..ea6e6da 100644 --- a/dkg/paranet.py +++ b/dkg/paranet.py @@ -27,9 +27,9 @@ ParanetNodesAccessPolicy, ParanetMinersAccessPolicy, ) -from dkg.manager import DefaultRequestManager +from dkg.managers.manager import DefaultRequestManager from dkg.method import Method -from dkg.module import Module +from dkg.modules.module import Module from dkg.types import Address, UAL, HexStr from dkg.utils.blockchain_request import BlockchainRequest from dkg.utils.ual import parse_ual diff --git a/dkg/providers/__init__.py b/dkg/providers/__init__.py index cbce2c7..08aae18 100644 --- a/dkg/providers/__init__.py +++ b/dkg/providers/__init__.py @@ -1,2 +1,9 @@ -from .blockchain import BlockchainProvider # NOQA -from .node_http import NodeHTTPProvider # NOQA +from .blockchain import BlockchainProvider, AsyncBlockchainProvider +from .node import NodeHTTPProvider, AsyncNodeHTTPProvider + +__all__ = [ + "BlockchainProvider", + "AsyncBlockchainProvider", + "NodeHTTPProvider", + "AsyncNodeHTTPProvider", +] diff --git a/dkg/providers/blockchain/__init__.py b/dkg/providers/blockchain/__init__.py new file mode 100644 index 0000000..2bd37de --- /dev/null +++ b/dkg/providers/blockchain/__init__.py @@ -0,0 +1,4 @@ +from .blockchain import BlockchainProvider +from .async_blockchain import AsyncBlockchainProvider + +__all__ = ["BlockchainProvider", "AsyncBlockchainProvider"] diff --git a/dkg/providers/blockchain/async_blockchain.py b/dkg/providers/blockchain/async_blockchain.py new file mode 100644 index 0000000..6f3f382 --- /dev/null +++ b/dkg/providers/blockchain/async_blockchain.py @@ -0,0 +1,245 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import os +import asyncio +from dotenv import load_dotenv +from functools import wraps +from typing import Any + +import aiohttp +from dkg.constants import BLOCKCHAINS +from dkg.exceptions import ( + AccountMissing, + NetworkNotSupported, +) +from dkg.types import URI, Address, Environment, Wei +from web3.contract import Contract +from web3.contract.contract import ContractFunction +from web3.types import TxReceipt +from web3.providers import AsyncHTTPProvider +from web3 import AsyncWeb3 +from dkg.providers.blockchain.base_blockchain import BaseBlockchainProvider + + +class AsyncBlockchainProvider(BaseBlockchainProvider): + def __init__( + self, + environment: Environment, + blockchain_id: str, + rpc_uri: URI | None = None, + gas_price: Wei | None = None, + verify: bool = True, + ): + super().__init__(environment, blockchain_id, rpc_uri, gas_price) + + ssl_context = None if verify else False + self.w3 = AsyncWeb3( + AsyncHTTPProvider(self.rpc_uri, request_kwargs={"ssl": ssl_context}) + ) + + if self.blockchain_id is None: + self.blockchain_id = f"{blockchain_id}:{self.w3.eth.chain_id}" + if self.blockchain_id not in BLOCKCHAINS[self.environment]: + raise NetworkNotSupported( + f"Network with blockchain ID {self.blockchain_id} isn't supported!" + ) + + self.gas_price_oracle = BLOCKCHAINS[self.environment][self.blockchain_id].get( + "gas_price_oracle", + None, + ) + + hub_address: Address = BLOCKCHAINS[self.environment][self.blockchain_id]["hub"] + self.contracts: dict[str, Contract] = { + "Hub": self.w3.eth.contract( + address=hub_address, + abi=self.abi["Hub"], + decode_tuples=True, + ) + } + + self.contracts_initialized = False + + load_dotenv() + if private_key := os.environ.get("PRIVATE_KEY"): + self.set_account(private_key) + + async def ensure_contracts_initialized(self): + if not self.contracts_initialized: + await self._init_contracts() + self.contracts_initialized = True + + async def make_json_rpc_request( + self, endpoint: str, args: dict[str, Any] = {} + ) -> Any: + web3_method = getattr(self.w3.eth, endpoint) + + if callable(web3_method): + return await web3_method(**args) + else: + return web3_method + + @staticmethod + def handle_updated_contract(func): + @wraps(func) + async def wrapper(self, *args, **kwargs): + contract_name = kwargs.get("contract") or (args[0] if args else None) + + try: + return await func(self, *args, **kwargs) + except Exception as err: + if ( + contract_name + and isinstance(contract_name, str) + and any(msg in str(err) for msg in ["revert", "VM Exception"]) + and not await self._check_contract_status(contract_name) + ): + is_updated = await self._update_contract_instance(contract_name) + if is_updated: + return await func(self, *args, **kwargs) + raise err + + return wrapper + + @handle_updated_contract + async def call_function( + self, + contract: str | dict[str, str], + function: str, + args: dict[str, Any] = {}, + state_changing: bool = False, + gas_price: Wei | None = None, + gas_limit: Wei | None = None, + ) -> TxReceipt | Any: + await self.ensure_contracts_initialized() + if isinstance(contract, str): + contract_name = contract + contract_instance = self.contracts[contract_name] + else: + contract_name = contract["name"] + contract_instance = self.w3.eth.contract( + address=contract["address"], + abi=self.abi[contract_name], + decode_tuples=True, + ) + self.contracts[contract_name] = contract_instance + + contract_function: ContractFunction = getattr( + contract_instance.functions, function + ) + + if not state_changing: + result = await contract_function(**args).call() + if function in ( + output_named_tuples := self.output_named_tuples[contract_name] + ): + result = output_named_tuples[function](*result) + return result + else: + if not hasattr(self, "account"): + raise AccountMissing( + "State-changing transactions can be performed only with specified " + "account." + ) + + options = { + "gas": gas_limit or await contract_function(**args).estimate_gas(), + } + + gas_price = ( + self.gas_price or gas_price or await self._get_network_gas_price() + ) + + if gas_price is not None: + options["gasPrice"] = gas_price + + tx_hash = await contract_function(**args).transact(options) + tx_receipt = await self.w3.eth.wait_for_transaction_receipt(tx_hash) + + return tx_receipt + + async def _get_network_gas_price(self) -> Wei | None: + if self.environment == "development": + return None + + async def fetch_gas_price(oracle_url: str) -> Wei | None: + try: + async with aiohttp.ClientSession() as session: + async with session.get(oracle_url) as response: + response.raise_for_status() + data: dict = await response.json() + + if "result" in data: + return int(data["result"], 16) + elif "average" in data: + return self.w3.to_wei(data["average"], "gwei") + else: + return None + except Exception: + return None + + oracles = self.gas_price_oracle + if oracles is not None: + if isinstance(oracles, str): + oracles = [oracles] + + for oracle_url in oracles: + gas_price = await fetch_gas_price(oracle_url) + if gas_price is not None: + return gas_price + + return None + + async def _init_contracts(self): + init_tasks = [] + for contract in self.abi.keys(): + if contract == "Hub": + continue + init_tasks.append(self._update_contract_instance(contract)) + await asyncio.gather(*init_tasks) + + async def _update_contract_instance(self, contract: str) -> bool: + [is_contract, is_storage] = await asyncio.gather( + self.contracts["Hub"].functions.isContract(contractName=contract).call(), + self.contracts["Hub"] + .functions.isAssetStorage(assetStorageName=contract) + .call(), + ) + if is_contract or is_storage: + self.contracts[contract] = self.w3.eth.contract( + address=( + await self.contracts["Hub"] + .functions.getAssetStorageAddress(contract) + .call() + if contract.endswith("AssetStorage") + or contract.endswith("CollectionStorage") + else await self.contracts["Hub"] + .functions.getContractAddress(contract) + .call() + ), + abi=self.abi[contract], + decode_tuples=True, + ) + return True + return False + + async def _check_contract_status(self, contract: str) -> bool: + try: + return await self.call_function(contract, "status") + except Exception: + return False diff --git a/dkg/providers/blockchain/base_blockchain.py b/dkg/providers/blockchain/base_blockchain.py new file mode 100644 index 0000000..5ff52d2 --- /dev/null +++ b/dkg/providers/blockchain/base_blockchain.py @@ -0,0 +1,102 @@ +import json +from collections import namedtuple +from pathlib import Path +from typing import Any, Type + +from dkg.constants import BLOCKCHAINS +from dkg.exceptions import ( + EnvironmentNotSupported, + RPCURINotDefined, +) +from dkg.types import URI, DataHexStr, Environment, Wei +from eth_account.signers.local import LocalAccount +from eth_typing import ABI, ABIFunction +from web3.logs import DISCARD +from web3.middleware import SignAndSendRawMiddlewareBuilder +from web3.types import TxReceipt + + +class BaseBlockchainProvider: + CONTRACTS_METADATA_DIR = Path(__file__).parents[2] / "data/interfaces" + + def __init__( + self, + environment: Environment, + blockchain_id: str, + rpc_uri: URI | None = None, + gas_price: Wei | None = None, + ): + if environment not in BLOCKCHAINS.keys(): + raise EnvironmentNotSupported(f"Environment {environment} isn't supported!") + + self.environment = environment + self.rpc_uri = rpc_uri + self.blockchain_id = ( + blockchain_id + if blockchain_id in BLOCKCHAINS[self.environment].keys() + else None + ) + + if self.rpc_uri is None and self.blockchain_id is not None: + self.blockchain_id = blockchain_id + self.rpc_uri = self.rpc_uri or BLOCKCHAINS[self.environment][ + self.blockchain_id + ].get("rpc", None) + + if self.rpc_uri is None: + raise RPCURINotDefined( + "No RPC URI provided for unrecognized " + f"blockchain ID {self.blockchain_id}" + ) + + self.gas_price = gas_price + + self.abi = self._load_abi() + self.output_named_tuples = self._generate_output_named_tuples() + + def _generate_output_named_tuples(self) -> dict[str, dict[str, Type[tuple]]]: + def generate_output_namedtuple(function_abi: ABIFunction) -> Type[tuple] | None: + output_names = [output["name"] for output in function_abi["outputs"]] + if all(name != "" for name in output_names): + return namedtuple(f"{function_abi['name']}Result", output_names) + return None + + output_named_tuples = {} + for contract_name, contract_abi in self.abi.items(): + output_named_tuples[contract_name] = {} + for item in contract_abi: + if (item["type"] != "function") or not item["outputs"]: + continue + elif item["name"] in output_named_tuples[contract_name]: + continue + named_tuple = generate_output_namedtuple(item) + if named_tuple is not None: + output_named_tuples[contract_name][item["name"]] = named_tuple + + return output_named_tuples + + def _load_abi(self) -> ABI: + abi = {} + + for contract_metadata in self.CONTRACTS_METADATA_DIR.glob("*.json"): + with open(contract_metadata, "r") as metadata_json: + abi[contract_metadata.stem] = json.load(metadata_json) + + return abi + + def decode_logs_event( + self, receipt: TxReceipt, contract_name: str, event_name: str + ) -> Any: + return ( + self.contracts[contract_name] + .events[event_name]() + .process_receipt(receipt, errors=DISCARD) + ) + + def set_account(self, private_key: DataHexStr): + self.account: LocalAccount = self.w3.eth.account.from_key(private_key) + self.w3.middleware_onion.inject( + SignAndSendRawMiddlewareBuilder.build(private_key), + layer=0, + ) + self.w3.eth.default_account = self.account.address diff --git a/dkg/providers/blockchain.py b/dkg/providers/blockchain/blockchain.py similarity index 69% rename from dkg/providers/blockchain.py rename to dkg/providers/blockchain/blockchain.py index 9cdd5ff..1c2f6a4 100644 --- a/dkg/providers/blockchain.py +++ b/dkg/providers/blockchain/blockchain.py @@ -15,36 +15,26 @@ # specific language governing permissions and limitations # under the License. -import json import os from dotenv import load_dotenv -from collections import namedtuple from functools import wraps -from pathlib import Path -from typing import Any, Type +from typing import Any import requests from dkg.constants import BLOCKCHAINS from dkg.exceptions import ( AccountMissing, - EnvironmentNotSupported, NetworkNotSupported, - RPCURINotDefined, ) -from dkg.types import URI, Address, DataHexStr, Environment, Wei -from eth_account.signers.local import LocalAccount -from eth_typing import ABI, ABIFunction +from dkg.types import URI, Address, Environment, Wei from web3 import Web3 from web3.contract import Contract from web3.contract.contract import ContractFunction -from web3.logs import DISCARD -from web3.middleware import SignAndSendRawMiddlewareBuilder from web3.types import TxReceipt +from dkg.providers.blockchain.base_blockchain import BaseBlockchainProvider -class BlockchainProvider: - CONTRACTS_METADATA_DIR = Path(__file__).parents[1] / "data/interfaces" - +class BlockchainProvider(BaseBlockchainProvider): def __init__( self, environment: Environment, @@ -53,28 +43,7 @@ def __init__( gas_price: Wei | None = None, verify: bool = True, ): - if environment not in BLOCKCHAINS.keys(): - raise EnvironmentNotSupported(f"Environment {environment} isn't supported!") - - self.environment = environment - self.rpc_uri = rpc_uri - self.blockchain_id = ( - blockchain_id - if blockchain_id in BLOCKCHAINS[self.environment].keys() - else None - ) - - if self.rpc_uri is None and self.blockchain_id is not None: - self.blockchain_id = blockchain_id - self.rpc_uri = self.rpc_uri or BLOCKCHAINS[self.environment][ - self.blockchain_id - ].get("rpc", None) - - if self.rpc_uri is None: - raise RPCURINotDefined( - "No RPC URI provided for unrecognized " - f"blockchain ID {self.blockchain_id}" - ) + super().__init__(environment, blockchain_id, rpc_uri, gas_price) self.w3 = Web3( Web3.HTTPProvider(self.rpc_uri, request_kwargs={"verify": verify}) @@ -87,15 +56,11 @@ def __init__( f"Network with blockchain ID {self.blockchain_id} isn't supported!" ) - self.gas_price = gas_price self.gas_price_oracle = BLOCKCHAINS[self.environment][self.blockchain_id].get( "gas_price_oracle", None, ) - self.abi = self._load_abi() - self.output_named_tuples = self._generate_output_named_tuples() - hub_address: Address = BLOCKCHAINS[self.environment][self.blockchain_id]["hub"] self.contracts: dict[str, Contract] = { "Hub": self.w3.eth.contract( @@ -194,23 +159,6 @@ def call_function( return tx_receipt - def decode_logs_event( - self, receipt: TxReceipt, contract_name: str, event_name: str - ) -> Any: - return ( - self.contracts[contract_name] - .events[event_name]() - .process_receipt(receipt, errors=DISCARD) - ) - - def set_account(self, private_key: DataHexStr): - self.account: LocalAccount = self.w3.eth.account.from_key(private_key) - self.w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(private_key), - layer=0, - ) - self.w3.eth.default_account = self.account.address - def _get_network_gas_price(self) -> Wei | None: if self.environment == "development": return None @@ -278,33 +226,3 @@ def _check_contract_status(self, contract: str) -> bool: return self.call_function(contract, "status") except Exception: return False - - def _generate_output_named_tuples(self) -> dict[str, dict[str, Type[tuple]]]: - def generate_output_namedtuple(function_abi: ABIFunction) -> Type[tuple] | None: - output_names = [output["name"] for output in function_abi["outputs"]] - if all(name != "" for name in output_names): - return namedtuple(f"{function_abi['name']}Result", output_names) - return None - - output_named_tuples = {} - for contract_name, contract_abi in self.abi.items(): - output_named_tuples[contract_name] = {} - for item in contract_abi: - if (item["type"] != "function") or not item["outputs"]: - continue - elif item["name"] in output_named_tuples[contract_name]: - continue - named_tuple = generate_output_namedtuple(item) - if named_tuple is not None: - output_named_tuples[contract_name][item["name"]] = named_tuple - - return output_named_tuples - - def _load_abi(self) -> ABI: - abi = {} - - for contract_metadata in self.CONTRACTS_METADATA_DIR.glob("*.json"): - with open(contract_metadata, "r") as metadata_json: - abi[contract_metadata.stem] = json.load(metadata_json) - - return abi diff --git a/dkg/providers/node/__init__.py b/dkg/providers/node/__init__.py new file mode 100644 index 0000000..895721f --- /dev/null +++ b/dkg/providers/node/__init__.py @@ -0,0 +1,4 @@ +from .node_http import NodeHTTPProvider +from .async_node_http import AsyncNodeHTTPProvider + +__all__ = ["NodeHTTPProvider", "AsyncNodeHTTPProvider"] diff --git a/dkg/providers/node/async_node_http.py b/dkg/providers/node/async_node_http.py new file mode 100644 index 0000000..7a3a1f4 --- /dev/null +++ b/dkg/providers/node/async_node_http.py @@ -0,0 +1,72 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from typing import Any + +import aiohttp +from dkg.dataclasses import HTTPRequestMethod, NodeResponseDict +from dkg.exceptions import HTTPRequestMethodNotSupported, NodeRequestError +from dkg.types import URI +from dkg.providers.node.base_node_http import BaseNodeHTTPProvider + + +class AsyncNodeHTTPProvider(BaseNodeHTTPProvider): + def __init__( + self, + endpoint_uri: URI | str, + api_version: str = "v1", + auth_token: str | None = None, + ): + super().__init__(endpoint_uri, api_version, auth_token) + + async def make_request( + self, + method: HTTPRequestMethod, + path: str, + params: dict[str, Any] = {}, + data: dict[str, Any] = {}, + ) -> NodeResponseDict: + url = f"{self.url}/{path}" + + async with aiohttp.ClientSession() as session: + try: + if method == HTTPRequestMethod.GET: + async with session.get( + url, params=params, headers=self.headers + ) as response: + response.raise_for_status() + response = await response.json() + elif method == HTTPRequestMethod.POST: + async with session.post( + url, json=data, headers=self.headers + ) as response: + response.raise_for_status() + response = await response.json() + else: + raise HTTPRequestMethodNotSupported( + f"{method.name} method isn't supported" + ) + + try: + return NodeResponseDict(response) + except ValueError as err: + raise NodeRequestError(f"JSON decoding failed: {err}") + + except aiohttp.ClientError as err: + raise NodeRequestError(f"Network error: {err}") + except Exception as err: + raise NodeRequestError(f"Unexpected error: {err}") diff --git a/dkg/providers/node/base_node_http.py b/dkg/providers/node/base_node_http.py new file mode 100644 index 0000000..f496037 --- /dev/null +++ b/dkg/providers/node/base_node_http.py @@ -0,0 +1,25 @@ +from abc import ABC, abstractmethod +from dkg.dataclasses import HTTPRequestMethod, NodeResponseDict +from typing import Any +from dkg.types import URI + + +class BaseNodeHTTPProvider(ABC): + def __init__( + self, + endpoint_uri: URI | str, + api_version: str = "v1", + auth_token: str | None = None, + ): + self.url = f"{URI(endpoint_uri)}/{api_version}" + self.headers = {"Authorization": f"Bearer {auth_token}"} if auth_token else {} + + @abstractmethod + async def make_request( + self, + method: HTTPRequestMethod, + path: str, + params: dict[str, Any] = {}, + data: dict[str, Any] = {}, + ) -> NodeResponseDict: + raise NotImplementedError("Subclasses must implement make_request") diff --git a/dkg/providers/node_http.py b/dkg/providers/node/node_http.py similarity index 92% rename from dkg/providers/node_http.py rename to dkg/providers/node/node_http.py index f8a122d..d437a00 100644 --- a/dkg/providers/node_http.py +++ b/dkg/providers/node/node_http.py @@ -22,17 +22,17 @@ from dkg.exceptions import HTTPRequestMethodNotSupported, NodeRequestError from dkg.types import URI from requests.exceptions import HTTPError, ConnectionError, Timeout, RequestException +from dkg.providers.node.base_node_http import BaseNodeHTTPProvider -class NodeHTTPProvider: +class NodeHTTPProvider(BaseNodeHTTPProvider): def __init__( self, endpoint_uri: URI | str, api_version: str = "v1", auth_token: str | None = None, ): - self.url = f"{URI(endpoint_uri)}/{api_version}" - self.headers = {"Authorization": f"Bearer {auth_token}"} if auth_token else {} + super().__init__(endpoint_uri, api_version, auth_token) def make_request( self, diff --git a/dkg/services/__init__.py b/dkg/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dkg/services/node_services/__init__.py b/dkg/services/node_services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dkg/services/node_services/async_node_service.py b/dkg/services/node_services/async_node_service.py new file mode 100644 index 0000000..7260bb0 --- /dev/null +++ b/dkg/services/node_services/async_node_service.py @@ -0,0 +1,205 @@ +from dkg.managers.async_manager import AsyncRequestManager +from dkg.method import Method +from dkg.constants import OperationStatuses, DefaultParameters +from dkg.utils.node_request import NodeRequest +from dkg.modules.async_module import AsyncModule +from typing import Dict, Any +from dkg.types import UAL +from dkg.dataclasses import BidSuggestionRange +from dkg.dataclasses import NodeResponseDict +import asyncio + + +class AsyncNodeService(AsyncModule): + def __init__(self, manager: AsyncRequestManager): + self.manager = manager + + _info = Method(NodeRequest.info) + _get_operation_result = Method(NodeRequest.get_operation_result) + _finality_status = Method(NodeRequest.finality_status) + _finality = Method(NodeRequest.finality) + _get_bid_suggestion = Method(NodeRequest.bid_suggestion) + _publish = Method(NodeRequest.publish) + _get = Method(NodeRequest.get) + _query = Method(NodeRequest.query) + + async def info(self) -> NodeResponseDict: + return await self._info() + + async def get_operation_result( + self, + operation_id: str, + operation: str, + max_retries: int, + frequency: int, + ) -> Dict[str, Any]: + response = {"status": OperationStatuses.PENDING.value} + + retries = 0 + + while True: + if retries > max_retries: + response["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Unable to get results. Max number of retries reached.", + } + break + + if retries > 0: + await asyncio.sleep(frequency) + + retries += 1 + + try: + result = await self._get_operation_result( + operation=operation, + operation_id=operation_id, + ) + response = {"data": result} + except Exception: + response = {"data": {"status": "NETWORK ERROR"}} + + # Check completion conditions + if ( + response["data"].get("status") == OperationStatuses.COMPLETED.value + or response["data"].get("status") == OperationStatuses.FAILED.value + ): + break + + return response["data"] + + async def finality_status( + self, + ual: UAL, + required_confirmations: int, + max_number_of_retries: int, + frequency: int, + ): + retries = 0 + finality = 0 + + while finality < required_confirmations and retries <= max_number_of_retries: + if retries > max_number_of_retries: + raise Exception( + f"Unable to achieve required confirmations. " + f"Max number of retries ({max_number_of_retries}) reached." + ) + + # Sleep between attempts (except for first try) + if retries > 0: + await asyncio.sleep(frequency) + + retries += 1 + + try: + response = await self._finality_status(ual) + finality = response.get("finality", 0) + except Exception: + finality = 0 + + return finality + + async def finality( + self, + ual: UAL, + required_confirmations: int, + max_number_of_retries: int, + frequency: int, + ): + finality_id = 0 + retries = 0 + + while finality_id < required_confirmations and retries < max_number_of_retries: + if retries > max_number_of_retries: + raise Exception( + f"Unable to achieve required confirmations. " + f"Max number of retries ({max_number_of_retries}) reached." + ) + + if retries > 0: + await asyncio.sleep(frequency) + + retries += 1 + + try: + try: + response = await self._finality( + ual=ual, minimumNumberOfNodeReplications=required_confirmations + ) + except Exception as e: + response = None + print(f"failed: {e}") + + if response is not None: + operation_id = response.json().get("operationId", 0) + if operation_id >= required_confirmations: + finality_id = operation_id + + except Exception as e: + finality_id = 0 + print(f"Retry {retries + 1}/{max_number_of_retries} failed: {e}") + + return finality_id + + async def get_bid_suggestion( + self, + blockchain_id, + additional_epochs, + latest_finalized_state_size, + content_asset_storage_address, + latest_finalized_state, + token_amount, + ): + result = await self._get_bid_suggestion( + blockchain_id, + additional_epochs, + latest_finalized_state_size, + content_asset_storage_address, + latest_finalized_state, + DefaultParameters.HASH_FUNCTION_ID.value, + token_amount or BidSuggestionRange.LOW, + ) + return int(result["bidSuggestion"]) + + async def publish( + self, + dataset_root, + dataset, + blockchain_id, + hash_function_id, + minimum_number_of_node_replications, + ): + return await self._publish( + dataset_root, + dataset, + blockchain_id, + hash_function_id, + minimum_number_of_node_replications, + ) + + async def get( + self, + ual_with_state, + content_type, + include_metadata, + hash_function_id, + paranet_ual, + subject_ual, + ): + return await self._get( + ual_with_state, + content_type, + include_metadata, + hash_function_id, + paranet_ual, + subject_ual, + ) + + async def query( + self, + query, + query_type, + repository, + paranet_ual, + ): + return await self._query(query, query_type, repository, paranet_ual) diff --git a/dkg/services/node_service.py b/dkg/services/node_services/node_service.py similarity index 97% rename from dkg/services/node_service.py rename to dkg/services/node_services/node_service.py index c9f0eb7..72f6172 100644 --- a/dkg/services/node_service.py +++ b/dkg/services/node_services/node_service.py @@ -1,6 +1,6 @@ -from dkg.manager import DefaultRequestManager +from dkg.managers.manager import DefaultRequestManager from dkg.method import Method -from dkg.module import Module +from dkg.modules.module import Module import time from dkg.utils.decorators import retry from dkg.exceptions import ( diff --git a/examples/async_demo.py b/examples/async_demo.py new file mode 100644 index 0000000..02c4ff9 --- /dev/null +++ b/examples/async_demo.py @@ -0,0 +1,123 @@ +import asyncio +import json +import time +from dkg import AsyncDKG +from dkg.constants import Environments, BlockchainIds +from dkg.providers import AsyncBlockchainProvider, AsyncNodeHTTPProvider + + +async def main(): + node_provider = AsyncNodeHTTPProvider( + endpoint_uri="http://localhost:8900", + api_version="v1", + ) + + # make sure that you have PRIVATE_KEY in .env so the blockchain provider can load it + blockchain_provider = AsyncBlockchainProvider( + Environments.DEVELOPMENT.value, + BlockchainIds.HARDHAT_1.value, + ) + + dkg = AsyncDKG( + node_provider, + blockchain_provider, + config={"max_number_of_retries": 300, "frequency": 2}, + ) + + def divider(): + print("==================================================") + print("==================================================") + print("==================================================") + + def print_json(json_dict: dict): + print(json.dumps(json_dict, indent=4)) + + content = { + "public": { + "@context": "https://schema.org", + "@id": "https://ford.mustang/2024", + "@type": "Car", + "name": "Ford Mustang", + "brand": {"@type": "Brand", "name": "Ford"}, + "model": "Mustang", + "manufacturer": {"@type": "Organization", "name": "Ford Motor Company"}, + "fuelType": "Gasoline", + "numberOfDoors": 2, + "vehicleEngine": { + "@type": "EngineSpecification", + "engineType": "V8", + "enginePower": { + "@type": "QuantitativeValue", + "value": "450", + "unitCode": "BHP", + }, + }, + "driveWheelConfiguration": "RWD", + "speed": {"@type": "QuantitativeValue", "value": "240", "unitCode": "KMH"}, + } + } + + divider() + + info_result = await dkg.node.info + print("======================== NODE INFO RECEIVED") + print_json(info_result) + + divider() + + start_time = time.perf_counter() + create_asset_result = await dkg.asset.create( + content=content, + options={ + "epochs_num": 2, + "minimum_number_of_finalization_confirmations": 3, + "minimum_number_of_node_replications": 1, + # "token_amount": 100, + }, + ) + print( + f"======================== ASSET CREATED in {time.perf_counter() - start_time} seconds" + ) + print_json(create_asset_result) + + divider() + + start_time = time.perf_counter() + get_result = await dkg.asset.get(create_asset_result.get("UAL")) + print( + f"======================== ASSET GET in {time.perf_counter() - start_time} seconds" + ) + print_json(get_result) + + divider() + + # This one is async + start_time = time.perf_counter() + query_operation_result = await dkg.graph.query( + """ + PREFIX SCHEMA: + SELECT ?s ?modelName + WHERE { + ?s schema:model ?modelName . + } + """ + ) + print( + f"======================== ASSET QUERY in {time.perf_counter() - start_time} seconds" + ) + print_json(query_operation_result) + + divider() + + start_time = time.perf_counter() + publish_finality_result = await dkg.graph.publish_finality( + create_asset_result.get("UAL") + ) + print( + f"======================== PUBLISH FINALITY in {time.perf_counter() - start_time} seconds" + ) + print_json(publish_finality_result) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/examples/demo.py b/examples/demo.py index 47774c8..00060d8 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -22,7 +22,10 @@ from dkg.providers import BlockchainProvider, NodeHTTPProvider from dkg.constants import Environments, BlockchainIds -node_provider = NodeHTTPProvider(endpoint_uri="http://localhost:8900", api_version="v1") +node_provider = NodeHTTPProvider( + endpoint_uri="http://localhost:8900", + api_version="v1", +) # make sure that you have PRIVATE_KEY in .env so the blockchain provider can load it blockchain_provider = BlockchainProvider( Environments.DEVELOPMENT.value, @@ -80,7 +83,7 @@ def print_json(json_dict: dict): divider() -start_time = time.time() +start_time = time.perf_counter() create_asset_result = dkg.asset.create( content=content, options={ @@ -90,18 +93,23 @@ def print_json(json_dict: dict): "token_amount": 100, }, ) -print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") +print( + f"======================== ASSET CREATED in {time.perf_counter() - start_time} seconds" +) print_json(create_asset_result) divider() -start_time = time.time() +start_time = time.perf_counter() get_result = dkg.asset.get(create_asset_result.get("UAL")) -print(f"======================== ASSET GET in {time.time() - start_time} seconds") +print( + f"======================== ASSET GET in {time.perf_counter() - start_time} seconds" +) print_json(get_result) divider() +start_time = time.perf_counter() query_operation_result = dkg.graph.query( """ PREFIX SCHEMA: @@ -111,12 +119,16 @@ def print_json(json_dict: dict): } """ ) -print("======================== ASSET QUERY") +print( + f"======================== ASSET QUERY in {time.perf_counter() - start_time} seconds" +) print_json(query_operation_result) -start_time = time.time() +divider() + +start_time = time.perf_counter() publish_finality_result = dkg.graph.publish_finality(create_asset_result.get("UAL")) print( - f"======================== PUBLISH FINALITY in {time.time() - start_time} seconds" + f"======================== PUBLISH FINALITY in {time.perf_counter() - start_time} seconds" ) print_json(publish_finality_result) From a4109cd56f1f9c533551ba96fc781fe5fa925db3 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 12:08:51 +0100 Subject: [PATCH 074/146] update async demo --- examples/async_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/async_demo.py b/examples/async_demo.py index 02c4ff9..dffa96f 100644 --- a/examples/async_demo.py +++ b/examples/async_demo.py @@ -72,7 +72,7 @@ def print_json(json_dict: dict): "epochs_num": 2, "minimum_number_of_finalization_confirmations": 3, "minimum_number_of_node_replications": 1, - # "token_amount": 100, + "token_amount": 100, }, ) print( From 219c1ae373ea105a8a16826349488be7cadeb8a6 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 12:14:47 +0100 Subject: [PATCH 075/146] Update project structure --- dkg/asset.py | 893 +++++++++++++++++++++++++++++++++++ dkg/clients/async_dkg.py | 2 +- dkg/clients/dkg.py | 2 +- dkg/graph.py | 118 ----- dkg/network/__init__.py | 3 + dkg/{ => network}/network.py | 0 dkg/paranet/__init__.py | 3 + dkg/{ => paranet}/paranet.py | 0 8 files changed, 901 insertions(+), 120 deletions(-) create mode 100644 dkg/asset.py delete mode 100644 dkg/graph.py create mode 100644 dkg/network/__init__.py rename dkg/{ => network}/network.py (100%) create mode 100644 dkg/paranet/__init__.py rename dkg/{ => paranet}/paranet.py (100%) diff --git a/dkg/asset.py b/dkg/asset.py new file mode 100644 index 0000000..f177727 --- /dev/null +++ b/dkg/asset.py @@ -0,0 +1,893 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import json +import hashlib +from typing import Literal, Dict, Optional, Any +from pyld import jsonld +from web3 import Web3 +from web3.constants import ADDRESS_ZERO +from web3.types import TxReceipt +from itertools import chain +from eth_abi.packed import encode_packed +from eth_account.messages import encode_defunct +from eth_account import Account +from hexbytes import HexBytes + +from dkg.constants import ( + PRIVATE_ASSERTION_PREDICATE, + PRIVATE_RESOURCE_PREDICATE, + PRIVATE_HASH_SUBJECT_PREFIX, + CHUNK_BYTE_SIZE, + MAX_FILE_SIZE, + DEFAULT_RDF_FORMAT, + Operations, + OutputTypes, + DefaultParameters, + ZERO_ADDRESS, +) +from dkg.dataclasses import ( + BidSuggestionRange, + NodeResponseDict, +) +from dkg.managers.manager import DefaultRequestManager +from dkg.method import Method +from dkg.modules.module import Module +from dkg.types import JSONLD, UAL, Address, HexStr, Wei +from dkg.utils.blockchain_request import ( + BlockchainRequest, + KnowledgeCollectionResult, + AllowanceResult, +) +from dkg.utils.node_request import ( + NodeRequest, + OperationStatus, +) +from dkg.utils.ual import format_ual, parse_ual +import dkg.utils.knowledge_collection_tools as kc_tools +import dkg.utils.knowledge_asset_tools as ka_tools + + +class KnowledgeAsset(Module): + def __init__(self, manager: DefaultRequestManager, input_service, node_service): + self.manager = manager + self.input_service = input_service + self.node_service = node_service + + _owner = Method(BlockchainRequest.owner_of) + + def is_valid_ual(self, ual: UAL) -> bool: + if not ual or not isinstance(ual, str): + raise ValueError("UAL must be a non-empty string.") + + parts = ual.split("/") + if len(parts) != 3: + raise ValueError("UAL format is incorrect.") + + prefixes = parts[0].split(":") + prefixes_number = len(prefixes) + if prefixes_number != 3 and prefixes_number != 4: + raise ValueError("Prefix format in UAL is incorrect.") + + if prefixes[0] != "did": + raise ValueError( + f"Invalid DID prefix. Expected: 'did'. Received: '{prefixes[0]}'." + ) + + if prefixes[1] != "dkg": + raise ValueError( + f"Invalid DKG prefix. Expected: 'dkg'. Received: '{prefixes[1]}'." + ) + + if prefixes[2] != ( + blockchain_name := ( + self.manager.blockchain_provider.blockchain_id.split(":")[0] + ) + ): + raise ValueError( + "Invalid blockchain name in the UAL prefix. " + f"Expected: '{blockchain_name}'. Received: '${prefixes[2]}'." + ) + + if prefixes_number == 4: + chain_id = self.manager.blockchain_provider.blockchain_id.split(":")[1] + + if int(prefixes[3]) != int(chain_id): + raise ValueError( + "Chain ID in UAL does not match the blockchain. " + f"Expected: '${chain_id}'. Received: '${prefixes[3]}'." + ) + + contract_address = self.manager.blockchain_provider.contracts[ + "ContentAssetStorage" + ].address + + if parts[1].lower() != contract_address.lower(): + raise ValueError( + "Contract address in UAL does not match. " + f"Expected: '${contract_address.lower()}'. " + f"Received: '${parts[1].lower()}'." + ) + + try: + owner = self._owner(int(parts[2])) + + if not owner or owner == ADDRESS_ZERO: + raise ValueError("Token does not exist or has no owner.") + + return True + except Exception as err: + raise ValueError(f"Error fetching asset owner: {err}") + + _get_contract_address = Method(BlockchainRequest.get_contract_address) + _get_current_allowance = Method(BlockchainRequest.allowance) + _increase_allowance = Method(BlockchainRequest.increase_allowance) + _decrease_allowance = Method(BlockchainRequest.decrease_allowance) + _chain_id = Method(BlockchainRequest.chain_id) + _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) + _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) + _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) + _epoch_length = Method(BlockchainRequest.epoch_length) + _get_stake_weighted_average_ask = Method( + BlockchainRequest.get_stake_weighted_average_ask + ) + _get_bid_suggestion = Method(NodeRequest.bid_suggestion) + _publish = Method(NodeRequest.publish) + _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) + _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + + def get_operation_status_object( + self, operation_result: Dict[str, Any], operation_id: str + ) -> Dict[str, Any]: + """ + Creates an operation status object from operation result and ID. + + Args: + operation_result: Dictionary containing operation result data + operation_id: The ID of the operation + + Returns: + Dictionary containing operation status information + """ + # Check if error_type exists in operation_result.data + operation_data = ( + {"status": operation_result.get("status"), **operation_result.get("data")} + if operation_result.get("data", {}).get("errorType") + else {"status": operation_result.get("status")} + ) + + return {"operationId": operation_id, **operation_data} + + def decrease_knowledge_collection_allowance( + self, + allowance_gap: int, + ): + knowledge_collection_address = self._get_contract_address("KnowledgeCollection") + self._decrease_allowance(knowledge_collection_address, allowance_gap) + + def increase_knowledge_collection_allowance( + self, + sender: str, + token_amount: str, + ) -> AllowanceResult: + """ + Increases the allowance for knowledge collection if necessary. + + Args: + sender: The address of the sender + token_amount: The amount of tokens to check/increase allowance for + + Returns: + AllowanceResult containing whether allowance was increased and the gap + """ + knowledge_collection_address = self._get_contract_address("KnowledgeCollection") + + allowance = self._get_current_allowance(sender, knowledge_collection_address) + allowance_gap = int(token_amount) - int(allowance) + + if allowance_gap > 0: + self._increase_allowance(knowledge_collection_address, allowance_gap) + + return AllowanceResult( + allowance_increased=True, allowance_gap=allowance_gap + ) + + return AllowanceResult(allowance_increased=False, allowance_gap=allowance_gap) + + def create_knowledge_collection( + self, + request: dict, + paranet_ka_contract: Optional[Address] = None, + paranet_token_id: Optional[int] = None, + ) -> KnowledgeCollectionResult: + """ + Creates a knowledge collection on the blockchain. + + Args: + request: dict containing all collection parameters + paranet_ka_contract: Optional paranet contract address + paranet_token_id: Optional paranet token ID + blockchain: Blockchain configuration + + Returns: + KnowledgeCollectionResult containing collection ID and transaction receipt + + Raises: + BlockchainError: If the collection creation fails + """ + sender = self.manager.blockchain_provider.account.address + allowance_increased = False + allowance_gap = 0 + + try: + # Handle allowance + if request.get("paymaster") and request.get("paymaster") != ZERO_ADDRESS: + pass + else: + allowance_result = self.increase_knowledge_collection_allowance( + sender=sender, + token_amount=request.get("tokenAmount"), + ) + allowance_increased = allowance_result.allowance_increased + allowance_gap = allowance_result.allowance_gap + + if not paranet_ka_contract and not paranet_token_id: + receipt = self._create_knowledge_collection( + request.get("publishOperationId"), + Web3.to_bytes(hexstr=request.get("merkleRoot")), + request.get("knowledgeAssetsAmount"), + request.get("byteSize"), + request.get("epochs"), + request.get("tokenAmount"), + request.get("isImmutable"), + request.get("paymaster"), + request.get("publisherNodeIdentityId"), + Web3.to_bytes(hexstr=request.get("publisherNodeR")), + Web3.to_bytes(hexstr=request.get("publisherNodeVS")), + request.get("identityIds"), + [Web3.to_bytes(hexstr=x) for x in request.get("r")], + [Web3.to_bytes(hexstr=x) for x in request.get("vs")], + ) + else: + receipt = self._mint_knowledge_asset( + paranet_ka_contract, + paranet_token_id, + list(request.values()), + ) + + event_data = self.manager.blockchain_provider.decode_logs_event( + receipt=receipt, + contract_name="KnowledgeCollectionStorage", + event_name="KnowledgeCollectionCreated", + ) + collection_id = ( + int(getattr(event_data[0].get("args", {}), "id", None)) + if event_data + else None + ) + + return KnowledgeCollectionResult( + knowledge_collection_id=collection_id, receipt=receipt + ) + + except Exception as e: + if allowance_increased: + self.decrease_knowledge_collection_allowance(allowance_gap) + raise e + + def process_content(self, content: str) -> list: + return [line.strip() for line in content.split("\n") if line.strip() != ""] + + def solidity_packed_sha256(self, types: list[str], values: list) -> str: + # Encode the values using eth_abi's encode_packed + packed_data = encode_packed(types, values) + + # Calculate SHA256 + sha256_hash = hashlib.sha256(packed_data).hexdigest() + + return f"0x{sha256_hash}" + + def insert_triple_sorted(self, triples_list: list, new_triple: str) -> int: + # Assuming triples_list is already sorted + left = 0 + right = len(triples_list) + + while left < right: + mid = (left + right) // 2 + if triples_list[mid] < new_triple: + left = mid + 1 + else: + right = mid + + # Insert the new triple at the correct position + triples_list.insert(left, new_triple) + return left + + def get_operation_status_dict(self, operation_result, operation_id): + # Check if data exists and has errorType + operation_data = ( + {"status": operation_result.get("status"), **operation_result.get("data")} + if operation_result.get("data") + and operation_result.get("data", {}).get("errorType") + else {"status": operation_result.get("status")} + ) + + return {"operationId": operation_id, **operation_data} + + def get_message_signer_address(self, dataset_root: str, signature: dict): + message = encode_defunct(HexBytes(dataset_root)) + r, s, v = signature.get("r"), signature.get("s"), signature.get("v") + r = r[2:] if r.startswith("0x") else r + s = s[2:] if s.startswith("0x") else s + + sig = "0x" + r + s + hex(v)[2:].zfill(2) + + return Account.recover_message(message, signature=sig) + + def create( + self, + content: dict[Literal["public", "private"], JSONLD], + options: dict = {}, + ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: + arguments = self.input_service.get_asset_create_arguments(options) + + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + epochs_num = arguments.get("epochs_num") + hash_function_id = arguments.get("hash_function_id") + immutable = arguments.get("immutable") + token_amount = arguments.get("token_amount") + payer = arguments.get("payer") + minimum_number_of_finalization_confirmations = arguments.get( + "minimum_number_of_finalization_confirmations" + ) + minimum_number_of_node_replications = arguments.get( + "minimum_number_of_node_replications" + ) + blockchain_id = self.manager.blockchain_provider.blockchain_id + + dataset = {} + public_content = dataset.get("public") + private_content = dataset.get("private") + if isinstance(content, str): + dataset["public"] = self.process_content(content) + elif isinstance(public_content, str) or ( + not public_content and private_content and isinstance(private_content, str) + ): + if public_content: + dataset["public"] = self.process_content(public_content) + else: + dataset["public"] = [] + + if private_content and isinstance(private_content, str): + dataset["private"] = self.process_content(private_content) + else: + dataset = kc_tools.format_dataset(content) + + public_triples_grouped = [] + + dataset["public"] = kc_tools.generate_missing_ids_for_blank_nodes( + dataset.get("public") + ) + + if dataset.get("private") and len(dataset.get("private")): + dataset["private"] = kc_tools.generate_missing_ids_for_blank_nodes( + dataset.get("private") + ) + + # Group private triples by subject and flatten + private_triples_grouped = kc_tools.group_nquads_by_subject( + dataset.get("private"), True + ) + + dataset["private"] = list(chain.from_iterable(private_triples_grouped)) + + # Compute private root and add to public + private_root = kc_tools.calculate_merkle_root(dataset.get("private")) + dataset["public"].append( + f'<{ka_tools.generate_named_node()}> <{PRIVATE_ASSERTION_PREDICATE}> "{private_root}" .' + ) + + # Compute private root and add to public + public_triples_grouped = kc_tools.group_nquads_by_subject( + dataset.get("public"), True + ) + + # Create a dictionary for public subject -> index for quick lookup + public_subject_dict = {} + for i in range(len(public_triples_grouped)): + public_subject = public_triples_grouped[i][0].split(" ")[0] + public_subject_dict[public_subject] = i + + private_triple_subject_hashes_grouped_without_public_pair = [] + + # Integrate private subjects into public or store separately if no match to be appended later + for private_triples in private_triples_grouped: + private_subject = private_triples[0].split(" ")[ + 0 + ] # Extract the private subject + + private_subject_hash = self.solidity_packed_sha256( + types=["string"], + values=[private_subject[1:-1]], + ) + + if ( + private_subject in public_subject_dict + ): # Check if there's a public pair + # If there's a public pair, insert a representation in that group + public_index = public_subject_dict.get(private_subject) + self.insert_triple_sorted( + public_triples_grouped[public_index], + f"{private_subject} <{PRIVATE_RESOURCE_PREDICATE}> <{ka_tools.generate_named_node()}> .", + ) + else: + # If no public pair, maintain separate list, inserting sorted by hash + self.insert_triple_sorted( + private_triple_subject_hashes_grouped_without_public_pair, + f"<{PRIVATE_HASH_SUBJECT_PREFIX}{private_subject_hash}> <{PRIVATE_RESOURCE_PREDICATE}> <{ka_tools.generate_named_node()}> .", + ) + + for triple in private_triple_subject_hashes_grouped_without_public_pair: + public_triples_grouped.append([triple]) + + dataset["public"] = list(chain.from_iterable(public_triples_grouped)) + else: + # No private triples, just group and flatten public + public_triples_grouped = kc_tools.group_nquads_by_subject( + dataset.get("public"), True + ) + dataset["public"] = list(chain.from_iterable(public_triples_grouped)) + + # Calculate the number of chunks + number_of_chunks = kc_tools.calculate_number_of_chunks( + dataset.get("public"), CHUNK_BYTE_SIZE + ) + dataset_size = number_of_chunks * CHUNK_BYTE_SIZE + + # Validate the assertion size in bytes + if dataset_size > MAX_FILE_SIZE: + raise ValueError(f"File size limit is {MAX_FILE_SIZE / (1024 * 1024)}MB.") + + # Calculate the Merkle root + dataset_root = kc_tools.calculate_merkle_root(dataset.get("public")) + + # Get the contract address for KnowledgeCollectionStorage + content_asset_storage_address = self._get_asset_storage_address( + "KnowledgeCollectionStorage" + ) + + publish_operation_id = self._publish( + dataset_root, + dataset, + blockchain_id, + hash_function_id, + minimum_number_of_node_replications, + )["operationId"] + publish_operation_result = self.node_service.get_operation_result( + publish_operation_id, + Operations.PUBLISH.value, + max_number_of_retries, + frequency, + ) + + if publish_operation_result.get( + "status" + ) != OperationStatus.COMPLETED and not publish_operation_result.get( + "data", {} + ).get("minAcksReached"): + return { + "datasetRoot": dataset_root, + "operation": { + "publish": self.get_operation_status_dict( + publish_operation_result, publish_operation_id + ) + }, + } + + data = publish_operation_result.get("data", {}) + signatures = data.get("signatures") + + publisher_node_signature = data.get("publisherNodeSignature", {}) + publisher_node_identity_id = publisher_node_signature.get("identityId") + publisher_node_r = publisher_node_signature.get("r") + publisher_node_vs = publisher_node_signature.get("vs") + + identity_ids, r, vs = [], [], [] + + for signature in signatures: + try: + signer_address = self.get_message_signer_address( + dataset_root, signature + ) + + key_is_operational_wallet = self._key_is_operational_wallet( + signature.get("identityId"), + Web3.solidity_keccak(["address"], [signer_address]), + 2, # IdentityLib.OPERATIONAL_KEY + ) + + # If valid, append the signature components + if key_is_operational_wallet: + identity_ids.append(signature.get("identityId")) + r.append(signature.get("r")) + vs.append(signature.get("vs")) + + except Exception: + continue + + if token_amount: + estimated_publishing_cost = token_amount + else: + time_until_next_epoch = self._time_until_next_epoch() + epoch_length = self._epoch_length() + stake_weighted_average_ask = self._get_stake_weighted_average_ask() + + # Convert to integers and perform calculation + estimated_publishing_cost = ( + ( + int(stake_weighted_average_ask) + * ( + int(epochs_num) * int(1e18) + + (int(time_until_next_epoch) * int(1e18)) // int(epoch_length) + ) + * int(dataset_size) + ) + // 1024 + // int(1e18) + ) + + knowledge_collection_id = None + mint_knowledge_asset_receipt = None + + knowledge_collection_result = self.create_knowledge_collection( + { + "publishOperationId": publish_operation_id, + "merkleRoot": dataset_root, + "knowledgeAssetsAmount": kc_tools.count_distinct_subjects( + dataset.get("public") + ), + "byteSize": dataset_size, + "epochs": epochs_num, + "tokenAmount": estimated_publishing_cost, + "isImmutable": immutable, + "paymaster": payer, + "publisherNodeIdentityId": publisher_node_identity_id, + "publisherNodeR": publisher_node_r, + "publisherNodeVS": publisher_node_vs, + "identityIds": identity_ids, + "r": r, + "vs": vs, + }, + None, + None, + ) + knowledge_collection_id = knowledge_collection_result.knowledge_collection_id + mint_knowledge_asset_receipt = knowledge_collection_result.receipt + + ual = format_ual( + blockchain_id, content_asset_storage_address, knowledge_collection_id + ) + + finality_status_result = 0 + if minimum_number_of_finalization_confirmations > 0: + finality_status_result = self.node_service.finality_status( + ual, + minimum_number_of_finalization_confirmations, + max_number_of_retries, + frequency, + ) + + return json.loads( + Web3.to_json( + { + "UAL": ual, + "datasetRoot": dataset_root, + "signatures": publish_operation_result.get("data", {}).get( + "signatures" + ), + "operation": { + "mintKnowledgeAsset": mint_knowledge_asset_receipt, + "publish": self.get_operation_status_object( + publish_operation_result, publish_operation_id + ), + "finality": { + "status": ( + "FINALIZED" + if finality_status_result + >= minimum_number_of_finalization_confirmations + else "NOT FINALIZED" + ) + }, + "numberOfConfirmations": finality_status_result, + "requiredConfirmations": minimum_number_of_finalization_confirmations, + }, + } + ) + ) + + _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) + + def submit_to_paranet( + self, ual: UAL, paranet_ual: UAL + ) -> dict[str, UAL | Address | TxReceipt]: + parsed_ual = parse_ual(ual) + knowledge_asset_storage, knowledge_asset_token_id = ( + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + parsed_paranet_ual = parse_ual(paranet_ual) + paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( + parsed_paranet_ual["contract_address"], + parsed_paranet_ual["token_id"], + ) + + receipt: TxReceipt = self._submit_knowledge_asset( + paranet_knowledge_asset_storage, + paranet_knowledge_asset_token_id, + knowledge_asset_storage, + knowledge_asset_token_id, + ) + + return { + "UAL": ual, + "paranetUAL": paranet_ual, + "paranetId": Web3.to_hex( + Web3.solidity_keccak( + ["address", "uint256"], + [knowledge_asset_storage, knowledge_asset_token_id], + ) + ), + "operation": json.loads(Web3.to_json(receipt)), + } + + _transfer = Method(BlockchainRequest.transfer_asset) + + def transfer( + self, + ual: UAL, + new_owner: Address, + ) -> dict[str, UAL | Address | TxReceipt]: + token_id = parse_ual(ual)["token_id"] + + receipt: TxReceipt = self._transfer( + self.manager.blockchain_provider.account, + new_owner, + token_id, + ) + + return { + "UAL": ual, + "owner": new_owner, + "operation": json.loads(Web3.to_json(receipt)), + } + + _burn_asset = Method(BlockchainRequest.burn_asset) + + def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: + token_id = parse_ual(ual)["token_id"] + + receipt: TxReceipt = self._burn_asset(token_id) + + return {"UAL": ual, "operation": json.loads(Web3.to_json(receipt))} + + _get_assertion_ids = Method(BlockchainRequest.get_assertion_ids) + _get_latest_assertion_id = Method(BlockchainRequest.get_latest_assertion_id) + _get_unfinalized_state = Method(BlockchainRequest.get_unfinalized_state) + + _get = Method(NodeRequest.get) + _query = Method(NodeRequest.query) + + def get(self, ual: UAL, options: dict = {}) -> dict: + arguments = self.input_service.get_asset_get_arguments(options) + + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + state = arguments.get("state") + include_metadata = arguments.get("include_metadata") + content_type = arguments.get("content_type") + validate = arguments.get("validate") + output_format = arguments.get("output_format") + hash_function_id = arguments.get("hash_function_id") + paranet_ual = arguments.get("paranet_ual") + subject_ual = arguments.get("subject_ual") + + ual_with_state = f"{ual}:{state}" if state else ual + get_public_operation_id: NodeResponseDict = self._get( + ual_with_state, + content_type, + include_metadata, + hash_function_id, + paranet_ual, + subject_ual, + )["operationId"] + + get_public_operation_result = self.node_service.get_operation_result( + get_public_operation_id, + Operations.GET.value, + max_number_of_retries, + frequency, + ) + + if subject_ual: + if get_public_operation_result.get("data"): + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + "subject_ual_pairs": get_public_operation_result.get("data"), + } + if get_public_operation_result.get("status") != "FAILED": + get_public_operation_result["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Unable to find assertion on the network!", + } + get_public_operation_result["status"] = "FAILED" + + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + metadata = get_public_operation_result.get("data") + assertion = get_public_operation_result.get("data", {}).get("assertion", None) + + if not assertion: + if get_public_operation_result.get("status") != "FAILED": + get_public_operation_result["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Unable to find assertion on the network!", + } + get_public_operation_result["status"] = "FAILED" + + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + + if validate: + is_valid = True # #TODO: Implement assertion validation logic + if not is_valid: + get_public_operation_result["data"] = { + "error_type": "DKG_CLIENT_ERROR", + "error_message": "Calculated root hashes don't match!", + } + + formatted_assertion = "\n".join( + assertion.get("public", []) + + ( + assertion.get("private") + if isinstance(assertion.get("private"), list) + else [] + ) + ) + + formatted_metadata = None + if output_format == OutputTypes.JSONLD.value: + formatted_assertion = self.to_jsonld(formatted_assertion) + + if include_metadata: + formatted_metadata = self.to_jsonld("\n".join(metadata)) + + if output_format == OutputTypes.NQUADS.value: + formatted_assertion = self.to_nquads( + formatted_assertion, DEFAULT_RDF_FORMAT + ) + if include_metadata: + formatted_metadata = self.to_nquads( + "\n".join(metadata), DEFAULT_RDF_FORMAT + ) + + result = { + "assertion": formatted_assertion, + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + + if include_metadata and metadata: + result["metadata"] = formatted_metadata + + return result + + _extend_storing_period = Method(BlockchainRequest.extend_asset_storing_period) + + def extend_storing_period( + self, + ual: UAL, + additional_epochs: int, + token_amount: Wei | None = None, + ) -> dict[str, UAL | TxReceipt]: + parsed_ual = parse_ual(ual) + blockchain_id, content_asset_storage_address, token_id = ( + parsed_ual["blockchain"], + parsed_ual["contract_address"], + parsed_ual["token_id"], + ) + + if token_amount is None: + latest_finalized_state = self._get_latest_assertion_id(token_id) + latest_finalized_state_size = self._get_assertion_size( + latest_finalized_state + ) + + token_amount = int( + self._get_bid_suggestion( + blockchain_id, + additional_epochs, + latest_finalized_state_size, + content_asset_storage_address, + latest_finalized_state, + DefaultParameters.HASH_FUNCTION_ID.value, + token_amount or BidSuggestionRange.LOW, + )["bidSuggestion"] + ) + + receipt: TxReceipt = self._extend_storing_period( + token_id, additional_epochs, token_amount + ) + + return { + "UAL": ual, + "operation": json.loads(Web3.to_json(receipt)), + } + + _get_block = Method(BlockchainRequest.get_block) + + _get_assertion_size = Method(BlockchainRequest.get_assertion_size) + + def get_owner(self, ual: UAL) -> Address: + token_id = parse_ual(ual)["token_id"] + + return self._owner(token_id) + + def to_jsonld(self, nquads: str): + options = { + "algorithm": "URDNA2015", + "format": "application/n-quads", + } + + return jsonld.from_rdf(nquads, options) + + def to_nquads(self, content, input_format): + options = { + "algorithm": "URDNA2015", + "format": "application/n-quads", + } + + if input_format: + options["inputFormat"] = input_format + try: + jsonld_data = jsonld.from_rdf(content, options) + canonized = jsonld.to_rdf(jsonld_data, options) + + if isinstance(canonized, str): + return [line for line in canonized.split("\n") if line.strip()] + + except Exception as e: + raise ValueError(f"Error processing content: {e}") diff --git a/dkg/clients/async_dkg.py b/dkg/clients/async_dkg.py index a1aff11..e5a2b5e 100644 --- a/dkg/clients/async_dkg.py +++ b/dkg/clients/async_dkg.py @@ -23,7 +23,7 @@ from dkg.graph.async_graph import AsyncGraph from dkg.managers.async_manager import AsyncRequestManager from dkg.modules.async_module import AsyncModule -from dkg.network import Network +from dkg.network.network import Network from dkg.node.async_node import AsyncNode from dkg.paranet import Paranet from dkg.types import UAL, Address, ChecksumAddress diff --git a/dkg/clients/dkg.py b/dkg/clients/dkg.py index 92763ea..527d1a7 100644 --- a/dkg/clients/dkg.py +++ b/dkg/clients/dkg.py @@ -22,7 +22,7 @@ from dkg.graph.graph import Graph from dkg.managers.manager import DefaultRequestManager from dkg.modules.module import Module -from dkg.network import Network +from dkg.network.network import Network from dkg.node.node import Node from dkg.paranet import Paranet from dkg.providers import BlockchainProvider, NodeHTTPProvider diff --git a/dkg/graph.py b/dkg/graph.py deleted file mode 100644 index b73695a..0000000 --- a/dkg/graph.py +++ /dev/null @@ -1,118 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -from rdflib.plugins.sparql.parser import parseQuery - - -from dkg.managers.manager import DefaultRequestManager -from dkg.method import Method -from dkg.modules.module import Module -from dkg.types import NQuads -from dkg.utils.node_request import ( - NodeRequest, -) -from dkg.services.node_services.node_service import NodeService -from dkg.services.input_service import InputService -from dkg.constants import Operations - - -class Graph(Module): - def __init__( - self, - manager: DefaultRequestManager, - input_service: InputService, - node_service: NodeService, - ): - self.manager = manager - self.input_service = input_service - self.node_service = node_service - - _query = Method(NodeRequest.query) - - def query( - self, - query: str, - options: dict = {}, - ) -> NQuads: - arguments = self.input_service.get_query_arguments(options) - - max_number_of_retries = arguments.get("max_number_of_retries") - frequency = arguments.get("frequency") - paranet_ual = arguments.get("paranet_ual") - repository = arguments.get("repository") - - parsed_query = parseQuery(query) - query_type = parsed_query[1].name.replace("Query", "").upper() - - result = self._query(query, query_type, repository, paranet_ual) - operation_id = result.get("operationId") - operation_result = self.node_service.get_operation_result( - operation_id, Operations.QUERY.value, max_number_of_retries, frequency - ) - - return operation_result["data"] - - def publish_finality(self, UAL, options=None): - if options is None: - options = {} - - arguments = self.input_service.get_publish_finality_arguments(options) - max_number_of_retries = arguments.get("max_number_of_retries") - minimum_number_of_finalization_confirmations = arguments.get( - "minimum_number_of_finalization_confirmations" - ) - frequency = arguments.get("frequency") - try: - finality_status_result = self.node_service.finality_status( - UAL, - minimum_number_of_finalization_confirmations, - max_number_of_retries, - frequency, - ) - except Exception as e: - return {"status": "ERROR", "error": str(e)} - - if finality_status_result == 0: - try: - finality_operation_id = self.node_service.finality( - UAL, - minimum_number_of_finalization_confirmations, - max_number_of_retries, - frequency, - ) - except Exception as e: - return {"status": "ERROR", "error": str(e)} - - try: - return self.node_service.get_operation_result( - finality_operation_id, "finality", max_number_of_retries, frequency - ) - except Exception as e: - return {"status": "NOT FINALIZED", "error": str(e)} - - elif finality_status_result >= minimum_number_of_finalization_confirmations: - return { - "status": "FINALIZED", - "numberOfConfirmations": finality_status_result, - "requiredConfirmations": minimum_number_of_finalization_confirmations, - } - else: - return { - "status": "NOT FINALIZED", - "numberOfConfirmations": finality_status_result, - "requiredConfirmations": minimum_number_of_finalization_confirmations, - } diff --git a/dkg/network/__init__.py b/dkg/network/__init__.py new file mode 100644 index 0000000..25a7f3f --- /dev/null +++ b/dkg/network/__init__.py @@ -0,0 +1,3 @@ +from .network import Network + +__all__ = ["Network"] diff --git a/dkg/network.py b/dkg/network/network.py similarity index 100% rename from dkg/network.py rename to dkg/network/network.py diff --git a/dkg/paranet/__init__.py b/dkg/paranet/__init__.py new file mode 100644 index 0000000..05a0395 --- /dev/null +++ b/dkg/paranet/__init__.py @@ -0,0 +1,3 @@ +from .paranet import Paranet + +__all__ = ["Paranet"] diff --git a/dkg/paranet.py b/dkg/paranet/paranet.py similarity index 100% rename from dkg/paranet.py rename to dkg/paranet/paranet.py From ba052be4e9e1f081c3a1ad1299a88c7651915df0 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 12:28:14 +0100 Subject: [PATCH 076/146] Reorganize project structure --- dkg/asset/asset.py | 893 ------------------------- dkg/clients/async_dkg.py | 10 +- dkg/clients/dkg.py | 10 +- dkg/modules/__init__.py | 16 + dkg/{ => modules}/asset/__init__.py | 0 dkg/{ => modules/asset}/asset.py | 0 dkg/{ => modules}/asset/async_asset.py | 0 dkg/{ => modules}/graph/__init__.py | 0 dkg/{ => modules}/graph/async_graph.py | 0 dkg/{ => modules}/graph/graph.py | 0 dkg/{ => modules}/network/__init__.py | 0 dkg/{ => modules}/network/network.py | 0 dkg/modules/node/__init__.py | 4 + dkg/{ => modules}/node/async_node.py | 0 dkg/{ => modules}/node/node.py | 0 dkg/{ => modules}/paranet/__init__.py | 0 dkg/{ => modules}/paranet/paranet.py | 0 dkg/node/__init__.py | 4 - 18 files changed, 30 insertions(+), 907 deletions(-) delete mode 100644 dkg/asset/asset.py rename dkg/{ => modules}/asset/__init__.py (100%) rename dkg/{ => modules/asset}/asset.py (100%) rename dkg/{ => modules}/asset/async_asset.py (100%) rename dkg/{ => modules}/graph/__init__.py (100%) rename dkg/{ => modules}/graph/async_graph.py (100%) rename dkg/{ => modules}/graph/graph.py (100%) rename dkg/{ => modules}/network/__init__.py (100%) rename dkg/{ => modules}/network/network.py (100%) create mode 100644 dkg/modules/node/__init__.py rename dkg/{ => modules}/node/async_node.py (100%) rename dkg/{ => modules}/node/node.py (100%) rename dkg/{ => modules}/paranet/__init__.py (100%) rename dkg/{ => modules}/paranet/paranet.py (100%) delete mode 100644 dkg/node/__init__.py diff --git a/dkg/asset/asset.py b/dkg/asset/asset.py deleted file mode 100644 index f177727..0000000 --- a/dkg/asset/asset.py +++ /dev/null @@ -1,893 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -import json -import hashlib -from typing import Literal, Dict, Optional, Any -from pyld import jsonld -from web3 import Web3 -from web3.constants import ADDRESS_ZERO -from web3.types import TxReceipt -from itertools import chain -from eth_abi.packed import encode_packed -from eth_account.messages import encode_defunct -from eth_account import Account -from hexbytes import HexBytes - -from dkg.constants import ( - PRIVATE_ASSERTION_PREDICATE, - PRIVATE_RESOURCE_PREDICATE, - PRIVATE_HASH_SUBJECT_PREFIX, - CHUNK_BYTE_SIZE, - MAX_FILE_SIZE, - DEFAULT_RDF_FORMAT, - Operations, - OutputTypes, - DefaultParameters, - ZERO_ADDRESS, -) -from dkg.dataclasses import ( - BidSuggestionRange, - NodeResponseDict, -) -from dkg.managers.manager import DefaultRequestManager -from dkg.method import Method -from dkg.modules.module import Module -from dkg.types import JSONLD, UAL, Address, HexStr, Wei -from dkg.utils.blockchain_request import ( - BlockchainRequest, - KnowledgeCollectionResult, - AllowanceResult, -) -from dkg.utils.node_request import ( - NodeRequest, - OperationStatus, -) -from dkg.utils.ual import format_ual, parse_ual -import dkg.utils.knowledge_collection_tools as kc_tools -import dkg.utils.knowledge_asset_tools as ka_tools - - -class KnowledgeAsset(Module): - def __init__(self, manager: DefaultRequestManager, input_service, node_service): - self.manager = manager - self.input_service = input_service - self.node_service = node_service - - _owner = Method(BlockchainRequest.owner_of) - - def is_valid_ual(self, ual: UAL) -> bool: - if not ual or not isinstance(ual, str): - raise ValueError("UAL must be a non-empty string.") - - parts = ual.split("/") - if len(parts) != 3: - raise ValueError("UAL format is incorrect.") - - prefixes = parts[0].split(":") - prefixes_number = len(prefixes) - if prefixes_number != 3 and prefixes_number != 4: - raise ValueError("Prefix format in UAL is incorrect.") - - if prefixes[0] != "did": - raise ValueError( - f"Invalid DID prefix. Expected: 'did'. Received: '{prefixes[0]}'." - ) - - if prefixes[1] != "dkg": - raise ValueError( - f"Invalid DKG prefix. Expected: 'dkg'. Received: '{prefixes[1]}'." - ) - - if prefixes[2] != ( - blockchain_name := ( - self.manager.blockchain_provider.blockchain_id.split(":")[0] - ) - ): - raise ValueError( - "Invalid blockchain name in the UAL prefix. " - f"Expected: '{blockchain_name}'. Received: '${prefixes[2]}'." - ) - - if prefixes_number == 4: - chain_id = self.manager.blockchain_provider.blockchain_id.split(":")[1] - - if int(prefixes[3]) != int(chain_id): - raise ValueError( - "Chain ID in UAL does not match the blockchain. " - f"Expected: '${chain_id}'. Received: '${prefixes[3]}'." - ) - - contract_address = self.manager.blockchain_provider.contracts[ - "ContentAssetStorage" - ].address - - if parts[1].lower() != contract_address.lower(): - raise ValueError( - "Contract address in UAL does not match. " - f"Expected: '${contract_address.lower()}'. " - f"Received: '${parts[1].lower()}'." - ) - - try: - owner = self._owner(int(parts[2])) - - if not owner or owner == ADDRESS_ZERO: - raise ValueError("Token does not exist or has no owner.") - - return True - except Exception as err: - raise ValueError(f"Error fetching asset owner: {err}") - - _get_contract_address = Method(BlockchainRequest.get_contract_address) - _get_current_allowance = Method(BlockchainRequest.allowance) - _increase_allowance = Method(BlockchainRequest.increase_allowance) - _decrease_allowance = Method(BlockchainRequest.decrease_allowance) - _chain_id = Method(BlockchainRequest.chain_id) - _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) - _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) - _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) - _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) - _epoch_length = Method(BlockchainRequest.epoch_length) - _get_stake_weighted_average_ask = Method( - BlockchainRequest.get_stake_weighted_average_ask - ) - _get_bid_suggestion = Method(NodeRequest.bid_suggestion) - _publish = Method(NodeRequest.publish) - _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) - _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) - - def get_operation_status_object( - self, operation_result: Dict[str, Any], operation_id: str - ) -> Dict[str, Any]: - """ - Creates an operation status object from operation result and ID. - - Args: - operation_result: Dictionary containing operation result data - operation_id: The ID of the operation - - Returns: - Dictionary containing operation status information - """ - # Check if error_type exists in operation_result.data - operation_data = ( - {"status": operation_result.get("status"), **operation_result.get("data")} - if operation_result.get("data", {}).get("errorType") - else {"status": operation_result.get("status")} - ) - - return {"operationId": operation_id, **operation_data} - - def decrease_knowledge_collection_allowance( - self, - allowance_gap: int, - ): - knowledge_collection_address = self._get_contract_address("KnowledgeCollection") - self._decrease_allowance(knowledge_collection_address, allowance_gap) - - def increase_knowledge_collection_allowance( - self, - sender: str, - token_amount: str, - ) -> AllowanceResult: - """ - Increases the allowance for knowledge collection if necessary. - - Args: - sender: The address of the sender - token_amount: The amount of tokens to check/increase allowance for - - Returns: - AllowanceResult containing whether allowance was increased and the gap - """ - knowledge_collection_address = self._get_contract_address("KnowledgeCollection") - - allowance = self._get_current_allowance(sender, knowledge_collection_address) - allowance_gap = int(token_amount) - int(allowance) - - if allowance_gap > 0: - self._increase_allowance(knowledge_collection_address, allowance_gap) - - return AllowanceResult( - allowance_increased=True, allowance_gap=allowance_gap - ) - - return AllowanceResult(allowance_increased=False, allowance_gap=allowance_gap) - - def create_knowledge_collection( - self, - request: dict, - paranet_ka_contract: Optional[Address] = None, - paranet_token_id: Optional[int] = None, - ) -> KnowledgeCollectionResult: - """ - Creates a knowledge collection on the blockchain. - - Args: - request: dict containing all collection parameters - paranet_ka_contract: Optional paranet contract address - paranet_token_id: Optional paranet token ID - blockchain: Blockchain configuration - - Returns: - KnowledgeCollectionResult containing collection ID and transaction receipt - - Raises: - BlockchainError: If the collection creation fails - """ - sender = self.manager.blockchain_provider.account.address - allowance_increased = False - allowance_gap = 0 - - try: - # Handle allowance - if request.get("paymaster") and request.get("paymaster") != ZERO_ADDRESS: - pass - else: - allowance_result = self.increase_knowledge_collection_allowance( - sender=sender, - token_amount=request.get("tokenAmount"), - ) - allowance_increased = allowance_result.allowance_increased - allowance_gap = allowance_result.allowance_gap - - if not paranet_ka_contract and not paranet_token_id: - receipt = self._create_knowledge_collection( - request.get("publishOperationId"), - Web3.to_bytes(hexstr=request.get("merkleRoot")), - request.get("knowledgeAssetsAmount"), - request.get("byteSize"), - request.get("epochs"), - request.get("tokenAmount"), - request.get("isImmutable"), - request.get("paymaster"), - request.get("publisherNodeIdentityId"), - Web3.to_bytes(hexstr=request.get("publisherNodeR")), - Web3.to_bytes(hexstr=request.get("publisherNodeVS")), - request.get("identityIds"), - [Web3.to_bytes(hexstr=x) for x in request.get("r")], - [Web3.to_bytes(hexstr=x) for x in request.get("vs")], - ) - else: - receipt = self._mint_knowledge_asset( - paranet_ka_contract, - paranet_token_id, - list(request.values()), - ) - - event_data = self.manager.blockchain_provider.decode_logs_event( - receipt=receipt, - contract_name="KnowledgeCollectionStorage", - event_name="KnowledgeCollectionCreated", - ) - collection_id = ( - int(getattr(event_data[0].get("args", {}), "id", None)) - if event_data - else None - ) - - return KnowledgeCollectionResult( - knowledge_collection_id=collection_id, receipt=receipt - ) - - except Exception as e: - if allowance_increased: - self.decrease_knowledge_collection_allowance(allowance_gap) - raise e - - def process_content(self, content: str) -> list: - return [line.strip() for line in content.split("\n") if line.strip() != ""] - - def solidity_packed_sha256(self, types: list[str], values: list) -> str: - # Encode the values using eth_abi's encode_packed - packed_data = encode_packed(types, values) - - # Calculate SHA256 - sha256_hash = hashlib.sha256(packed_data).hexdigest() - - return f"0x{sha256_hash}" - - def insert_triple_sorted(self, triples_list: list, new_triple: str) -> int: - # Assuming triples_list is already sorted - left = 0 - right = len(triples_list) - - while left < right: - mid = (left + right) // 2 - if triples_list[mid] < new_triple: - left = mid + 1 - else: - right = mid - - # Insert the new triple at the correct position - triples_list.insert(left, new_triple) - return left - - def get_operation_status_dict(self, operation_result, operation_id): - # Check if data exists and has errorType - operation_data = ( - {"status": operation_result.get("status"), **operation_result.get("data")} - if operation_result.get("data") - and operation_result.get("data", {}).get("errorType") - else {"status": operation_result.get("status")} - ) - - return {"operationId": operation_id, **operation_data} - - def get_message_signer_address(self, dataset_root: str, signature: dict): - message = encode_defunct(HexBytes(dataset_root)) - r, s, v = signature.get("r"), signature.get("s"), signature.get("v") - r = r[2:] if r.startswith("0x") else r - s = s[2:] if s.startswith("0x") else s - - sig = "0x" + r + s + hex(v)[2:].zfill(2) - - return Account.recover_message(message, signature=sig) - - def create( - self, - content: dict[Literal["public", "private"], JSONLD], - options: dict = {}, - ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: - arguments = self.input_service.get_asset_create_arguments(options) - - max_number_of_retries = arguments.get("max_number_of_retries") - frequency = arguments.get("frequency") - epochs_num = arguments.get("epochs_num") - hash_function_id = arguments.get("hash_function_id") - immutable = arguments.get("immutable") - token_amount = arguments.get("token_amount") - payer = arguments.get("payer") - minimum_number_of_finalization_confirmations = arguments.get( - "minimum_number_of_finalization_confirmations" - ) - minimum_number_of_node_replications = arguments.get( - "minimum_number_of_node_replications" - ) - blockchain_id = self.manager.blockchain_provider.blockchain_id - - dataset = {} - public_content = dataset.get("public") - private_content = dataset.get("private") - if isinstance(content, str): - dataset["public"] = self.process_content(content) - elif isinstance(public_content, str) or ( - not public_content and private_content and isinstance(private_content, str) - ): - if public_content: - dataset["public"] = self.process_content(public_content) - else: - dataset["public"] = [] - - if private_content and isinstance(private_content, str): - dataset["private"] = self.process_content(private_content) - else: - dataset = kc_tools.format_dataset(content) - - public_triples_grouped = [] - - dataset["public"] = kc_tools.generate_missing_ids_for_blank_nodes( - dataset.get("public") - ) - - if dataset.get("private") and len(dataset.get("private")): - dataset["private"] = kc_tools.generate_missing_ids_for_blank_nodes( - dataset.get("private") - ) - - # Group private triples by subject and flatten - private_triples_grouped = kc_tools.group_nquads_by_subject( - dataset.get("private"), True - ) - - dataset["private"] = list(chain.from_iterable(private_triples_grouped)) - - # Compute private root and add to public - private_root = kc_tools.calculate_merkle_root(dataset.get("private")) - dataset["public"].append( - f'<{ka_tools.generate_named_node()}> <{PRIVATE_ASSERTION_PREDICATE}> "{private_root}" .' - ) - - # Compute private root and add to public - public_triples_grouped = kc_tools.group_nquads_by_subject( - dataset.get("public"), True - ) - - # Create a dictionary for public subject -> index for quick lookup - public_subject_dict = {} - for i in range(len(public_triples_grouped)): - public_subject = public_triples_grouped[i][0].split(" ")[0] - public_subject_dict[public_subject] = i - - private_triple_subject_hashes_grouped_without_public_pair = [] - - # Integrate private subjects into public or store separately if no match to be appended later - for private_triples in private_triples_grouped: - private_subject = private_triples[0].split(" ")[ - 0 - ] # Extract the private subject - - private_subject_hash = self.solidity_packed_sha256( - types=["string"], - values=[private_subject[1:-1]], - ) - - if ( - private_subject in public_subject_dict - ): # Check if there's a public pair - # If there's a public pair, insert a representation in that group - public_index = public_subject_dict.get(private_subject) - self.insert_triple_sorted( - public_triples_grouped[public_index], - f"{private_subject} <{PRIVATE_RESOURCE_PREDICATE}> <{ka_tools.generate_named_node()}> .", - ) - else: - # If no public pair, maintain separate list, inserting sorted by hash - self.insert_triple_sorted( - private_triple_subject_hashes_grouped_without_public_pair, - f"<{PRIVATE_HASH_SUBJECT_PREFIX}{private_subject_hash}> <{PRIVATE_RESOURCE_PREDICATE}> <{ka_tools.generate_named_node()}> .", - ) - - for triple in private_triple_subject_hashes_grouped_without_public_pair: - public_triples_grouped.append([triple]) - - dataset["public"] = list(chain.from_iterable(public_triples_grouped)) - else: - # No private triples, just group and flatten public - public_triples_grouped = kc_tools.group_nquads_by_subject( - dataset.get("public"), True - ) - dataset["public"] = list(chain.from_iterable(public_triples_grouped)) - - # Calculate the number of chunks - number_of_chunks = kc_tools.calculate_number_of_chunks( - dataset.get("public"), CHUNK_BYTE_SIZE - ) - dataset_size = number_of_chunks * CHUNK_BYTE_SIZE - - # Validate the assertion size in bytes - if dataset_size > MAX_FILE_SIZE: - raise ValueError(f"File size limit is {MAX_FILE_SIZE / (1024 * 1024)}MB.") - - # Calculate the Merkle root - dataset_root = kc_tools.calculate_merkle_root(dataset.get("public")) - - # Get the contract address for KnowledgeCollectionStorage - content_asset_storage_address = self._get_asset_storage_address( - "KnowledgeCollectionStorage" - ) - - publish_operation_id = self._publish( - dataset_root, - dataset, - blockchain_id, - hash_function_id, - minimum_number_of_node_replications, - )["operationId"] - publish_operation_result = self.node_service.get_operation_result( - publish_operation_id, - Operations.PUBLISH.value, - max_number_of_retries, - frequency, - ) - - if publish_operation_result.get( - "status" - ) != OperationStatus.COMPLETED and not publish_operation_result.get( - "data", {} - ).get("minAcksReached"): - return { - "datasetRoot": dataset_root, - "operation": { - "publish": self.get_operation_status_dict( - publish_operation_result, publish_operation_id - ) - }, - } - - data = publish_operation_result.get("data", {}) - signatures = data.get("signatures") - - publisher_node_signature = data.get("publisherNodeSignature", {}) - publisher_node_identity_id = publisher_node_signature.get("identityId") - publisher_node_r = publisher_node_signature.get("r") - publisher_node_vs = publisher_node_signature.get("vs") - - identity_ids, r, vs = [], [], [] - - for signature in signatures: - try: - signer_address = self.get_message_signer_address( - dataset_root, signature - ) - - key_is_operational_wallet = self._key_is_operational_wallet( - signature.get("identityId"), - Web3.solidity_keccak(["address"], [signer_address]), - 2, # IdentityLib.OPERATIONAL_KEY - ) - - # If valid, append the signature components - if key_is_operational_wallet: - identity_ids.append(signature.get("identityId")) - r.append(signature.get("r")) - vs.append(signature.get("vs")) - - except Exception: - continue - - if token_amount: - estimated_publishing_cost = token_amount - else: - time_until_next_epoch = self._time_until_next_epoch() - epoch_length = self._epoch_length() - stake_weighted_average_ask = self._get_stake_weighted_average_ask() - - # Convert to integers and perform calculation - estimated_publishing_cost = ( - ( - int(stake_weighted_average_ask) - * ( - int(epochs_num) * int(1e18) - + (int(time_until_next_epoch) * int(1e18)) // int(epoch_length) - ) - * int(dataset_size) - ) - // 1024 - // int(1e18) - ) - - knowledge_collection_id = None - mint_knowledge_asset_receipt = None - - knowledge_collection_result = self.create_knowledge_collection( - { - "publishOperationId": publish_operation_id, - "merkleRoot": dataset_root, - "knowledgeAssetsAmount": kc_tools.count_distinct_subjects( - dataset.get("public") - ), - "byteSize": dataset_size, - "epochs": epochs_num, - "tokenAmount": estimated_publishing_cost, - "isImmutable": immutable, - "paymaster": payer, - "publisherNodeIdentityId": publisher_node_identity_id, - "publisherNodeR": publisher_node_r, - "publisherNodeVS": publisher_node_vs, - "identityIds": identity_ids, - "r": r, - "vs": vs, - }, - None, - None, - ) - knowledge_collection_id = knowledge_collection_result.knowledge_collection_id - mint_knowledge_asset_receipt = knowledge_collection_result.receipt - - ual = format_ual( - blockchain_id, content_asset_storage_address, knowledge_collection_id - ) - - finality_status_result = 0 - if minimum_number_of_finalization_confirmations > 0: - finality_status_result = self.node_service.finality_status( - ual, - minimum_number_of_finalization_confirmations, - max_number_of_retries, - frequency, - ) - - return json.loads( - Web3.to_json( - { - "UAL": ual, - "datasetRoot": dataset_root, - "signatures": publish_operation_result.get("data", {}).get( - "signatures" - ), - "operation": { - "mintKnowledgeAsset": mint_knowledge_asset_receipt, - "publish": self.get_operation_status_object( - publish_operation_result, publish_operation_id - ), - "finality": { - "status": ( - "FINALIZED" - if finality_status_result - >= minimum_number_of_finalization_confirmations - else "NOT FINALIZED" - ) - }, - "numberOfConfirmations": finality_status_result, - "requiredConfirmations": minimum_number_of_finalization_confirmations, - }, - } - ) - ) - - _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) - - def submit_to_paranet( - self, ual: UAL, paranet_ual: UAL - ) -> dict[str, UAL | Address | TxReceipt]: - parsed_ual = parse_ual(ual) - knowledge_asset_storage, knowledge_asset_token_id = ( - parsed_ual["contract_address"], - parsed_ual["token_id"], - ) - - parsed_paranet_ual = parse_ual(paranet_ual) - paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( - parsed_paranet_ual["contract_address"], - parsed_paranet_ual["token_id"], - ) - - receipt: TxReceipt = self._submit_knowledge_asset( - paranet_knowledge_asset_storage, - paranet_knowledge_asset_token_id, - knowledge_asset_storage, - knowledge_asset_token_id, - ) - - return { - "UAL": ual, - "paranetUAL": paranet_ual, - "paranetId": Web3.to_hex( - Web3.solidity_keccak( - ["address", "uint256"], - [knowledge_asset_storage, knowledge_asset_token_id], - ) - ), - "operation": json.loads(Web3.to_json(receipt)), - } - - _transfer = Method(BlockchainRequest.transfer_asset) - - def transfer( - self, - ual: UAL, - new_owner: Address, - ) -> dict[str, UAL | Address | TxReceipt]: - token_id = parse_ual(ual)["token_id"] - - receipt: TxReceipt = self._transfer( - self.manager.blockchain_provider.account, - new_owner, - token_id, - ) - - return { - "UAL": ual, - "owner": new_owner, - "operation": json.loads(Web3.to_json(receipt)), - } - - _burn_asset = Method(BlockchainRequest.burn_asset) - - def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: - token_id = parse_ual(ual)["token_id"] - - receipt: TxReceipt = self._burn_asset(token_id) - - return {"UAL": ual, "operation": json.loads(Web3.to_json(receipt))} - - _get_assertion_ids = Method(BlockchainRequest.get_assertion_ids) - _get_latest_assertion_id = Method(BlockchainRequest.get_latest_assertion_id) - _get_unfinalized_state = Method(BlockchainRequest.get_unfinalized_state) - - _get = Method(NodeRequest.get) - _query = Method(NodeRequest.query) - - def get(self, ual: UAL, options: dict = {}) -> dict: - arguments = self.input_service.get_asset_get_arguments(options) - - max_number_of_retries = arguments.get("max_number_of_retries") - frequency = arguments.get("frequency") - state = arguments.get("state") - include_metadata = arguments.get("include_metadata") - content_type = arguments.get("content_type") - validate = arguments.get("validate") - output_format = arguments.get("output_format") - hash_function_id = arguments.get("hash_function_id") - paranet_ual = arguments.get("paranet_ual") - subject_ual = arguments.get("subject_ual") - - ual_with_state = f"{ual}:{state}" if state else ual - get_public_operation_id: NodeResponseDict = self._get( - ual_with_state, - content_type, - include_metadata, - hash_function_id, - paranet_ual, - subject_ual, - )["operationId"] - - get_public_operation_result = self.node_service.get_operation_result( - get_public_operation_id, - Operations.GET.value, - max_number_of_retries, - frequency, - ) - - if subject_ual: - if get_public_operation_result.get("data"): - return { - "operation": { - "get": self.get_operation_status_object( - get_public_operation_result, get_public_operation_id - ), - }, - "subject_ual_pairs": get_public_operation_result.get("data"), - } - if get_public_operation_result.get("status") != "FAILED": - get_public_operation_result["data"] = { - "errorType": "DKG_CLIENT_ERROR", - "errorMessage": "Unable to find assertion on the network!", - } - get_public_operation_result["status"] = "FAILED" - - return { - "operation": { - "get": self.get_operation_status_object( - get_public_operation_result, get_public_operation_id - ), - }, - } - metadata = get_public_operation_result.get("data") - assertion = get_public_operation_result.get("data", {}).get("assertion", None) - - if not assertion: - if get_public_operation_result.get("status") != "FAILED": - get_public_operation_result["data"] = { - "errorType": "DKG_CLIENT_ERROR", - "errorMessage": "Unable to find assertion on the network!", - } - get_public_operation_result["status"] = "FAILED" - - return { - "operation": { - "get": self.get_operation_status_object( - get_public_operation_result, get_public_operation_id - ), - }, - } - - if validate: - is_valid = True # #TODO: Implement assertion validation logic - if not is_valid: - get_public_operation_result["data"] = { - "error_type": "DKG_CLIENT_ERROR", - "error_message": "Calculated root hashes don't match!", - } - - formatted_assertion = "\n".join( - assertion.get("public", []) - + ( - assertion.get("private") - if isinstance(assertion.get("private"), list) - else [] - ) - ) - - formatted_metadata = None - if output_format == OutputTypes.JSONLD.value: - formatted_assertion = self.to_jsonld(formatted_assertion) - - if include_metadata: - formatted_metadata = self.to_jsonld("\n".join(metadata)) - - if output_format == OutputTypes.NQUADS.value: - formatted_assertion = self.to_nquads( - formatted_assertion, DEFAULT_RDF_FORMAT - ) - if include_metadata: - formatted_metadata = self.to_nquads( - "\n".join(metadata), DEFAULT_RDF_FORMAT - ) - - result = { - "assertion": formatted_assertion, - "operation": { - "get": self.get_operation_status_object( - get_public_operation_result, get_public_operation_id - ), - }, - } - - if include_metadata and metadata: - result["metadata"] = formatted_metadata - - return result - - _extend_storing_period = Method(BlockchainRequest.extend_asset_storing_period) - - def extend_storing_period( - self, - ual: UAL, - additional_epochs: int, - token_amount: Wei | None = None, - ) -> dict[str, UAL | TxReceipt]: - parsed_ual = parse_ual(ual) - blockchain_id, content_asset_storage_address, token_id = ( - parsed_ual["blockchain"], - parsed_ual["contract_address"], - parsed_ual["token_id"], - ) - - if token_amount is None: - latest_finalized_state = self._get_latest_assertion_id(token_id) - latest_finalized_state_size = self._get_assertion_size( - latest_finalized_state - ) - - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - additional_epochs, - latest_finalized_state_size, - content_asset_storage_address, - latest_finalized_state, - DefaultParameters.HASH_FUNCTION_ID.value, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] - ) - - receipt: TxReceipt = self._extend_storing_period( - token_id, additional_epochs, token_amount - ) - - return { - "UAL": ual, - "operation": json.loads(Web3.to_json(receipt)), - } - - _get_block = Method(BlockchainRequest.get_block) - - _get_assertion_size = Method(BlockchainRequest.get_assertion_size) - - def get_owner(self, ual: UAL) -> Address: - token_id = parse_ual(ual)["token_id"] - - return self._owner(token_id) - - def to_jsonld(self, nquads: str): - options = { - "algorithm": "URDNA2015", - "format": "application/n-quads", - } - - return jsonld.from_rdf(nquads, options) - - def to_nquads(self, content, input_format): - options = { - "algorithm": "URDNA2015", - "format": "application/n-quads", - } - - if input_format: - options["inputFormat"] = input_format - try: - jsonld_data = jsonld.from_rdf(content, options) - canonized = jsonld.to_rdf(jsonld_data, options) - - if isinstance(canonized, str): - return [line for line in canonized.split("\n") if line.strip()] - - except Exception as e: - raise ValueError(f"Error processing content: {e}") diff --git a/dkg/clients/async_dkg.py b/dkg/clients/async_dkg.py index e5a2b5e..7dfbcc9 100644 --- a/dkg/clients/async_dkg.py +++ b/dkg/clients/async_dkg.py @@ -19,13 +19,13 @@ from dkg.assertion import Assertion -from dkg.asset.async_asset import AsyncKnowledgeAsset -from dkg.graph.async_graph import AsyncGraph +from dkg.modules.asset import AsyncKnowledgeAsset +from dkg.modules.graph import AsyncGraph from dkg.managers.async_manager import AsyncRequestManager from dkg.modules.async_module import AsyncModule -from dkg.network.network import Network -from dkg.node.async_node import AsyncNode -from dkg.paranet import Paranet +from dkg.modules.network import Network +from dkg.modules.node import AsyncNode +from dkg.modules.paranet import Paranet from dkg.types import UAL, Address, ChecksumAddress from dkg.utils.ual import format_ual, parse_ual from dkg.services.input_service import InputService diff --git a/dkg/clients/dkg.py b/dkg/clients/dkg.py index 527d1a7..b701f19 100644 --- a/dkg/clients/dkg.py +++ b/dkg/clients/dkg.py @@ -18,13 +18,13 @@ from functools import wraps from dkg.assertion import Assertion -from dkg.asset.asset import KnowledgeAsset -from dkg.graph.graph import Graph +from dkg.modules.asset import KnowledgeAsset +from dkg.modules.graph import Graph from dkg.managers.manager import DefaultRequestManager from dkg.modules.module import Module -from dkg.network.network import Network -from dkg.node.node import Node -from dkg.paranet import Paranet +from dkg.modules.network import Network +from dkg.modules.node import Node +from dkg.modules.paranet import Paranet from dkg.providers import BlockchainProvider, NodeHTTPProvider from dkg.types import UAL, Address, ChecksumAddress from dkg.utils.ual import format_ual, parse_ual diff --git a/dkg/modules/__init__.py b/dkg/modules/__init__.py index e69de29..8f53e0a 100644 --- a/dkg/modules/__init__.py +++ b/dkg/modules/__init__.py @@ -0,0 +1,16 @@ +from .asset import KnowledgeAsset, AsyncKnowledgeAsset +from .graph import Graph, AsyncGraph +from .node import Node, AsyncNode +from .network import Network +from .paranet import Paranet + +__all__ = [ + "KnowledgeAsset", + "AsyncKnowledgeAsset", + "Graph", + "AsyncGraph", + "Node", + "AsyncNode", + "Network", + "Paranet", +] diff --git a/dkg/asset/__init__.py b/dkg/modules/asset/__init__.py similarity index 100% rename from dkg/asset/__init__.py rename to dkg/modules/asset/__init__.py diff --git a/dkg/asset.py b/dkg/modules/asset/asset.py similarity index 100% rename from dkg/asset.py rename to dkg/modules/asset/asset.py diff --git a/dkg/asset/async_asset.py b/dkg/modules/asset/async_asset.py similarity index 100% rename from dkg/asset/async_asset.py rename to dkg/modules/asset/async_asset.py diff --git a/dkg/graph/__init__.py b/dkg/modules/graph/__init__.py similarity index 100% rename from dkg/graph/__init__.py rename to dkg/modules/graph/__init__.py diff --git a/dkg/graph/async_graph.py b/dkg/modules/graph/async_graph.py similarity index 100% rename from dkg/graph/async_graph.py rename to dkg/modules/graph/async_graph.py diff --git a/dkg/graph/graph.py b/dkg/modules/graph/graph.py similarity index 100% rename from dkg/graph/graph.py rename to dkg/modules/graph/graph.py diff --git a/dkg/network/__init__.py b/dkg/modules/network/__init__.py similarity index 100% rename from dkg/network/__init__.py rename to dkg/modules/network/__init__.py diff --git a/dkg/network/network.py b/dkg/modules/network/network.py similarity index 100% rename from dkg/network/network.py rename to dkg/modules/network/network.py diff --git a/dkg/modules/node/__init__.py b/dkg/modules/node/__init__.py new file mode 100644 index 0000000..45b18c6 --- /dev/null +++ b/dkg/modules/node/__init__.py @@ -0,0 +1,4 @@ +from .node import Node +from .async_node import AsyncNode + +__all__ = ["Node", "AsyncNode"] diff --git a/dkg/node/async_node.py b/dkg/modules/node/async_node.py similarity index 100% rename from dkg/node/async_node.py rename to dkg/modules/node/async_node.py diff --git a/dkg/node/node.py b/dkg/modules/node/node.py similarity index 100% rename from dkg/node/node.py rename to dkg/modules/node/node.py diff --git a/dkg/paranet/__init__.py b/dkg/modules/paranet/__init__.py similarity index 100% rename from dkg/paranet/__init__.py rename to dkg/modules/paranet/__init__.py diff --git a/dkg/paranet/paranet.py b/dkg/modules/paranet/paranet.py similarity index 100% rename from dkg/paranet/paranet.py rename to dkg/modules/paranet/paranet.py diff --git a/dkg/node/__init__.py b/dkg/node/__init__.py deleted file mode 100644 index beb2789..0000000 --- a/dkg/node/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from dkg.node.node import Node -from dkg.node.async_node import AsyncNode - -__all__ = ["Node", "AsyncNode"] From 386b22cb3f8e4e8eb05e57c7047a873ec3a0e1d7 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 12:38:07 +0100 Subject: [PATCH 077/146] Remove sync modules from async client --- dkg/clients/async_dkg.py | 15 +++------------ dkg/clients/dkg.py | 10 +++++----- dkg/modules/__init__.py | 16 ---------------- dkg/modules/asset/__init__.py | 4 ---- dkg/modules/graph/__init__.py | 4 ---- dkg/modules/network/__init__.py | 3 --- dkg/modules/node/__init__.py | 4 ---- dkg/modules/paranet/__init__.py | 3 --- 8 files changed, 8 insertions(+), 51 deletions(-) diff --git a/dkg/clients/async_dkg.py b/dkg/clients/async_dkg.py index 7dfbcc9..0ee092f 100644 --- a/dkg/clients/async_dkg.py +++ b/dkg/clients/async_dkg.py @@ -18,14 +18,11 @@ from functools import wraps -from dkg.assertion import Assertion -from dkg.modules.asset import AsyncKnowledgeAsset -from dkg.modules.graph import AsyncGraph +from dkg.modules.asset.async_asset import AsyncKnowledgeAsset +from dkg.modules.graph.async_graph import AsyncGraph from dkg.managers.async_manager import AsyncRequestManager from dkg.modules.async_module import AsyncModule -from dkg.modules.network import Network -from dkg.modules.node import AsyncNode -from dkg.modules.paranet import Paranet +from dkg.modules.node.async_node import AsyncNode from dkg.types import UAL, Address, ChecksumAddress from dkg.utils.ual import format_ual, parse_ual from dkg.services.input_service import InputService @@ -35,10 +32,7 @@ class AsyncDKG(AsyncModule): - assertion: Assertion asset: AsyncKnowledgeAsset - paranet: Paranet - network: Network node: AsyncNode graph: AsyncGraph @@ -53,12 +47,9 @@ def __init__( self.initialize_services(config) modules = { - "assertion": Assertion(self.manager), "asset": AsyncKnowledgeAsset( self.manager, self.input_service, self.node_service ), - "paranet": Paranet(self.manager), - "network": Network(self.manager), "node": AsyncNode(self.manager, self.node_service), "graph": AsyncGraph(self.manager, self.input_service, self.node_service), } diff --git a/dkg/clients/dkg.py b/dkg/clients/dkg.py index b701f19..252899f 100644 --- a/dkg/clients/dkg.py +++ b/dkg/clients/dkg.py @@ -18,13 +18,13 @@ from functools import wraps from dkg.assertion import Assertion -from dkg.modules.asset import KnowledgeAsset -from dkg.modules.graph import Graph +from dkg.modules.asset.asset import KnowledgeAsset +from dkg.modules.graph.graph import Graph from dkg.managers.manager import DefaultRequestManager from dkg.modules.module import Module -from dkg.modules.network import Network -from dkg.modules.node import Node -from dkg.modules.paranet import Paranet +from dkg.modules.network.network import Network +from dkg.modules.node.node import Node +from dkg.modules.paranet.paranet import Paranet from dkg.providers import BlockchainProvider, NodeHTTPProvider from dkg.types import UAL, Address, ChecksumAddress from dkg.utils.ual import format_ual, parse_ual diff --git a/dkg/modules/__init__.py b/dkg/modules/__init__.py index 8f53e0a..e69de29 100644 --- a/dkg/modules/__init__.py +++ b/dkg/modules/__init__.py @@ -1,16 +0,0 @@ -from .asset import KnowledgeAsset, AsyncKnowledgeAsset -from .graph import Graph, AsyncGraph -from .node import Node, AsyncNode -from .network import Network -from .paranet import Paranet - -__all__ = [ - "KnowledgeAsset", - "AsyncKnowledgeAsset", - "Graph", - "AsyncGraph", - "Node", - "AsyncNode", - "Network", - "Paranet", -] diff --git a/dkg/modules/asset/__init__.py b/dkg/modules/asset/__init__.py index 374697e..e69de29 100644 --- a/dkg/modules/asset/__init__.py +++ b/dkg/modules/asset/__init__.py @@ -1,4 +0,0 @@ -from .asset import KnowledgeAsset -from .async_asset import AsyncKnowledgeAsset - -__all__ = ["KnowledgeAsset", "AsyncKnowledgeAsset"] diff --git a/dkg/modules/graph/__init__.py b/dkg/modules/graph/__init__.py index 70c3b2a..e69de29 100644 --- a/dkg/modules/graph/__init__.py +++ b/dkg/modules/graph/__init__.py @@ -1,4 +0,0 @@ -from .graph import Graph -from .async_graph import AsyncGraph - -__all__ = ["Graph", "AsyncGraph"] diff --git a/dkg/modules/network/__init__.py b/dkg/modules/network/__init__.py index 25a7f3f..e69de29 100644 --- a/dkg/modules/network/__init__.py +++ b/dkg/modules/network/__init__.py @@ -1,3 +0,0 @@ -from .network import Network - -__all__ = ["Network"] diff --git a/dkg/modules/node/__init__.py b/dkg/modules/node/__init__.py index 45b18c6..e69de29 100644 --- a/dkg/modules/node/__init__.py +++ b/dkg/modules/node/__init__.py @@ -1,4 +0,0 @@ -from .node import Node -from .async_node import AsyncNode - -__all__ = ["Node", "AsyncNode"] diff --git a/dkg/modules/paranet/__init__.py b/dkg/modules/paranet/__init__.py index 05a0395..e69de29 100644 --- a/dkg/modules/paranet/__init__.py +++ b/dkg/modules/paranet/__init__.py @@ -1,3 +0,0 @@ -from .paranet import Paranet - -__all__ = ["Paranet"] From 32db848601b6233fa87a0b782f5c3b995540646c Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 13:34:21 +0100 Subject: [PATCH 078/146] PR suggestions --- dkg/constants.py | 14 +++++++++++++- dkg/modules/graph/async_graph.py | 12 ++++++------ dkg/modules/graph/graph.py | 12 ++++++------ dkg/services/node_services/async_node_service.py | 6 +++--- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/dkg/constants.py b/dkg/constants.py index b3d7a07..8a96010 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -1,4 +1,5 @@ -from enum import Enum +from enum import Enum, auto +from dkg.types import AutoStrEnumUpperCase # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -166,3 +167,14 @@ class Operations(Enum): QUERY = "query" PUBLISH_PARANET = "publishParanet" FINALITY = "finality" + + +class Status(AutoStrEnumUpperCase): + ERROR = auto() + NOT_FINALIZED = auto() + FINALIZED = auto() + NETWORK_ERROR = auto() + + +class ErrorType(AutoStrEnumUpperCase): + DKG_CLIENT_ERROR = auto() diff --git a/dkg/modules/graph/async_graph.py b/dkg/modules/graph/async_graph.py index e39e462..352a237 100644 --- a/dkg/modules/graph/async_graph.py +++ b/dkg/modules/graph/async_graph.py @@ -21,7 +21,7 @@ from dkg.managers.async_manager import AsyncRequestManager from dkg.modules.async_module import AsyncModule from dkg.types import NQuads -from dkg.constants import Operations +from dkg.constants import Operations, Status from dkg.services.input_service import InputService from dkg.services.node_services.async_node_service import AsyncNodeService from dkg.types import UAL @@ -84,7 +84,7 @@ async def publish_finality(self, UAL: UAL, options=None): frequency, ) except Exception as e: - return {"status": "ERROR", "error": str(e)} + return {"status": Status.ERROR.value, "error": str(e)} if finality_status_result == 0: try: @@ -95,24 +95,24 @@ async def publish_finality(self, UAL: UAL, options=None): frequency, ) except Exception as e: - return {"status": "ERROR", "error": str(e)} + return {"status": Status.ERROR.value, "error": str(e)} try: return await self.node_service.get_operation_result( finality_operation_id, "finality", max_number_of_retries, frequency ) except Exception as e: - return {"status": "NOT FINALIZED", "error": str(e)} + return {"status": Status.NOT_FINALIZED.value, "error": str(e)} elif finality_status_result >= minimum_number_of_finalization_confirmations: return { - "status": "FINALIZED", + "status": Status.FINALIZED.value, "numberOfConfirmations": finality_status_result, "requiredConfirmations": minimum_number_of_finalization_confirmations, } else: return { - "status": "NOT FINALIZED", + "status": Status.NOT_FINALIZED.value, "numberOfConfirmations": finality_status_result, "requiredConfirmations": minimum_number_of_finalization_confirmations, } diff --git a/dkg/modules/graph/graph.py b/dkg/modules/graph/graph.py index b73695a..16c6b54 100644 --- a/dkg/modules/graph/graph.py +++ b/dkg/modules/graph/graph.py @@ -27,7 +27,7 @@ ) from dkg.services.node_services.node_service import NodeService from dkg.services.input_service import InputService -from dkg.constants import Operations +from dkg.constants import Operations, Status class Graph(Module): @@ -84,7 +84,7 @@ def publish_finality(self, UAL, options=None): frequency, ) except Exception as e: - return {"status": "ERROR", "error": str(e)} + return {"status": Status.ERROR.value, "error": str(e)} if finality_status_result == 0: try: @@ -95,24 +95,24 @@ def publish_finality(self, UAL, options=None): frequency, ) except Exception as e: - return {"status": "ERROR", "error": str(e)} + return {"status": Status.ERROR.value, "error": str(e)} try: return self.node_service.get_operation_result( finality_operation_id, "finality", max_number_of_retries, frequency ) except Exception as e: - return {"status": "NOT FINALIZED", "error": str(e)} + return {"status": Status.NOT_FINALIZED.value, "error": str(e)} elif finality_status_result >= minimum_number_of_finalization_confirmations: return { - "status": "FINALIZED", + "status": Status.FINALIZED.value, "numberOfConfirmations": finality_status_result, "requiredConfirmations": minimum_number_of_finalization_confirmations, } else: return { - "status": "NOT FINALIZED", + "status": Status.NOT_FINALIZED.value, "numberOfConfirmations": finality_status_result, "requiredConfirmations": minimum_number_of_finalization_confirmations, } diff --git a/dkg/services/node_services/async_node_service.py b/dkg/services/node_services/async_node_service.py index 7260bb0..cd33869 100644 --- a/dkg/services/node_services/async_node_service.py +++ b/dkg/services/node_services/async_node_service.py @@ -1,6 +1,6 @@ from dkg.managers.async_manager import AsyncRequestManager from dkg.method import Method -from dkg.constants import OperationStatuses, DefaultParameters +from dkg.constants import OperationStatuses, DefaultParameters, ErrorType, Status from dkg.utils.node_request import NodeRequest from dkg.modules.async_module import AsyncModule from typing import Dict, Any @@ -40,7 +40,7 @@ async def get_operation_result( while True: if retries > max_retries: response["data"] = { - "errorType": "DKG_CLIENT_ERROR", + "errorType": ErrorType.DKG_CLIENT_ERROR.value, "errorMessage": "Unable to get results. Max number of retries reached.", } break @@ -57,7 +57,7 @@ async def get_operation_result( ) response = {"data": result} except Exception: - response = {"data": {"status": "NETWORK ERROR"}} + response = {"data": {"status": Status.NETWORK_ERROR.value}} # Check completion conditions if ( From 90082815906689f362ee45fd1ad5ce8f665a112a Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 14:32:30 +0100 Subject: [PATCH 079/146] Add async blokchain service --- dkg/clients/async_dkg.py | 9 +- dkg/modules/asset/asset.py | 3 - dkg/modules/asset/async_asset.py | 362 +++++------------- dkg/services/blockchain_services/__init__.py | 0 .../async_blockchain_service.py | 180 +++++++++ .../blockchain_services/blockchain_service.py | 7 + .../node_services/async_node_service.py | 23 +- dkg/services/node_services/node_service.py | 46 +++ dkg/utils/blockchain_request.py | 11 - dkg/utils/knowledge_collection_tools.py | 12 + dkg/utils/node_request.py | 25 +- 11 files changed, 373 insertions(+), 305 deletions(-) create mode 100644 dkg/services/blockchain_services/__init__.py create mode 100644 dkg/services/blockchain_services/async_blockchain_service.py create mode 100644 dkg/services/blockchain_services/blockchain_service.py diff --git a/dkg/clients/async_dkg.py b/dkg/clients/async_dkg.py index 0ee092f..e235238 100644 --- a/dkg/clients/async_dkg.py +++ b/dkg/clients/async_dkg.py @@ -29,6 +29,9 @@ from dkg.providers.blockchain.async_blockchain import AsyncBlockchainProvider from dkg.providers.node.async_node_http import AsyncNodeHTTPProvider from dkg.services.node_services.async_node_service import AsyncNodeService +from dkg.services.blockchain_services.async_blockchain_service import ( + AsyncBlockchainService, +) class AsyncDKG(AsyncModule): @@ -48,7 +51,10 @@ def __init__( modules = { "asset": AsyncKnowledgeAsset( - self.manager, self.input_service, self.node_service + self.manager, + self.input_service, + self.node_service, + self.blockchain_service, ), "node": AsyncNode(self.manager, self.node_service), "graph": AsyncGraph(self.manager, self.input_service, self.node_service), @@ -62,6 +68,7 @@ def __init__( def initialize_services(self, config: dict = {}): self.input_service = InputService(self.manager, config) self.node_service = AsyncNodeService(self.manager) + self.blockchain_service = AsyncBlockchainService(self.manager) @staticmethod @wraps(format_ual) diff --git a/dkg/modules/asset/asset.py b/dkg/modules/asset/asset.py index f177727..b7da1fa 100644 --- a/dkg/modules/asset/asset.py +++ b/dkg/modules/asset/asset.py @@ -137,9 +137,7 @@ def is_valid_ual(self, ual: UAL) -> bool: _get_current_allowance = Method(BlockchainRequest.allowance) _increase_allowance = Method(BlockchainRequest.increase_allowance) _decrease_allowance = Method(BlockchainRequest.decrease_allowance) - _chain_id = Method(BlockchainRequest.chain_id) _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) - _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) _epoch_length = Method(BlockchainRequest.epoch_length) @@ -687,7 +685,6 @@ def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: return {"UAL": ual, "operation": json.loads(Web3.to_json(receipt))} - _get_assertion_ids = Method(BlockchainRequest.get_assertion_ids) _get_latest_assertion_id = Method(BlockchainRequest.get_latest_assertion_id) _get_unfinalized_state = Method(BlockchainRequest.get_unfinalized_state) diff --git a/dkg/modules/asset/async_asset.py b/dkg/modules/asset/async_asset.py index 14eed9f..f8dc929 100644 --- a/dkg/modules/asset/async_asset.py +++ b/dkg/modules/asset/async_asset.py @@ -16,15 +16,13 @@ # under the License. import json -import hashlib import asyncio -from typing import Literal, Dict, Optional, Any +from typing import Literal from pyld import jsonld from web3 import Web3 from web3.constants import ADDRESS_ZERO from web3.types import TxReceipt from itertools import chain -from eth_abi.packed import encode_packed from eth_account.messages import encode_defunct from eth_account import Account from hexbytes import HexBytes @@ -38,20 +36,13 @@ DEFAULT_RDF_FORMAT, Operations, OutputTypes, - DefaultParameters, - ZERO_ADDRESS, -) -from dkg.dataclasses import ( - BidSuggestionRange, ) from dkg.managers.async_manager import AsyncRequestManager from dkg.method import Method from dkg.modules.async_module import AsyncModule -from dkg.types import JSONLD, UAL, Address, HexStr, Wei +from dkg.types import JSONLD, UAL, Address, HexStr from dkg.utils.blockchain_request import ( BlockchainRequest, - KnowledgeCollectionResult, - AllowanceResult, ) from dkg.utils.node_request import ( OperationStatus, @@ -61,6 +52,10 @@ import dkg.utils.knowledge_asset_tools as ka_tools from dkg.services.input_service import InputService from dkg.services.node_services.async_node_service import AsyncNodeService +from dkg.services.blockchain_services.async_blockchain_service import ( + AsyncBlockchainService, +) +from dkg.utils.node_request import get_operation_status_object class AsyncKnowledgeAsset(AsyncModule): @@ -69,14 +64,14 @@ def __init__( manager: AsyncRequestManager, input_service: InputService, node_service: AsyncNodeService, + blockchain_service: AsyncBlockchainService, ): self.manager = manager self.input_service = input_service self.node_service = node_service + self.blockchain_service = blockchain_service - _owner = Method(BlockchainRequest.owner_of) - - def is_valid_ual(self, ual: UAL) -> bool: + async def is_valid_ual(self, ual: UAL) -> bool: if not ual or not isinstance(ual, str): raise ValueError("UAL must be a non-empty string.") @@ -130,7 +125,7 @@ def is_valid_ual(self, ual: UAL) -> bool: ) try: - owner = self._owner(int(parts[2])) + owner = await self.blockchain_service.get_owner(int(parts[2])) if not owner or owner == ADDRESS_ZERO: raise ValueError("Token does not exist or has no owner.") @@ -139,179 +134,9 @@ def is_valid_ual(self, ual: UAL) -> bool: except Exception as err: raise ValueError(f"Error fetching asset owner: {err}") - _get_contract_address = Method(BlockchainRequest.get_contract_address) - _get_current_allowance = Method(BlockchainRequest.allowance) - _increase_allowance = Method(BlockchainRequest.increase_allowance) - _decrease_allowance = Method(BlockchainRequest.decrease_allowance) - _chain_id = Method(BlockchainRequest.chain_id) - _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) - _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) - _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) - _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) - _epoch_length = Method(BlockchainRequest.epoch_length) - _get_stake_weighted_average_ask = Method( - BlockchainRequest.get_stake_weighted_average_ask - ) - _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) - _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) - - def get_operation_status_object( - self, operation_result: Dict[str, Any], operation_id: str - ) -> Dict[str, Any]: - """ - Creates an operation status object from operation result and ID. - - Args: - operation_result: Dictionary containing operation result data - operation_id: The ID of the operation - - Returns: - Dictionary containing operation status information - """ - # Check if error_type exists in operation_result.data - operation_data = ( - {"status": operation_result.get("status"), **operation_result.get("data")} - if operation_result.get("data", {}).get("errorType") - else {"status": operation_result.get("status")} - ) - - return {"operationId": operation_id, **operation_data} - - async def decrease_knowledge_collection_allowance( - self, - allowance_gap: int, - ): - knowledge_collection_address = await self._get_contract_address( - "KnowledgeCollection" - ) - await self._decrease_allowance(knowledge_collection_address, allowance_gap) - - async def increase_knowledge_collection_allowance( - self, - sender: str, - token_amount: str, - ) -> AllowanceResult: - """ - Increases the allowance for knowledge collection if necessary. - - Args: - sender: The address of the sender - token_amount: The amount of tokens to check/increase allowance for - - Returns: - AllowanceResult containing whether allowance was increased and the gap - """ - knowledge_collection_address = await self._get_contract_address( - "KnowledgeCollection" - ) - - allowance = await self._get_current_allowance( - sender, knowledge_collection_address - ) - allowance_gap = int(token_amount) - int(allowance) - - if allowance_gap > 0: - await self._increase_allowance(knowledge_collection_address, allowance_gap) - - return AllowanceResult( - allowance_increased=True, allowance_gap=allowance_gap - ) - - return AllowanceResult(allowance_increased=False, allowance_gap=allowance_gap) - - async def create_knowledge_collection( - self, - request: dict, - paranet_ka_contract: Optional[Address] = None, - paranet_token_id: Optional[int] = None, - ) -> KnowledgeCollectionResult: - """ - Creates a knowledge collection on the blockchain. - - Args: - request: dict containing all collection parameters - paranet_ka_contract: Optional paranet contract address - paranet_token_id: Optional paranet token ID - blockchain: Blockchain configuration - - Returns: - KnowledgeCollectionResult containing collection ID and transaction receipt - - Raises: - BlockchainError: If the collection creation fails - """ - sender = self.manager.blockchain_provider.account.address - allowance_increased = False - allowance_gap = 0 - - try: - # Handle allowance - if request.get("paymaster") and request.get("paymaster") != ZERO_ADDRESS: - pass - else: - allowance_result = await self.increase_knowledge_collection_allowance( - sender=sender, - token_amount=request.get("tokenAmount"), - ) - allowance_increased = allowance_result.allowance_increased - allowance_gap = allowance_result.allowance_gap - - if not paranet_ka_contract and not paranet_token_id: - receipt = await self._create_knowledge_collection( - request.get("publishOperationId"), - Web3.to_bytes(hexstr=request.get("merkleRoot")), - request.get("knowledgeAssetsAmount"), - request.get("byteSize"), - request.get("epochs"), - request.get("tokenAmount"), - request.get("isImmutable"), - request.get("paymaster"), - request.get("publisherNodeIdentityId"), - Web3.to_bytes(hexstr=request.get("publisherNodeR")), - Web3.to_bytes(hexstr=request.get("publisherNodeVS")), - request.get("identityIds"), - [Web3.to_bytes(hexstr=x) for x in request.get("r")], - [Web3.to_bytes(hexstr=x) for x in request.get("vs")], - ) - else: - receipt = await self._mint_knowledge_asset( - paranet_ka_contract, - paranet_token_id, - list(request.values()), - ) - - event_data = self.manager.blockchain_provider.decode_logs_event( - receipt=receipt, - contract_name="KnowledgeCollectionStorage", - event_name="KnowledgeCollectionCreated", - ) - collection_id = ( - int(getattr(event_data[0].get("args", {}), "id", None)) - if event_data - else None - ) - - return KnowledgeCollectionResult( - knowledge_collection_id=collection_id, receipt=receipt - ) - - except Exception as e: - if allowance_increased: - await self.decrease_knowledge_collection_allowance(allowance_gap) - raise e - def process_content(self, content: str) -> list: return [line.strip() for line in content.split("\n") if line.strip() != ""] - def solidity_packed_sha256(self, types: list[str], values: list) -> str: - # Encode the values using eth_abi's encode_packed - packed_data = encode_packed(types, values) - - # Calculate SHA256 - sha256_hash = hashlib.sha256(packed_data).hexdigest() - - return f"0x{sha256_hash}" - def insert_triple_sorted(self, triples_list: list, new_triple: str) -> int: # Assuming triples_list is already sorted left = 0 @@ -356,10 +181,12 @@ async def process_signature(signature): dataset_root, signature ) - key_is_operational_wallet = await self._key_is_operational_wallet( - signature.get("identityId"), - Web3.solidity_keccak(["address"], [signer_address]), - 2, # IdentityLib.OPERATIONAL_KEY + key_is_operational_wallet = ( + await self.blockchain_service.key_is_operational_wallet( + signature.get("identityId"), + Web3.solidity_keccak(["address"], [signer_address]), + 2, # IdentityLib.OPERATIONAL_KEY + ) ) if key_is_operational_wallet: @@ -473,7 +300,7 @@ async def create( 0 ] # Extract the private subject - private_subject_hash = self.solidity_packed_sha256( + private_subject_hash = kc_tools.solidity_packed_sha256( types=["string"], values=[private_subject[1:-1]], ) @@ -519,8 +346,10 @@ async def create( dataset_root = kc_tools.calculate_merkle_root(dataset.get("public")) # Get the contract address for KnowledgeCollectionStorage - content_asset_storage_address = await self._get_asset_storage_address( - "KnowledgeCollectionStorage" + content_asset_storage_address = ( + await self.blockchain_service.get_asset_storage_address( + "KnowledgeCollectionStorage" + ) ) result = await self.node_service.publish( @@ -568,9 +397,13 @@ async def create( if token_amount: estimated_publishing_cost = token_amount else: - time_until_next_epoch = await self._time_until_next_epoch() - epoch_length = await self._epoch_length() - stake_weighted_average_ask = await self._get_stake_weighted_average_ask() + time_until_next_epoch = ( + await self.blockchain_service.time_until_next_epoch() + ) + epoch_length = await self.blockchain_service.epoch_length() + stake_weighted_average_ask = ( + await self.blockchain_service.get_stake_weighted_average_ask() + ) # Convert to integers and perform calculation estimated_publishing_cost = ( @@ -589,27 +422,29 @@ async def create( knowledge_collection_id = None mint_knowledge_asset_receipt = None - knowledge_collection_result = await self.create_knowledge_collection( - { - "publishOperationId": publish_operation_id, - "merkleRoot": dataset_root, - "knowledgeAssetsAmount": kc_tools.count_distinct_subjects( - dataset.get("public") - ), - "byteSize": dataset_size, - "epochs": epochs_num, - "tokenAmount": estimated_publishing_cost, - "isImmutable": immutable, - "paymaster": payer, - "publisherNodeIdentityId": publisher_node_identity_id, - "publisherNodeR": publisher_node_r, - "publisherNodeVS": publisher_node_vs, - "identityIds": identity_ids, - "r": r, - "vs": vs, - }, - None, - None, + knowledge_collection_result = ( + await self.blockchain_service.create_knowledge_collection( + { + "publishOperationId": publish_operation_id, + "merkleRoot": dataset_root, + "knowledgeAssetsAmount": kc_tools.count_distinct_subjects( + dataset.get("public") + ), + "byteSize": dataset_size, + "epochs": epochs_num, + "tokenAmount": estimated_publishing_cost, + "isImmutable": immutable, + "paymaster": payer, + "publisherNodeIdentityId": publisher_node_identity_id, + "publisherNodeR": publisher_node_r, + "publisherNodeVS": publisher_node_vs, + "identityIds": identity_ids, + "r": r, + "vs": vs, + }, + None, + None, + ) ) knowledge_collection_id = knowledge_collection_result.knowledge_collection_id mint_knowledge_asset_receipt = knowledge_collection_result.receipt @@ -637,7 +472,7 @@ async def create( ), "operation": { "mintKnowledgeAsset": mint_knowledge_asset_receipt, - "publish": self.get_operation_status_object( + "publish": get_operation_status_object( publish_operation_result, publish_operation_id ), "finality": { @@ -719,9 +554,7 @@ def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: return {"UAL": ual, "operation": json.loads(Web3.to_json(receipt))} - _get_assertion_ids = Method(BlockchainRequest.get_assertion_ids) _get_latest_assertion_id = Method(BlockchainRequest.get_latest_assertion_id) - _get_unfinalized_state = Method(BlockchainRequest.get_unfinalized_state) async def get(self, ual: UAL, options: dict = None) -> dict: if options is None: @@ -761,7 +594,7 @@ async def get(self, ual: UAL, options: dict = None) -> dict: if get_public_operation_result.get("data"): return { "operation": { - "get": self.get_operation_status_object( + "get": get_operation_status_object( get_public_operation_result, get_public_operation_id ), }, @@ -776,7 +609,7 @@ async def get(self, ual: UAL, options: dict = None) -> dict: return { "operation": { - "get": self.get_operation_status_object( + "get": get_operation_status_object( get_public_operation_result, get_public_operation_id ), }, @@ -794,7 +627,7 @@ async def get(self, ual: UAL, options: dict = None) -> dict: return { "operation": { - "get": self.get_operation_status_object( + "get": get_operation_status_object( get_public_operation_result, get_public_operation_id ), }, @@ -836,7 +669,7 @@ async def get(self, ual: UAL, options: dict = None) -> dict: result = { "assertion": formatted_assertion, "operation": { - "get": self.get_operation_status_object( + "get": get_operation_status_object( get_public_operation_result, get_public_operation_id ), }, @@ -847,55 +680,50 @@ async def get(self, ual: UAL, options: dict = None) -> dict: return result - _extend_storing_period = Method(BlockchainRequest.extend_asset_storing_period) - - async def extend_storing_period( - self, - ual: UAL, - additional_epochs: int, - token_amount: Wei | None = None, - ) -> dict[str, UAL | TxReceipt]: - parsed_ual = parse_ual(ual) - blockchain_id, content_asset_storage_address, token_id = ( - parsed_ual["blockchain"], - parsed_ual["contract_address"], - parsed_ual["token_id"], - ) - - if token_amount is None: - latest_finalized_state = self._get_latest_assertion_id(token_id) - latest_finalized_state_size = self._get_assertion_size( - latest_finalized_state - ) - - token_amount = await self.node_service.get_bid_suggestion( - blockchain_id, - additional_epochs, - latest_finalized_state_size, - content_asset_storage_address, - latest_finalized_state, - DefaultParameters.HASH_FUNCTION_ID.value, - token_amount or BidSuggestionRange.LOW, - ) - - receipt: TxReceipt = self._extend_storing_period( - token_id, additional_epochs, token_amount - ) - - return { - "UAL": ual, - "operation": json.loads(Web3.to_json(receipt)), - } + # _extend_storing_period = Method(BlockchainRequest.extend_asset_storing_period) + + # async def extend_storing_period( + # self, + # ual: UAL, + # additional_epochs: int, + # token_amount: Wei | None = None, + # ) -> dict[str, UAL | TxReceipt]: + # parsed_ual = parse_ual(ual) + # blockchain_id, content_asset_storage_address, token_id = ( + # parsed_ual["blockchain"], + # parsed_ual["contract_address"], + # parsed_ual["token_id"], + # ) + + # if token_amount is None: + # latest_finalized_state = self._get_latest_assertion_id(token_id) + # latest_finalized_state_size = self._get_assertion_size( + # latest_finalized_state + # ) + + # token_amount = await self.node_service.get_bid_suggestion( + # blockchain_id, + # additional_epochs, + # latest_finalized_state_size, + # content_asset_storage_address, + # latest_finalized_state, + # DefaultParameters.HASH_FUNCTION_ID.value, + # token_amount or BidSuggestionRange.LOW, + # ) + + # receipt: TxReceipt = self._extend_storing_period( + # token_id, additional_epochs, token_amount + # ) + + # return { + # "UAL": ual, + # "operation": json.loads(Web3.to_json(receipt)), + # } _get_block = Method(BlockchainRequest.get_block) _get_assertion_size = Method(BlockchainRequest.get_assertion_size) - def get_owner(self, ual: UAL) -> Address: - token_id = parse_ual(ual)["token_id"] - - return self._owner(token_id) - def to_jsonld(self, nquads: str): options = { "algorithm": "URDNA2015", diff --git a/dkg/services/blockchain_services/__init__.py b/dkg/services/blockchain_services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dkg/services/blockchain_services/async_blockchain_service.py b/dkg/services/blockchain_services/async_blockchain_service.py new file mode 100644 index 0000000..9fca708 --- /dev/null +++ b/dkg/services/blockchain_services/async_blockchain_service.py @@ -0,0 +1,180 @@ +from dkg.modules.async_module import AsyncModule +from dkg.managers.async_manager import AsyncRequestManager +from dkg.utils.blockchain_request import BlockchainRequest +from dkg.method import Method +from dkg.constants import ZERO_ADDRESS +from web3 import Web3 +from typing import Optional +from dkg.types import Address, UAL +from dkg.utils.blockchain_request import KnowledgeCollectionResult, AllowanceResult +from dkg.utils.ual import parse_ual + + +class AsyncBlockchainService(AsyncModule): + def __init__(self, manager: AsyncRequestManager): + self.manager = manager + + _owner = Method(BlockchainRequest.owner_of) + _get_contract_address = Method(BlockchainRequest.get_contract_address) + _get_current_allowance = Method(BlockchainRequest.allowance) + _increase_allowance = Method(BlockchainRequest.increase_allowance) + _decrease_allowance = Method(BlockchainRequest.decrease_allowance) + _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) + _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) + _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) + _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) + _epoch_length = Method(BlockchainRequest.epoch_length) + _get_stake_weighted_average_ask = Method( + BlockchainRequest.get_stake_weighted_average_ask + ) + _get_block = Method(BlockchainRequest.get_block) + + async def decrease_knowledge_collection_allowance( + self, + allowance_gap: int, + ): + knowledge_collection_address = await self._get_contract_address( + "KnowledgeCollection" + ) + await self._decrease_allowance(knowledge_collection_address, allowance_gap) + + async def increase_knowledge_collection_allowance( + self, + sender: str, + token_amount: str, + ) -> AllowanceResult: + """ + Increases the allowance for knowledge collection if necessary. + + Args: + sender: The address of the sender + token_amount: The amount of tokens to check/increase allowance for + + Returns: + AllowanceResult containing whether allowance was increased and the gap + """ + knowledge_collection_address = await self._get_contract_address( + "KnowledgeCollection" + ) + + allowance = await self._get_current_allowance( + sender, knowledge_collection_address + ) + allowance_gap = int(token_amount) - int(allowance) + + if allowance_gap > 0: + await self._increase_allowance(knowledge_collection_address, allowance_gap) + + return AllowanceResult( + allowance_increased=True, allowance_gap=allowance_gap + ) + + return AllowanceResult(allowance_increased=False, allowance_gap=allowance_gap) + + async def create_knowledge_collection( + self, + request: dict, + paranet_ka_contract: Optional[Address] = None, + paranet_token_id: Optional[int] = None, + ) -> KnowledgeCollectionResult: + """ + Creates a knowledge collection on the blockchain. + + Args: + request: dict containing all collection parameters + paranet_ka_contract: Optional paranet contract address + paranet_token_id: Optional paranet token ID + blockchain: Blockchain configuration + + Returns: + KnowledgeCollectionResult containing collection ID and transaction receipt + + Raises: + BlockchainError: If the collection creation fails + """ + sender = self.manager.blockchain_provider.account.address + allowance_increased = False + allowance_gap = 0 + + try: + # Handle allowance + if request.get("paymaster") and request.get("paymaster") != ZERO_ADDRESS: + pass + else: + allowance_result = await self.increase_knowledge_collection_allowance( + sender=sender, + token_amount=request.get("tokenAmount"), + ) + allowance_increased = allowance_result.allowance_increased + allowance_gap = allowance_result.allowance_gap + + if not paranet_ka_contract and not paranet_token_id: + receipt = await self._create_knowledge_collection( + request.get("publishOperationId"), + Web3.to_bytes(hexstr=request.get("merkleRoot")), + request.get("knowledgeAssetsAmount"), + request.get("byteSize"), + request.get("epochs"), + request.get("tokenAmount"), + request.get("isImmutable"), + request.get("paymaster"), + request.get("publisherNodeIdentityId"), + Web3.to_bytes(hexstr=request.get("publisherNodeR")), + Web3.to_bytes(hexstr=request.get("publisherNodeVS")), + request.get("identityIds"), + [Web3.to_bytes(hexstr=x) for x in request.get("r")], + [Web3.to_bytes(hexstr=x) for x in request.get("vs")], + ) + else: + receipt = await self._mint_knowledge_asset( + paranet_ka_contract, + paranet_token_id, + list(request.values()), + ) + + event_data = self.manager.blockchain_provider.decode_logs_event( + receipt=receipt, + contract_name="KnowledgeCollectionStorage", + event_name="KnowledgeCollectionCreated", + ) + collection_id = ( + int(getattr(event_data[0].get("args", {}), "id", None)) + if event_data + else None + ) + + return KnowledgeCollectionResult( + knowledge_collection_id=collection_id, receipt=receipt + ) + + except Exception as e: + if allowance_increased: + await self.decrease_knowledge_collection_allowance(allowance_gap) + raise e + + # TODO: change self._owner to v8 compatible function + async def get_owner(self, ual: UAL) -> Address: + token_id = parse_ual(ual)["token_id"] + + return await self._owner(token_id) + + async def get_asset_storage_address(self, asset_storage_name: str) -> Address: + return await self._get_asset_storage_address(asset_storage_name) + + async def key_is_operational_wallet( + self, identity_id: int, key: Address, purpose: int + ) -> bool: + return await self._key_is_operational_wallet(identity_id, key, purpose) + + async def time_until_next_epoch(self) -> int: + return await self._time_until_next_epoch() + + async def epoch_length(self) -> int: + return await self._epoch_length() + + async def get_stake_weighted_average_ask(self) -> int: + return await self._get_stake_weighted_average_ask() + + async def get_block(self, block_identifier: str | int): + return await self._get_block(block_identifier) diff --git a/dkg/services/blockchain_services/blockchain_service.py b/dkg/services/blockchain_services/blockchain_service.py new file mode 100644 index 0000000..c82e6c0 --- /dev/null +++ b/dkg/services/blockchain_services/blockchain_service.py @@ -0,0 +1,7 @@ +from dkg.modules.module import Module +from dkg.managers.manager import RequestManager + + +class BlockchainService(Module): + def __init__(self, manager: RequestManager): + self.manager = manager diff --git a/dkg/services/node_services/async_node_service.py b/dkg/services/node_services/async_node_service.py index cd33869..841f9e3 100644 --- a/dkg/services/node_services/async_node_service.py +++ b/dkg/services/node_services/async_node_service.py @@ -1,11 +1,10 @@ from dkg.managers.async_manager import AsyncRequestManager from dkg.method import Method -from dkg.constants import OperationStatuses, DefaultParameters, ErrorType, Status +from dkg.constants import OperationStatuses, ErrorType, Status from dkg.utils.node_request import NodeRequest from dkg.modules.async_module import AsyncModule from typing import Dict, Any from dkg.types import UAL -from dkg.dataclasses import BidSuggestionRange from dkg.dataclasses import NodeResponseDict import asyncio @@ -141,26 +140,6 @@ async def finality( return finality_id - async def get_bid_suggestion( - self, - blockchain_id, - additional_epochs, - latest_finalized_state_size, - content_asset_storage_address, - latest_finalized_state, - token_amount, - ): - result = await self._get_bid_suggestion( - blockchain_id, - additional_epochs, - latest_finalized_state_size, - content_asset_storage_address, - latest_finalized_state, - DefaultParameters.HASH_FUNCTION_ID.value, - token_amount or BidSuggestionRange.LOW, - ) - return int(result["bidSuggestion"]) - async def publish( self, dataset_root, diff --git a/dkg/services/node_services/node_service.py b/dkg/services/node_services/node_service.py index 72f6172..0006ef9 100644 --- a/dkg/services/node_services/node_service.py +++ b/dkg/services/node_services/node_service.py @@ -19,6 +19,9 @@ def __init__(self, manager: DefaultRequestManager): _get_operation_result = Method(NodeRequest.get_operation_result) _finality_status = Method(NodeRequest.finality_status) _finality = Method(NodeRequest.finality) + _publish = Method(NodeRequest.publish) + _get = Method(NodeRequest.get) + _query = Method(NodeRequest.query) def get_operation_result( self, operation_id: str, operation: str, max_retries: int, frequency: int @@ -114,3 +117,46 @@ def finality(self, ual, required_confirmations, max_number_of_retries, frequency print(f"Retry {retries + 1}/{max_number_of_retries} failed: {e}") return finality_id + + def publish( + self, + dataset_root, + dataset, + blockchain_id, + hash_function_id, + minimum_number_of_node_replications, + ): + return self._publish( + dataset_root, + dataset, + blockchain_id, + hash_function_id, + minimum_number_of_node_replications, + ) + + def get( + self, + ual_with_state, + content_type, + include_metadata, + hash_function_id, + paranet_ual, + subject_ual, + ): + return self._get( + ual_with_state, + content_type, + include_metadata, + hash_function_id, + paranet_ual, + subject_ual, + ) + + def query( + self, + query, + query_type, + repository, + paranet_ual, + ): + return self._query(query, query_type, repository, paranet_ual) diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index a1f87f8..f9e6d0c 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -135,11 +135,6 @@ class BlockchainRequest: function="transferFrom", args={"from": Address, "to": Address, "tokenId": int}, ) - get_assertion_ids = ContractCall( - contract="ContentAssetStorage", - function="getAssertionIds", - args={"tokenId": int}, - ) get_latest_assertion_id = ContractCall( contract="ContentAssetStorage", function="getLatestAssertionId", @@ -151,12 +146,6 @@ class BlockchainRequest: args={"tokenId": int}, ) - get_unfinalized_state = ContractCall( - contract="UnfinalizedStateStorage", - function="getUnfinalizedState", - args={"tokenId": int}, - ) - get_assertion_size = ContractCall( contract="AssertionStorage", function="getAssertionSize", diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index 6c5ad4f..66a13b8 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -8,6 +8,8 @@ from uuid import uuid4 from web3 import Web3 import math +import hashlib +from eth_abi.packed import encode_packed def normalize_dataset( @@ -234,3 +236,13 @@ def count_distinct_subjects(nquads_list: list[str]) -> int: subjects = {str(quad[0]) for quad in graph} return len(subjects) + + +def solidity_packed_sha256(types: list[str], values: list) -> str: + # Encode the values using eth_abi's encode_packed + packed_data = encode_packed(types, values) + + # Calculate SHA256 + sha256_hash = hashlib.sha256(packed_data).hexdigest() + + return f"0x{sha256_hash}" diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index abb8e7d..46075b5 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -17,7 +17,7 @@ from dataclasses import dataclass, field from enum import auto, Enum -from typing import Any, Type +from typing import Any, Type, Dict from dkg.dataclasses import BidSuggestionRange, HTTPRequestMethod from dkg.exceptions import OperationFailed, OperationNotFinished @@ -192,3 +192,26 @@ def validate_operation_status(operation_result: dict[str, Any]) -> None: ) case _: raise OperationNotFinished("Operation isn't finished") + + +def get_operation_status_object( + self, operation_result: Dict[str, Any], operation_id: str +) -> Dict[str, Any]: + """ + Creates an operation status object from operation result and ID. + + Args: + operation_result: Dictionary containing operation result data + operation_id: The ID of the operation + + Returns: + Dictionary containing operation status information + """ + # Check if error_type exists in operation_result.data + operation_data = ( + {"status": operation_result.get("status"), **operation_result.get("data")} + if operation_result.get("data", {}).get("errorType") + else {"status": operation_result.get("status")} + ) + + return {"operationId": operation_id, **operation_data} From ef20670e65e0c7ae5f9650854e9a82c120b36242 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 14:38:22 +0100 Subject: [PATCH 080/146] Fixes --- dkg/modules/asset/asset.py | 1 - dkg/utils/node_request.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/dkg/modules/asset/asset.py b/dkg/modules/asset/asset.py index b7da1fa..dc51c73 100644 --- a/dkg/modules/asset/asset.py +++ b/dkg/modules/asset/asset.py @@ -686,7 +686,6 @@ def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: return {"UAL": ual, "operation": json.loads(Web3.to_json(receipt))} _get_latest_assertion_id = Method(BlockchainRequest.get_latest_assertion_id) - _get_unfinalized_state = Method(BlockchainRequest.get_unfinalized_state) _get = Method(NodeRequest.get) _query = Method(NodeRequest.query) diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 46075b5..9ab2447 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -195,7 +195,7 @@ def validate_operation_status(operation_result: dict[str, Any]) -> None: def get_operation_status_object( - self, operation_result: Dict[str, Any], operation_id: str + operation_result: Dict[str, Any], operation_id: str ) -> Dict[str, Any]: """ Creates an operation status object from operation result and ID. From 3cdf84b5a056829cd3f58ed9cc2e1c3c84efe270 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 14:50:51 +0100 Subject: [PATCH 081/146] Add sync blockchain service --- Makefile | 2 +- dkg/clients/dkg.py | 7 +- dkg/modules/asset/asset.py | 306 +++++------------- .../blockchain_services/blockchain_service.py | 171 +++++++++- 4 files changed, 253 insertions(+), 233 deletions(-) diff --git a/Makefile b/Makefile index eeff22e..9a900bc 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ run-demo: python3 examples/demo.py ruff: + ruff check --fix ruff format - ruff check help: @echo "Available commands:" diff --git a/dkg/clients/dkg.py b/dkg/clients/dkg.py index 252899f..9ba1e1c 100644 --- a/dkg/clients/dkg.py +++ b/dkg/clients/dkg.py @@ -30,6 +30,7 @@ from dkg.utils.ual import format_ual, parse_ual from dkg.services.input_service import InputService from dkg.services.node_services.node_service import NodeService +from dkg.services.blockchain_services.blockchain_service import BlockchainService class DKG(Module): @@ -53,7 +54,10 @@ def __init__( modules = { "assertion": Assertion(self.manager), "asset": KnowledgeAsset( - self.manager, self.input_service, self.node_service + self.manager, + self.input_service, + self.node_service, + self.blockchain_service, ), "paranet": Paranet(self.manager), "network": Network(self.manager), @@ -69,6 +73,7 @@ def __init__( def initialize_services(self, config): self.input_service = InputService(self.manager, config) self.node_service = NodeService(self.manager) + self.blockchain_service = BlockchainService(self.manager) @staticmethod @wraps(format_ual) diff --git a/dkg/modules/asset/asset.py b/dkg/modules/asset/asset.py index dc51c73..34c577b 100644 --- a/dkg/modules/asset/asset.py +++ b/dkg/modules/asset/asset.py @@ -17,7 +17,7 @@ import json import hashlib -from typing import Literal, Dict, Optional, Any +from typing import Literal from pyld import jsonld from web3 import Web3 from web3.constants import ADDRESS_ZERO @@ -37,38 +37,42 @@ DEFAULT_RDF_FORMAT, Operations, OutputTypes, - DefaultParameters, - ZERO_ADDRESS, ) from dkg.dataclasses import ( - BidSuggestionRange, NodeResponseDict, ) from dkg.managers.manager import DefaultRequestManager from dkg.method import Method from dkg.modules.module import Module -from dkg.types import JSONLD, UAL, Address, HexStr, Wei +from dkg.types import JSONLD, UAL, Address, HexStr from dkg.utils.blockchain_request import ( BlockchainRequest, - KnowledgeCollectionResult, - AllowanceResult, ) from dkg.utils.node_request import ( NodeRequest, OperationStatus, + get_operation_status_object, ) from dkg.utils.ual import format_ual, parse_ual import dkg.utils.knowledge_collection_tools as kc_tools import dkg.utils.knowledge_asset_tools as ka_tools +from dkg.services.input_service import InputService +from dkg.services.node_services.node_service import NodeService +from dkg.services.blockchain_services.blockchain_service import BlockchainService class KnowledgeAsset(Module): - def __init__(self, manager: DefaultRequestManager, input_service, node_service): + def __init__( + self, + manager: DefaultRequestManager, + input_service: InputService, + node_service: NodeService, + blockchain_service: BlockchainService, + ): self.manager = manager self.input_service = input_service self.node_service = node_service - - _owner = Method(BlockchainRequest.owner_of) + self.blockchain_service = blockchain_service def is_valid_ual(self, ual: UAL) -> bool: if not ual or not isinstance(ual, str): @@ -124,7 +128,7 @@ def is_valid_ual(self, ual: UAL) -> bool: ) try: - owner = self._owner(int(parts[2])) + owner = self.blockchain_service.get_owner(int(parts[2])) if not owner or owner == ADDRESS_ZERO: raise ValueError("Token does not exist or has no owner.") @@ -133,161 +137,6 @@ def is_valid_ual(self, ual: UAL) -> bool: except Exception as err: raise ValueError(f"Error fetching asset owner: {err}") - _get_contract_address = Method(BlockchainRequest.get_contract_address) - _get_current_allowance = Method(BlockchainRequest.allowance) - _increase_allowance = Method(BlockchainRequest.increase_allowance) - _decrease_allowance = Method(BlockchainRequest.decrease_allowance) - _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) - _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) - _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) - _epoch_length = Method(BlockchainRequest.epoch_length) - _get_stake_weighted_average_ask = Method( - BlockchainRequest.get_stake_weighted_average_ask - ) - _get_bid_suggestion = Method(NodeRequest.bid_suggestion) - _publish = Method(NodeRequest.publish) - _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) - _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) - - def get_operation_status_object( - self, operation_result: Dict[str, Any], operation_id: str - ) -> Dict[str, Any]: - """ - Creates an operation status object from operation result and ID. - - Args: - operation_result: Dictionary containing operation result data - operation_id: The ID of the operation - - Returns: - Dictionary containing operation status information - """ - # Check if error_type exists in operation_result.data - operation_data = ( - {"status": operation_result.get("status"), **operation_result.get("data")} - if operation_result.get("data", {}).get("errorType") - else {"status": operation_result.get("status")} - ) - - return {"operationId": operation_id, **operation_data} - - def decrease_knowledge_collection_allowance( - self, - allowance_gap: int, - ): - knowledge_collection_address = self._get_contract_address("KnowledgeCollection") - self._decrease_allowance(knowledge_collection_address, allowance_gap) - - def increase_knowledge_collection_allowance( - self, - sender: str, - token_amount: str, - ) -> AllowanceResult: - """ - Increases the allowance for knowledge collection if necessary. - - Args: - sender: The address of the sender - token_amount: The amount of tokens to check/increase allowance for - - Returns: - AllowanceResult containing whether allowance was increased and the gap - """ - knowledge_collection_address = self._get_contract_address("KnowledgeCollection") - - allowance = self._get_current_allowance(sender, knowledge_collection_address) - allowance_gap = int(token_amount) - int(allowance) - - if allowance_gap > 0: - self._increase_allowance(knowledge_collection_address, allowance_gap) - - return AllowanceResult( - allowance_increased=True, allowance_gap=allowance_gap - ) - - return AllowanceResult(allowance_increased=False, allowance_gap=allowance_gap) - - def create_knowledge_collection( - self, - request: dict, - paranet_ka_contract: Optional[Address] = None, - paranet_token_id: Optional[int] = None, - ) -> KnowledgeCollectionResult: - """ - Creates a knowledge collection on the blockchain. - - Args: - request: dict containing all collection parameters - paranet_ka_contract: Optional paranet contract address - paranet_token_id: Optional paranet token ID - blockchain: Blockchain configuration - - Returns: - KnowledgeCollectionResult containing collection ID and transaction receipt - - Raises: - BlockchainError: If the collection creation fails - """ - sender = self.manager.blockchain_provider.account.address - allowance_increased = False - allowance_gap = 0 - - try: - # Handle allowance - if request.get("paymaster") and request.get("paymaster") != ZERO_ADDRESS: - pass - else: - allowance_result = self.increase_knowledge_collection_allowance( - sender=sender, - token_amount=request.get("tokenAmount"), - ) - allowance_increased = allowance_result.allowance_increased - allowance_gap = allowance_result.allowance_gap - - if not paranet_ka_contract and not paranet_token_id: - receipt = self._create_knowledge_collection( - request.get("publishOperationId"), - Web3.to_bytes(hexstr=request.get("merkleRoot")), - request.get("knowledgeAssetsAmount"), - request.get("byteSize"), - request.get("epochs"), - request.get("tokenAmount"), - request.get("isImmutable"), - request.get("paymaster"), - request.get("publisherNodeIdentityId"), - Web3.to_bytes(hexstr=request.get("publisherNodeR")), - Web3.to_bytes(hexstr=request.get("publisherNodeVS")), - request.get("identityIds"), - [Web3.to_bytes(hexstr=x) for x in request.get("r")], - [Web3.to_bytes(hexstr=x) for x in request.get("vs")], - ) - else: - receipt = self._mint_knowledge_asset( - paranet_ka_contract, - paranet_token_id, - list(request.values()), - ) - - event_data = self.manager.blockchain_provider.decode_logs_event( - receipt=receipt, - contract_name="KnowledgeCollectionStorage", - event_name="KnowledgeCollectionCreated", - ) - collection_id = ( - int(getattr(event_data[0].get("args", {}), "id", None)) - if event_data - else None - ) - - return KnowledgeCollectionResult( - knowledge_collection_id=collection_id, receipt=receipt - ) - - except Exception as e: - if allowance_increased: - self.decrease_knowledge_collection_allowance(allowance_gap) - raise e - def process_content(self, content: str) -> list: return [line.strip() for line in content.split("\n") if line.strip() != ""] @@ -466,11 +315,13 @@ def create( dataset_root = kc_tools.calculate_merkle_root(dataset.get("public")) # Get the contract address for KnowledgeCollectionStorage - content_asset_storage_address = self._get_asset_storage_address( - "KnowledgeCollectionStorage" + content_asset_storage_address = ( + self.blockchain_service.get_asset_storage_address( + "KnowledgeCollectionStorage" + ) ) - publish_operation_id = self._publish( + publish_operation_id = self.node_service.publish( dataset_root, dataset, blockchain_id, @@ -514,10 +365,12 @@ def create( dataset_root, signature ) - key_is_operational_wallet = self._key_is_operational_wallet( - signature.get("identityId"), - Web3.solidity_keccak(["address"], [signer_address]), - 2, # IdentityLib.OPERATIONAL_KEY + key_is_operational_wallet = ( + self.blockchain_service.key_is_operational_wallet( + signature.get("identityId"), + Web3.solidity_keccak(["address"], [signer_address]), + 2, # IdentityLib.OPERATIONAL_KEY + ) ) # If valid, append the signature components @@ -532,9 +385,11 @@ def create( if token_amount: estimated_publishing_cost = token_amount else: - time_until_next_epoch = self._time_until_next_epoch() - epoch_length = self._epoch_length() - stake_weighted_average_ask = self._get_stake_weighted_average_ask() + time_until_next_epoch = self.blockchain_service.time_until_next_epoch() + epoch_length = self.blockchain_service.epoch_length() + stake_weighted_average_ask = ( + self.blockchain_service.get_stake_weighted_average_ask() + ) # Convert to integers and perform calculation estimated_publishing_cost = ( @@ -601,7 +456,7 @@ def create( ), "operation": { "mintKnowledgeAsset": mint_knowledge_asset_receipt, - "publish": self.get_operation_status_object( + "publish": get_operation_status_object( publish_operation_result, publish_operation_id ), "finality": { @@ -725,7 +580,7 @@ def get(self, ual: UAL, options: dict = {}) -> dict: if get_public_operation_result.get("data"): return { "operation": { - "get": self.get_operation_status_object( + "get": get_operation_status_object( get_public_operation_result, get_public_operation_id ), }, @@ -740,7 +595,7 @@ def get(self, ual: UAL, options: dict = {}) -> dict: return { "operation": { - "get": self.get_operation_status_object( + "get": get_operation_status_object( get_public_operation_result, get_public_operation_id ), }, @@ -758,7 +613,7 @@ def get(self, ual: UAL, options: dict = {}) -> dict: return { "operation": { - "get": self.get_operation_status_object( + "get": get_operation_status_object( get_public_operation_result, get_public_operation_id ), }, @@ -800,7 +655,7 @@ def get(self, ual: UAL, options: dict = {}) -> dict: result = { "assertion": formatted_assertion, "operation": { - "get": self.get_operation_status_object( + "get": get_operation_status_object( get_public_operation_result, get_public_operation_id ), }, @@ -811,57 +666,50 @@ def get(self, ual: UAL, options: dict = {}) -> dict: return result - _extend_storing_period = Method(BlockchainRequest.extend_asset_storing_period) - - def extend_storing_period( - self, - ual: UAL, - additional_epochs: int, - token_amount: Wei | None = None, - ) -> dict[str, UAL | TxReceipt]: - parsed_ual = parse_ual(ual) - blockchain_id, content_asset_storage_address, token_id = ( - parsed_ual["blockchain"], - parsed_ual["contract_address"], - parsed_ual["token_id"], - ) - - if token_amount is None: - latest_finalized_state = self._get_latest_assertion_id(token_id) - latest_finalized_state_size = self._get_assertion_size( - latest_finalized_state - ) - - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - additional_epochs, - latest_finalized_state_size, - content_asset_storage_address, - latest_finalized_state, - DefaultParameters.HASH_FUNCTION_ID.value, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] - ) - - receipt: TxReceipt = self._extend_storing_period( - token_id, additional_epochs, token_amount - ) - - return { - "UAL": ual, - "operation": json.loads(Web3.to_json(receipt)), - } - - _get_block = Method(BlockchainRequest.get_block) + # _extend_storing_period = Method(BlockchainRequest.extend_asset_storing_period) + + # def extend_storing_period( + # self, + # ual: UAL, + # additional_epochs: int, + # token_amount: Wei | None = None, + # ) -> dict[str, UAL | TxReceipt]: + # parsed_ual = parse_ual(ual) + # blockchain_id, content_asset_storage_address, token_id = ( + # parsed_ual["blockchain"], + # parsed_ual["contract_address"], + # parsed_ual["token_id"], + # ) + + # if token_amount is None: + # latest_finalized_state = self._get_latest_assertion_id(token_id) + # latest_finalized_state_size = self._get_assertion_size( + # latest_finalized_state + # ) + + # token_amount = int( + # self._get_bid_suggestion( + # blockchain_id, + # additional_epochs, + # latest_finalized_state_size, + # content_asset_storage_address, + # latest_finalized_state, + # DefaultParameters.HASH_FUNCTION_ID.value, + # token_amount or BidSuggestionRange.LOW, + # )["bidSuggestion"] + # ) + + # receipt: TxReceipt = self._extend_storing_period( + # token_id, additional_epochs, token_amount + # ) + + # return { + # "UAL": ual, + # "operation": json.loads(Web3.to_json(receipt)), + # } _get_assertion_size = Method(BlockchainRequest.get_assertion_size) - def get_owner(self, ual: UAL) -> Address: - token_id = parse_ual(ual)["token_id"] - - return self._owner(token_id) - def to_jsonld(self, nquads: str): options = { "algorithm": "URDNA2015", diff --git a/dkg/services/blockchain_services/blockchain_service.py b/dkg/services/blockchain_services/blockchain_service.py index c82e6c0..b39ab66 100644 --- a/dkg/services/blockchain_services/blockchain_service.py +++ b/dkg/services/blockchain_services/blockchain_service.py @@ -1,7 +1,174 @@ from dkg.modules.module import Module -from dkg.managers.manager import RequestManager +from dkg.managers.manager import DefaultRequestManager +from dkg.utils.blockchain_request import BlockchainRequest +from dkg.method import Method +from dkg.constants import ZERO_ADDRESS +from web3 import Web3 +from typing import Optional +from dkg.types import Address, UAL +from dkg.utils.blockchain_request import KnowledgeCollectionResult, AllowanceResult +from dkg.utils.ual import parse_ual class BlockchainService(Module): - def __init__(self, manager: RequestManager): + def __init__(self, manager: DefaultRequestManager): self.manager = manager + + _owner = Method(BlockchainRequest.owner_of) + _get_contract_address = Method(BlockchainRequest.get_contract_address) + _get_current_allowance = Method(BlockchainRequest.allowance) + _increase_allowance = Method(BlockchainRequest.increase_allowance) + _decrease_allowance = Method(BlockchainRequest.decrease_allowance) + _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) + _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) + _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) + _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) + _epoch_length = Method(BlockchainRequest.epoch_length) + _get_stake_weighted_average_ask = Method( + BlockchainRequest.get_stake_weighted_average_ask + ) + _get_block = Method(BlockchainRequest.get_block) + + def decrease_knowledge_collection_allowance( + self, + allowance_gap: int, + ): + knowledge_collection_address = self._get_contract_address("KnowledgeCollection") + self._decrease_allowance(knowledge_collection_address, allowance_gap) + + def increase_knowledge_collection_allowance( + self, + sender: str, + token_amount: str, + ) -> AllowanceResult: + """ + Increases the allowance for knowledge collection if necessary. + + Args: + sender: The address of the sender + token_amount: The amount of tokens to check/increase allowance for + + Returns: + AllowanceResult containing whether allowance was increased and the gap + """ + knowledge_collection_address = self._get_contract_address("KnowledgeCollection") + + allowance = self._get_current_allowance(sender, knowledge_collection_address) + allowance_gap = int(token_amount) - int(allowance) + + if allowance_gap > 0: + self._increase_allowance(knowledge_collection_address, allowance_gap) + + return AllowanceResult( + allowance_increased=True, allowance_gap=allowance_gap + ) + + return AllowanceResult(allowance_increased=False, allowance_gap=allowance_gap) + + def create_knowledge_collection( + self, + request: dict, + paranet_ka_contract: Optional[Address] = None, + paranet_token_id: Optional[int] = None, + ) -> KnowledgeCollectionResult: + """ + Creates a knowledge collection on the blockchain. + + Args: + request: dict containing all collection parameters + paranet_ka_contract: Optional paranet contract address + paranet_token_id: Optional paranet token ID + blockchain: Blockchain configuration + + Returns: + KnowledgeCollectionResult containing collection ID and transaction receipt + + Raises: + BlockchainError: If the collection creation fails + """ + sender = self.manager.blockchain_provider.account.address + allowance_increased = False + allowance_gap = 0 + + try: + # Handle allowance + if request.get("paymaster") and request.get("paymaster") != ZERO_ADDRESS: + pass + else: + allowance_result = self.increase_knowledge_collection_allowance( + sender=sender, + token_amount=request.get("tokenAmount"), + ) + allowance_increased = allowance_result.allowance_increased + allowance_gap = allowance_result.allowance_gap + + if not paranet_ka_contract and not paranet_token_id: + receipt = self._create_knowledge_collection( + request.get("publishOperationId"), + Web3.to_bytes(hexstr=request.get("merkleRoot")), + request.get("knowledgeAssetsAmount"), + request.get("byteSize"), + request.get("epochs"), + request.get("tokenAmount"), + request.get("isImmutable"), + request.get("paymaster"), + request.get("publisherNodeIdentityId"), + Web3.to_bytes(hexstr=request.get("publisherNodeR")), + Web3.to_bytes(hexstr=request.get("publisherNodeVS")), + request.get("identityIds"), + [Web3.to_bytes(hexstr=x) for x in request.get("r")], + [Web3.to_bytes(hexstr=x) for x in request.get("vs")], + ) + else: + receipt = self._mint_knowledge_asset( + paranet_ka_contract, + paranet_token_id, + list(request.values()), + ) + + event_data = self.manager.blockchain_provider.decode_logs_event( + receipt=receipt, + contract_name="KnowledgeCollectionStorage", + event_name="KnowledgeCollectionCreated", + ) + collection_id = ( + int(getattr(event_data[0].get("args", {}), "id", None)) + if event_data + else None + ) + + return KnowledgeCollectionResult( + knowledge_collection_id=collection_id, receipt=receipt + ) + + except Exception as e: + if allowance_increased: + self.decrease_knowledge_collection_allowance(allowance_gap) + raise e + + # TODO: change self._owner to v8 compatible function + def get_owner(self, ual: UAL) -> Address: + token_id = parse_ual(ual)["token_id"] + + return self._owner(token_id) + + def get_asset_storage_address(self, asset_storage_name: str) -> Address: + return self._get_asset_storage_address(asset_storage_name) + + def key_is_operational_wallet( + self, identity_id: int, key: Address, purpose: int + ) -> bool: + return self._key_is_operational_wallet(identity_id, key, purpose) + + def time_until_next_epoch(self) -> int: + return self._time_until_next_epoch() + + def epoch_length(self) -> int: + return self._epoch_length() + + def get_stake_weighted_average_ask(self) -> int: + return self._get_stake_weighted_average_ask() + + def get_block(self, block_identifier: str | int): + return self._get_block(block_identifier) From 6575ba1c61893dfc5036069c52934985e7784599 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 14:55:00 +0100 Subject: [PATCH 082/146] fixes --- dkg/modules/asset/asset.py | 44 ++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/dkg/modules/asset/asset.py b/dkg/modules/asset/asset.py index 34c577b..62b9270 100644 --- a/dkg/modules/asset/asset.py +++ b/dkg/modules/asset/asset.py @@ -408,27 +408,29 @@ def create( knowledge_collection_id = None mint_knowledge_asset_receipt = None - knowledge_collection_result = self.create_knowledge_collection( - { - "publishOperationId": publish_operation_id, - "merkleRoot": dataset_root, - "knowledgeAssetsAmount": kc_tools.count_distinct_subjects( - dataset.get("public") - ), - "byteSize": dataset_size, - "epochs": epochs_num, - "tokenAmount": estimated_publishing_cost, - "isImmutable": immutable, - "paymaster": payer, - "publisherNodeIdentityId": publisher_node_identity_id, - "publisherNodeR": publisher_node_r, - "publisherNodeVS": publisher_node_vs, - "identityIds": identity_ids, - "r": r, - "vs": vs, - }, - None, - None, + knowledge_collection_result = ( + self.blockchain_service.create_knowledge_collection( + { + "publishOperationId": publish_operation_id, + "merkleRoot": dataset_root, + "knowledgeAssetsAmount": kc_tools.count_distinct_subjects( + dataset.get("public") + ), + "byteSize": dataset_size, + "epochs": epochs_num, + "tokenAmount": estimated_publishing_cost, + "isImmutable": immutable, + "paymaster": payer, + "publisherNodeIdentityId": publisher_node_identity_id, + "publisherNodeR": publisher_node_r, + "publisherNodeVS": publisher_node_vs, + "identityIds": identity_ids, + "r": r, + "vs": vs, + }, + None, + None, + ) ) knowledge_collection_id = knowledge_collection_result.knowledge_collection_id mint_knowledge_asset_receipt = knowledge_collection_result.receipt From 30c970be2c19210f26d84207b20bfbf43fd9019c Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Fri, 17 Jan 2025 15:12:33 +0100 Subject: [PATCH 083/146] Code review --- dkg/asset.py | 5 ++- dkg/constants.py | 11 ++++-- dkg/graph.py | 36 ++++--------------- dkg/services/input_service.py | 2 +- dkg/services/node_service.py | 68 +++++++++++++++++++++++++++++------ dkg/utils/node_request.py | 2 +- 6 files changed, 77 insertions(+), 47 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index c3642a9..3d56bff 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -147,7 +147,6 @@ def is_valid_ual(self, ual: UAL) -> bool: BlockchainRequest.get_stake_weighted_average_ask ) _get_bid_suggestion = Method(NodeRequest.bid_suggestion) - _publish = Method(NodeRequest.publish) _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) @@ -472,7 +471,7 @@ def create( "KnowledgeCollectionStorage" ) - publish_operation_id = self._publish( + publish_operation_id = self.node_service.publish( dataset_root, dataset, blockchain_id, @@ -709,7 +708,7 @@ def get(self, ual: UAL, options: dict = {}) -> dict: subject_ual = arguments.get("subject_ual") ual_with_state = f"{ual}:{state}" if state else ual - get_public_operation_id: NodeResponseDict = self._get( + get_public_operation_id: NodeResponseDict = self.node_service.get( ual_with_state, content_type, include_metadata, diff --git a/dkg/constants.py b/dkg/constants.py index b3d7a07..c74534d 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -1,4 +1,5 @@ -from enum import Enum +from enum import Enum, auto +from dkg.types import AutoStrEnumUpperCase # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -41,7 +42,7 @@ class DefaultParameters(Enum): FREQUENCY: int = 5 MAX_NUMBER_OF_RETRIES: int = 5 HASH_FUNCTION_ID: int = 1 - MIN_NUMBER_OF_FINALIZATION_CONF: int = 3 + MIN_NUMBER_OF_FINALIZATION_CONFIRMATION: int = 3 IMMUTABLE: bool = False VALIDATE: bool = True OUTPUT_FORMAT: str = "JSON-LD" @@ -166,3 +167,9 @@ class Operations(Enum): QUERY = "query" PUBLISH_PARANET = "publishParanet" FINALITY = "finality" + + +class Status(AutoStrEnumUpperCase): + ERROR = auto() + NOT_FINALIZED = auto() + FINALIZED = auto() diff --git a/dkg/graph.py b/dkg/graph.py index 55ebd19..089a18a 100644 --- a/dkg/graph.py +++ b/dkg/graph.py @@ -19,15 +19,11 @@ from dkg.manager import DefaultRequestManager -from dkg.method import Method from dkg.module import Module from dkg.types import NQuads -from dkg.utils.node_request import ( - NodeRequest, -) from dkg.services.node_service import NodeService from dkg.services.input_service import InputService -from dkg.constants import Operations +from dkg.constants import Operations, Status class Graph(Module): @@ -41,8 +37,6 @@ def __init__( self.input_service = input_service self.node_service = node_service - _query = Method(NodeRequest.query) - def query( self, query: str, @@ -58,7 +52,7 @@ def query( parsed_query = parseQuery(query) query_type = parsed_query[1].name.replace("Query", "").upper() - result = self._query(query, query_type, repository, paranet_ual) + result = self.node_service.query(query, query_type, repository, paranet_ual) operation_id = result.get("operationId") operation_result = self.node_service.get_operation_result( operation_id, Operations.QUERY.value, max_number_of_retries, frequency @@ -84,35 +78,17 @@ def publish_finality(self, UAL, options=None): frequency, ) except Exception as e: - return {"status": "ERROR", "error": str(e)} - - if finality_status_result == 0: - try: - finality_operation_id = self.node_service.finality( - UAL, - minimum_number_of_finalization_confirmations, - max_number_of_retries, - frequency, - ) - except Exception as e: - return {"status": "ERROR", "error": str(e)} - - try: - return self.node_service.get_operation_result( - finality_operation_id, "finality", max_number_of_retries, frequency - ) - except Exception as e: - return {"status": "NOT FINALIZED", "error": str(e)} + return {"status": Status.ERROR.value, "error": str(e)} - elif finality_status_result >= minimum_number_of_finalization_confirmations: + if finality_status_result >= minimum_number_of_finalization_confirmations: return { - "status": "FINALIZED", + "status": Status.FINALIZED.value, "numberOfConfirmations": finality_status_result, "requiredConfirmations": minimum_number_of_finalization_confirmations, } else: return { - "status": "NOT FINALIZED", + "status": Status.NOT_FINALIZED.value, "numberOfConfirmations": finality_status_result, "requiredConfirmations": minimum_number_of_finalization_confirmations, } diff --git a/dkg/services/input_service.py b/dkg/services/input_service.py index 1f1184a..e8147ed 100644 --- a/dkg/services/input_service.py +++ b/dkg/services/input_service.py @@ -149,7 +149,7 @@ def get_minimum_number_of_finalization_confirmations(self, options): return ( options.get("minimum_number_of_finalization_confirmations") or self.config.get("minimum_number_of_finalization_confirmations") - or DefaultParameters.MIN_NUMBER_OF_FINALIZATION_CONF.value + or DefaultParameters.MIN_NUMBER_OF_FINALIZATION_CONFIRMATION.value or None ) diff --git a/dkg/services/node_service.py b/dkg/services/node_service.py index c9f0eb7..39605f6 100644 --- a/dkg/services/node_service.py +++ b/dkg/services/node_service.py @@ -18,7 +18,10 @@ def __init__(self, manager: DefaultRequestManager): _get_operation_result = Method(NodeRequest.get_operation_result) _finality_status = Method(NodeRequest.finality_status) - _finality = Method(NodeRequest.finality) + _ask = Method(NodeRequest.ask) + _publish = Method(NodeRequest.publish) + _get = Method(NodeRequest.get) + _query = Method(NodeRequest.query) def get_operation_result( self, operation_id: str, operation: str, max_retries: int, frequency: int @@ -79,11 +82,11 @@ def finality_status( return finality - def finality(self, ual, required_confirmations, max_number_of_retries, frequency): - finality_id = 0 + def ask(self, ual, required_confirmations, max_number_of_retries, frequency): + ask = 0 retries = 0 - while finality_id < required_confirmations and retries < max_number_of_retries: + while ask < required_confirmations and retries < max_number_of_retries: if retries > max_number_of_retries: raise Exception( f"Unable to achieve required confirmations. " @@ -97,7 +100,7 @@ def finality(self, ual, required_confirmations, max_number_of_retries, frequency try: try: - response = self._finality( + response = self._ask( ual=ual, minimumNumberOfNodeReplications=required_confirmations ) except Exception as e: @@ -105,12 +108,57 @@ def finality(self, ual, required_confirmations, max_number_of_retries, frequency print(f"failed: {e}") if response is not None: - operation_id = response.json().get("operationId", 0) - if operation_id >= required_confirmations: - finality_id = operation_id + number_of_confirmations = response.json().get( + "numberOfConfirmations", 0 + ) + if number_of_confirmations >= required_confirmations: + ask = number_of_confirmations except Exception as e: - finality_id = 0 + ask = 0 print(f"Retry {retries + 1}/{max_number_of_retries} failed: {e}") - return finality_id + return ask + + def publish( + self, + dataset_root, + dataset, + blockchain_id, + hash_function_id, + minimum_number_of_node_replications, + ): + return self._publish( + dataset_root, + dataset, + blockchain_id, + hash_function_id, + minimum_number_of_node_replications, + ) + + def get( + self, + ual_with_state, + content_type, + include_metadata, + hash_function_id, + paranet_ual, + subject_ual, + ): + return self._get( + ual_with_state, + content_type, + include_metadata, + hash_function_id, + paranet_ual, + subject_ual, + ) + + def query( + self, + query, + query_type, + repository, + paranet_ual, + ): + return self._query(query, query_type, repository, paranet_ual) diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index abb8e7d..d9f8ecd 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -64,7 +64,7 @@ class NodeRequest: }, ) - finality = NodeCall( + ask = NodeCall( method=HTTPRequestMethod.POST, path="ask", params={ From 00c7062585bf7514868b982c2604b2566f94f0f8 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 15:16:01 +0100 Subject: [PATCH 084/146] Finality fix, graph create/get bind --- dkg/clients/async_dkg.py | 16 ++++++++++++--- dkg/modules/graph/graph.py | 20 +------------------ .../node_services/async_node_service.py | 6 +++--- dkg/services/node_services/node_service.py | 6 +++--- dkg/utils/node_request.py | 2 +- 5 files changed, 21 insertions(+), 29 deletions(-) diff --git a/dkg/clients/async_dkg.py b/dkg/clients/async_dkg.py index e235238..3ff7b00 100644 --- a/dkg/clients/async_dkg.py +++ b/dkg/clients/async_dkg.py @@ -61,9 +61,19 @@ def __init__( } self._attach_modules(modules) - # Backwards compatibility - self.graph.get = self.asset.get.__get__(self.asset) - self.graph.create = self.asset.create.__get__(self.asset) + self._setup_backwards_compatibility() + + def _setup_backwards_compatibility(self): + # Create async wrapper methods + async def graph_get(*args, **kwargs): + return await self.asset.get(*args, **kwargs) + + async def graph_create(*args, **kwargs): + return await self.asset.create(*args, **kwargs) + + # Attach methods to graph + self.graph.get = graph_get + self.graph.create = graph_create def initialize_services(self, config: dict = {}): self.input_service = InputService(self.manager, config) diff --git a/dkg/modules/graph/graph.py b/dkg/modules/graph/graph.py index 16c6b54..04234f1 100644 --- a/dkg/modules/graph/graph.py +++ b/dkg/modules/graph/graph.py @@ -86,25 +86,7 @@ def publish_finality(self, UAL, options=None): except Exception as e: return {"status": Status.ERROR.value, "error": str(e)} - if finality_status_result == 0: - try: - finality_operation_id = self.node_service.finality( - UAL, - minimum_number_of_finalization_confirmations, - max_number_of_retries, - frequency, - ) - except Exception as e: - return {"status": Status.ERROR.value, "error": str(e)} - - try: - return self.node_service.get_operation_result( - finality_operation_id, "finality", max_number_of_retries, frequency - ) - except Exception as e: - return {"status": Status.NOT_FINALIZED.value, "error": str(e)} - - elif finality_status_result >= minimum_number_of_finalization_confirmations: + if finality_status_result >= minimum_number_of_finalization_confirmations: return { "status": Status.FINALIZED.value, "numberOfConfirmations": finality_status_result, diff --git a/dkg/services/node_services/async_node_service.py b/dkg/services/node_services/async_node_service.py index 841f9e3..1641988 100644 --- a/dkg/services/node_services/async_node_service.py +++ b/dkg/services/node_services/async_node_service.py @@ -16,7 +16,7 @@ def __init__(self, manager: AsyncRequestManager): _info = Method(NodeRequest.info) _get_operation_result = Method(NodeRequest.get_operation_result) _finality_status = Method(NodeRequest.finality_status) - _finality = Method(NodeRequest.finality) + _ask = Method(NodeRequest.ask) _get_bid_suggestion = Method(NodeRequest.bid_suggestion) _publish = Method(NodeRequest.publish) _get = Method(NodeRequest.get) @@ -98,7 +98,7 @@ async def finality_status( return finality - async def finality( + async def ask( self, ual: UAL, required_confirmations: int, @@ -122,7 +122,7 @@ async def finality( try: try: - response = await self._finality( + response = await self._ask( ual=ual, minimumNumberOfNodeReplications=required_confirmations ) except Exception as e: diff --git a/dkg/services/node_services/node_service.py b/dkg/services/node_services/node_service.py index 0006ef9..999a74f 100644 --- a/dkg/services/node_services/node_service.py +++ b/dkg/services/node_services/node_service.py @@ -18,7 +18,7 @@ def __init__(self, manager: DefaultRequestManager): _get_operation_result = Method(NodeRequest.get_operation_result) _finality_status = Method(NodeRequest.finality_status) - _finality = Method(NodeRequest.finality) + _ask = Method(NodeRequest.ask) _publish = Method(NodeRequest.publish) _get = Method(NodeRequest.get) _query = Method(NodeRequest.query) @@ -82,7 +82,7 @@ def finality_status( return finality - def finality(self, ual, required_confirmations, max_number_of_retries, frequency): + def ask(self, ual, required_confirmations, max_number_of_retries, frequency): finality_id = 0 retries = 0 @@ -100,7 +100,7 @@ def finality(self, ual, required_confirmations, max_number_of_retries, frequency try: try: - response = self._finality( + response = self._ask( ual=ual, minimumNumberOfNodeReplications=required_confirmations ) except Exception as e: diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 9ab2447..28f7972 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -64,7 +64,7 @@ class NodeRequest: }, ) - finality = NodeCall( + ask = NodeCall( method=HTTPRequestMethod.POST, path="ask", params={ From 1144dd8e43bb1319b97668e3d49df3ba3bf055fb Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 15:26:39 +0100 Subject: [PATCH 085/146] Rename ask to confirmations_count --- dkg/services/node_services/node_service.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dkg/services/node_services/node_service.py b/dkg/services/node_services/node_service.py index 11427ae..e447055 100644 --- a/dkg/services/node_services/node_service.py +++ b/dkg/services/node_services/node_service.py @@ -83,10 +83,13 @@ def finality_status( return finality def ask(self, ual, required_confirmations, max_number_of_retries, frequency): - ask = 0 + confirmations_count = 0 retries = 0 - while ask < required_confirmations and retries < max_number_of_retries: + while ( + confirmations_count < required_confirmations + and retries < max_number_of_retries + ): if retries > max_number_of_retries: raise Exception( f"Unable to achieve required confirmations. " @@ -112,13 +115,13 @@ def ask(self, ual, required_confirmations, max_number_of_retries, frequency): "numberOfConfirmations", 0 ) if number_of_confirmations >= required_confirmations: - ask = number_of_confirmations + confirmations_count = number_of_confirmations except Exception as e: - ask = 0 + confirmations_count = 0 print(f"Retry {retries + 1}/{max_number_of_retries} failed: {e}") - return ask + return confirmations_count def publish( self, From 03fb0b0cd741411f0afbe639719d4daba66d4533 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 16:44:21 +0100 Subject: [PATCH 086/146] version bump --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 791af38..dd37076 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ [tool.poetry] name = "dkg" -version = "8.0.0a4" +version = "8.0.0" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" -authors = ["Uladzislau Hubar "] +authors = ["Zvonimir Sculac "] license = "Apache-2.0" readme = "README.md" From a77e7bb167d0b7b63824511d7e47f4c9937d3f8c Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 16:54:13 +0100 Subject: [PATCH 087/146] Ressurect sigma boy --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index dd37076..860d79b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "dkg" version = "8.0.0" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" -authors = ["Zvonimir Sculac "] +authors = ["Uladzislau Hubar "] license = "Apache-2.0" readme = "README.md" From fc64d720064416e8dd7c4f39bb4b6d12e2cf707b Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 17 Jan 2025 16:55:30 +0100 Subject: [PATCH 088/146] Add author --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 860d79b..d473a92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "dkg" version = "8.0.0" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" -authors = ["Uladzislau Hubar "] +authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" readme = "README.md" From 6532101ead46e79510075a63bebb3eacbe775fe9 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 20 Jan 2025 09:10:55 +0100 Subject: [PATCH 089/146] version bumo --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d473a92..26cd14a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.0" +version = "8.0.1" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From 01094f8b8496a856e6eb9136a473cfe6388b9b63 Mon Sep 17 00:00:00 2001 From: BogBogdan Date: Tue, 21 Jan 2025 16:39:39 +0100 Subject: [PATCH 090/146] paranet demo update --- examples/paranets_demo.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/examples/paranets_demo.py b/examples/paranets_demo.py index c089176..32310a8 100644 --- a/examples/paranets_demo.py +++ b/examples/paranets_demo.py @@ -103,10 +103,18 @@ def convert_hexbytes(data): print_json(create_paranet_service_knowledge_asset_result) divider() - paranet_service_ual = create_paranet_service_knowledge_asset_result["UAL"] + + +submitTOParanet = dkg.asset.submit_to_paranet(paranet_service_ual, paranet_ual) + +print("======================== SUBMITED TO PARANET") +print_json(submitTOParanet) + +divider() + create_paranet_service_result = dkg.paranet.create_service( - paranet_service_ual, + submitTOParanet["UAL"], "TestParanetService", "TestParanetServiceDescription", ["0x03C094044301E082468876634F0b209E11d98452"], @@ -231,6 +239,13 @@ def print_reward_stats(is_voter: bool = False): divider() +submitTOParanet2 = dkg.asset.submit_to_paranet(create_submit_ka1_result["UAL"], paranet_ual) + +print("======================== SUBMITED TO PARANET") +print_json(submitTOParanet2) + +divider() + ka2 = { "public": { "@context": ["http://schema.org"], From ff60003db9059b0fd4ef244319d7d108b34a0b95 Mon Sep 17 00:00:00 2001 From: BogBogdan Date: Wed, 22 Jan 2025 10:01:10 +0100 Subject: [PATCH 091/146] Names of functions changed in blockchain_request --- dkg/utils/blockchain_request.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index f9e6d0c..ca26e96 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -305,7 +305,7 @@ class BlockchainRequest: ) submit_knowledge_asset = ContractTransaction( contract="Paranet", - function="submitKnowledgeAsset", + function="submitKnowledgeCollection", args={ "paranetKAStorageContract": Address, "paranetKATokenId": int, @@ -336,7 +336,7 @@ class BlockchainRequest: get_updating_knowledge_asset_states = ContractCall( contract="ParanetKnowledgeMinersRegistry", - function="getUpdatingKnowledgeAssetStates", + function="getUpdatingKnowledgeCollectionStates", args={ "miner": Address, "paranetId": HexStr, @@ -414,7 +414,7 @@ class BlockchainRequest: mint_knowledge_asset = ContractTransaction( contract="Paranet", - function="mintKnowledgeAsset", + function="mintKnowledgeCollection", args={ "paranetKAStorageContract": Address, "paranetKATokenId": int, From f6a357c24beadc1258b173c41441a472dec33f53 Mon Sep 17 00:00:00 2001 From: BogBogdan Date: Wed, 22 Jan 2025 10:47:04 +0100 Subject: [PATCH 092/146] Changed names 2 --- dkg/modules/asset/asset.py | 6 ++-- dkg/modules/asset/async_asset.py | 6 ++-- dkg/modules/paranet/paranet.py | 4 +-- .../async_blockchain_service.py | 4 +-- .../blockchain_services/blockchain_service.py | 4 +-- dkg/utils/blockchain_request.py | 6 ++-- examples/paranets_demo.py | 32 ++++++++++--------- 7 files changed, 32 insertions(+), 30 deletions(-) diff --git a/dkg/modules/asset/asset.py b/dkg/modules/asset/asset.py index 6dd8d9a..87fb900 100644 --- a/dkg/modules/asset/asset.py +++ b/dkg/modules/asset/asset.py @@ -406,7 +406,7 @@ def create( ) knowledge_collection_id = None - mint_knowledge_asset_receipt = None + mint_knowledge_collection_receipt = None knowledge_collection_result = ( self.blockchain_service.create_knowledge_collection( @@ -433,7 +433,7 @@ def create( ) ) knowledge_collection_id = knowledge_collection_result.knowledge_collection_id - mint_knowledge_asset_receipt = knowledge_collection_result.receipt + mint_knowledge_collection_receipt = knowledge_collection_result.receipt ual = format_ual( blockchain_id, content_asset_storage_address, knowledge_collection_id @@ -457,7 +457,7 @@ def create( "signatures" ), "operation": { - "mintKnowledgeAsset": mint_knowledge_asset_receipt, + "mintKnowledgeAsset": mint_knowledge_collection_receipt, "publish": get_operation_status_object( publish_operation_result, publish_operation_id ), diff --git a/dkg/modules/asset/async_asset.py b/dkg/modules/asset/async_asset.py index f8dc929..4ae8d0c 100644 --- a/dkg/modules/asset/async_asset.py +++ b/dkg/modules/asset/async_asset.py @@ -420,7 +420,7 @@ async def create( ) knowledge_collection_id = None - mint_knowledge_asset_receipt = None + mint_knowledge_collection_receipt = None knowledge_collection_result = ( await self.blockchain_service.create_knowledge_collection( @@ -447,7 +447,7 @@ async def create( ) ) knowledge_collection_id = knowledge_collection_result.knowledge_collection_id - mint_knowledge_asset_receipt = knowledge_collection_result.receipt + mint_knowledge_collection_receipt = knowledge_collection_result.receipt ual = format_ual( blockchain_id, content_asset_storage_address, knowledge_collection_id @@ -471,7 +471,7 @@ async def create( "signatures" ), "operation": { - "mintKnowledgeAsset": mint_knowledge_asset_receipt, + "mintKnowledgeAsset": mint_knowledge_collection_receipt, "publish": get_operation_status_object( publish_operation_result, publish_operation_id ), diff --git a/dkg/modules/paranet/paranet.py b/dkg/modules/paranet/paranet.py index ea6e6da..275fd4c 100644 --- a/dkg/modules/paranet/paranet.py +++ b/dkg/modules/paranet/paranet.py @@ -755,8 +755,8 @@ def claim_voter_reward( "operation": json.loads(Web3.to_json(receipt)), } - _get_updating_knowledge_asset_states = Method( - BlockchainRequest.get_updating_knowledge_asset_states + _get_updating_knowledge_collection_states = Method( + BlockchainRequest.get_updating_knowledge_collection_states ) def _get_incentives_pool_contract( diff --git a/dkg/services/blockchain_services/async_blockchain_service.py b/dkg/services/blockchain_services/async_blockchain_service.py index 9fca708..649990e 100644 --- a/dkg/services/blockchain_services/async_blockchain_service.py +++ b/dkg/services/blockchain_services/async_blockchain_service.py @@ -20,7 +20,7 @@ def __init__(self, manager: AsyncRequestManager): _increase_allowance = Method(BlockchainRequest.increase_allowance) _decrease_allowance = Method(BlockchainRequest.decrease_allowance) _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) - _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + _mint_knowledge_collection = Method(BlockchainRequest.mint_knowledge_collection) _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) @@ -127,7 +127,7 @@ async def create_knowledge_collection( [Web3.to_bytes(hexstr=x) for x in request.get("vs")], ) else: - receipt = await self._mint_knowledge_asset( + receipt = await self._mint_knowledge_collection( paranet_ka_contract, paranet_token_id, list(request.values()), diff --git a/dkg/services/blockchain_services/blockchain_service.py b/dkg/services/blockchain_services/blockchain_service.py index b39ab66..eddea4d 100644 --- a/dkg/services/blockchain_services/blockchain_service.py +++ b/dkg/services/blockchain_services/blockchain_service.py @@ -20,7 +20,7 @@ def __init__(self, manager: DefaultRequestManager): _increase_allowance = Method(BlockchainRequest.increase_allowance) _decrease_allowance = Method(BlockchainRequest.decrease_allowance) _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) - _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + _mint_knowledge_collection = Method(BlockchainRequest.mint_knowledge_collection) _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) @@ -121,7 +121,7 @@ def create_knowledge_collection( [Web3.to_bytes(hexstr=x) for x in request.get("vs")], ) else: - receipt = self._mint_knowledge_asset( + receipt = self._mint_knowledge_collection( paranet_ka_contract, paranet_token_id, list(request.values()), diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index ca26e96..a5b3887 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -303,7 +303,7 @@ class BlockchainRequest: "paranetServiceAddresses": list[Address], }, ) - submit_knowledge_asset = ContractTransaction( + submit_knowledge_collection = ContractTransaction( contract="Paranet", function="submitKnowledgeCollection", args={ @@ -334,7 +334,7 @@ class BlockchainRequest: }, ) - get_updating_knowledge_asset_states = ContractCall( + get_updating_knowledge_collection_states = ContractCall( contract="ParanetKnowledgeMinersRegistry", function="getUpdatingKnowledgeCollectionStates", args={ @@ -412,7 +412,7 @@ class BlockchainRequest: }, ) - mint_knowledge_asset = ContractTransaction( + mint_knowledge_collection = ContractTransaction( contract="Paranet", function="mintKnowledgeCollection", args={ diff --git a/examples/paranets_demo.py b/examples/paranets_demo.py index 32310a8..88bf0b5 100644 --- a/examples/paranets_demo.py +++ b/examples/paranets_demo.py @@ -22,13 +22,15 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider from dkg.dataclasses import ParanetNodesAccessPolicy, ParanetMinersAccessPolicy +from dkg.constants import Environments, BlockchainIds +from dkg.providers import BlockchainProvider node_provider = NodeHTTPProvider("http://localhost:8900") + blockchain_provider = BlockchainProvider( - "development", - "hardhat2:31337", - private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", -) + Environments.DEVELOPMENT.value, + BlockchainIds.HARDHAT_1.value, + ) dkg = DKG(node_provider, blockchain_provider) @@ -65,14 +67,14 @@ def convert_hexbytes(data): } } -create_paranet_knowledge_asset_result = dkg.asset.create(paranet_data, 1) +create_paranet_knowledge_collection_result = dkg.asset.create(paranet_data, 1) print("======================== PARANET KNOWLEDGE ASSET CREATED") -print_json(create_paranet_knowledge_asset_result) +print_json(create_paranet_knowledge_collection_result) divider() -paranet_ual = create_paranet_knowledge_asset_result["UAL"] +paranet_ual = create_paranet_knowledge_collection_result["UAL"] create_paranet_result = dkg.paranet.create( paranet_ual, "TestParanet", @@ -95,26 +97,26 @@ def convert_hexbytes(data): } } -create_paranet_service_knowledge_asset_result = dkg.asset.create( +create_paranet_service_knowledge_collection_result = dkg.asset.create( paranet_service_data, 1 ) print("======================== PARANET SERVICE KNOWLEDGE ASSET CREATED") -print_json(create_paranet_service_knowledge_asset_result) +print_json(create_paranet_service_knowledge_collection_result) divider() -paranet_service_ual = create_paranet_service_knowledge_asset_result["UAL"] +paranet_service_ual = create_paranet_service_knowledge_collection_result["UAL"] -submitTOParanet = dkg.asset.submit_to_paranet(paranet_service_ual, paranet_ual) +submit_to_paranet = dkg.asset.submit_to_paranet(paranet_service_ual, paranet_ual) print("======================== SUBMITED TO PARANET") -print_json(submitTOParanet) +print_json(submit_to_paranet) divider() create_paranet_service_result = dkg.paranet.create_service( - submitTOParanet["UAL"], + submit_to_paranet["UAL"], "TestParanetService", "TestParanetServiceDescription", ["0x03C094044301E082468876634F0b209E11d98452"], @@ -239,10 +241,10 @@ def print_reward_stats(is_voter: bool = False): divider() -submitTOParanet2 = dkg.asset.submit_to_paranet(create_submit_ka1_result["UAL"], paranet_ual) +submit_to_paranet_result2 = dkg.asset.submit_to_paranet(create_submit_ka1_result["UAL"], paranet_ual) print("======================== SUBMITED TO PARANET") -print_json(submitTOParanet2) +print_json(submit_to_paranet_result2) divider() From 4e7b1be9f228aaf7b4e3960e34dea65d2e4806bb Mon Sep 17 00:00:00 2001 From: BogBogdan Date: Wed, 22 Jan 2025 11:58:31 +0100 Subject: [PATCH 093/146] fix KA --- dkg/utils/blockchain_request.py | 12 ++++++------ examples/paranets_demo.py | 31 +++++++++++++++---------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index a5b3887..9b90641 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -307,10 +307,10 @@ class BlockchainRequest: contract="Paranet", function="submitKnowledgeCollection", args={ - "paranetKAStorageContract": Address, - "paranetKATokenId": int, - "knowledgeAssetStorageContract": Address, - "knowledgeAssetTokenId": int, + "paranetKCStorageContract": Address, + "paranetKnowledgeCollectionId": int, + "knowledgeCollectionStorageContract": Address, + "knowledgeCollectionTokenId": int, }, ) @@ -416,8 +416,8 @@ class BlockchainRequest: contract="Paranet", function="mintKnowledgeCollection", args={ - "paranetKAStorageContract": Address, - "paranetKATokenId": int, + "paranetKCStorageContract": Address, + "paranetKCTokenId": int, "knowledgeAssetArgs": dict, }, ) diff --git a/examples/paranets_demo.py b/examples/paranets_demo.py index 88bf0b5..9c42404 100644 --- a/examples/paranets_demo.py +++ b/examples/paranets_demo.py @@ -23,7 +23,6 @@ from dkg.providers import BlockchainProvider, NodeHTTPProvider from dkg.dataclasses import ParanetNodesAccessPolicy, ParanetMinersAccessPolicy from dkg.constants import Environments, BlockchainIds -from dkg.providers import BlockchainProvider node_provider = NodeHTTPProvider("http://localhost:8900") @@ -69,7 +68,7 @@ def convert_hexbytes(data): create_paranet_knowledge_collection_result = dkg.asset.create(paranet_data, 1) -print("======================== PARANET KNOWLEDGE ASSET CREATED") +print("======================== PARANET KNOWLEDGE COLLECTION CREATED") print_json(create_paranet_knowledge_collection_result) divider() @@ -101,7 +100,7 @@ def convert_hexbytes(data): paranet_service_data, 1 ) -print("======================== PARANET SERVICE KNOWLEDGE ASSET CREATED") +print("======================== PARANET SERVICE KNOWLEDGE COLLECTION CREATED") print_json(create_paranet_service_knowledge_collection_result) divider() @@ -116,7 +115,7 @@ def convert_hexbytes(data): divider() create_paranet_service_result = dkg.paranet.create_service( - submit_to_paranet["UAL"], + paranet_service_ual, "TestParanetService", "TestParanetServiceDescription", ["0x03C094044301E082468876634F0b209E11d98452"], @@ -217,7 +216,7 @@ def print_reward_stats(is_voter: bool = False): divider() -ka1 = { +kc1 = { "public": { "@context": ["http://schema.org"], "@id": "uuid:3", @@ -227,8 +226,8 @@ def print_reward_stats(is_voter: bool = False): } } -create_submit_ka1_result = dkg.asset.create( - ka1, +create_submit_kc1_result = dkg.asset.create( + kc1, 1, 100000000000000000000, paranet_ual=paranet_ual, @@ -237,18 +236,18 @@ def print_reward_stats(is_voter: bool = False): print( "======================== KNOWLEDGE ASSET #1 CREATED AND SUBMITTED TO THE PARANET" ) -print_json(create_submit_ka1_result) +print_json(create_submit_kc1_result) divider() -submit_to_paranet_result2 = dkg.asset.submit_to_paranet(create_submit_ka1_result["UAL"], paranet_ual) +submit_to_paranet_result2 = dkg.asset.submit_to_paranet(create_submit_kc1_result["UAL"], paranet_ual) print("======================== SUBMITED TO PARANET") print_json(submit_to_paranet_result2) divider() -ka2 = { +kc2 = { "public": { "@context": ["http://schema.org"], "@id": "uuid:4", @@ -258,16 +257,16 @@ def print_reward_stats(is_voter: bool = False): } } -create_ka2_result = dkg.asset.create(ka2, 1, 20000000000000000000) +create_kc2_result = dkg.asset.create(kc2, 1, 20000000000000000000) print("======================== KNOWLEDGE ASSET #2 CREATED") -print_json(create_ka2_result) +print_json(create_kc2_result) -ka2_ual = create_ka2_result["UAL"] -submit_ka2_result = dkg.asset.submit_to_paranet(ka2_ual, paranet_ual) +kc2_ual = create_kc2_result["UAL"] +submit_kc2_result = dkg.asset.submit_to_paranet(kc2_ual, paranet_ual) print("======================== KNOWLEDGE ASSET #2 SUBMITTED TO THE PARANET") -print_json(submit_ka2_result) +print_json(submit_kc2_result) # divider() @@ -288,7 +287,7 @@ def print_reward_stats(is_voter: bool = False): # }} # """ # query_result = dkg.graph.query( -# federated_query.format(ual=ka2_ual), +# federated_query.format(ual=kc2_ual), # paranet_ual, # ) From 67c9e45dd54b53701784724ebf3386bc830c6e97 Mon Sep 17 00:00:00 2001 From: BogBogdan Date: Wed, 22 Jan 2025 15:03:03 +0100 Subject: [PATCH 094/146] minor fixes --- dkg/modules/asset/asset.py | 2 +- dkg/modules/asset/async_asset.py | 2 +- dkg/modules/paranet/paranet.py | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/dkg/modules/asset/asset.py b/dkg/modules/asset/asset.py index 87fb900..90d5ccd 100644 --- a/dkg/modules/asset/asset.py +++ b/dkg/modules/asset/asset.py @@ -457,7 +457,7 @@ def create( "signatures" ), "operation": { - "mintKnowledgeAsset": mint_knowledge_collection_receipt, + "mintKnowledgeCollection": mint_knowledge_collection_receipt, "publish": get_operation_status_object( publish_operation_result, publish_operation_id ), diff --git a/dkg/modules/asset/async_asset.py b/dkg/modules/asset/async_asset.py index 4ae8d0c..939b539 100644 --- a/dkg/modules/asset/async_asset.py +++ b/dkg/modules/asset/async_asset.py @@ -471,7 +471,7 @@ async def create( "signatures" ), "operation": { - "mintKnowledgeAsset": mint_knowledge_collection_receipt, + "mintKnowledgeCollection": mint_knowledge_collection_receipt, "publish": get_operation_status_object( publish_operation_result, publish_operation_id ), diff --git a/dkg/modules/paranet/paranet.py b/dkg/modules/paranet/paranet.py index 275fd4c..b3b4507 100644 --- a/dkg/modules/paranet/paranet.py +++ b/dkg/modules/paranet/paranet.py @@ -755,9 +755,7 @@ def claim_voter_reward( "operation": json.loads(Web3.to_json(receipt)), } - _get_updating_knowledge_collection_states = Method( - BlockchainRequest.get_updating_knowledge_collection_states - ) + def _get_incentives_pool_contract( self, From 4aa22e02571e92425de57c7d8a0caac1c863a578 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 7 Feb 2025 10:13:05 +0100 Subject: [PATCH 095/146] Add new query endpoint --- dkg/modules/graph/graph.py | 11 ++--------- dkg/services/input_service.py | 2 -- dkg/utils/node_request.py | 4 ++-- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/dkg/modules/graph/graph.py b/dkg/modules/graph/graph.py index 3aa65cc..9608261 100644 --- a/dkg/modules/graph/graph.py +++ b/dkg/modules/graph/graph.py @@ -23,7 +23,7 @@ from dkg.types import NQuads from dkg.services.node_services.node_service import NodeService from dkg.services.input_service import InputService -from dkg.constants import Operations, Status +from dkg.constants import Status class Graph(Module): @@ -43,9 +43,6 @@ def query( options: dict = {}, ) -> NQuads: arguments = self.input_service.get_query_arguments(options) - - max_number_of_retries = arguments.get("max_number_of_retries") - frequency = arguments.get("frequency") paranet_ual = arguments.get("paranet_ual") repository = arguments.get("repository") @@ -53,12 +50,8 @@ def query( query_type = parsed_query[1].name.replace("Query", "").upper() result = self.node_service.query(query, query_type, repository, paranet_ual) - operation_id = result.get("operationId") - operation_result = self.node_service.get_operation_result( - operation_id, Operations.QUERY.value, max_number_of_retries, frequency - ) - return operation_result["data"] + return result.get("data") def publish_finality(self, UAL, options=None): if options is None: diff --git a/dkg/services/input_service.py b/dkg/services/input_service.py index e8147ed..f42baac 100644 --- a/dkg/services/input_service.py +++ b/dkg/services/input_service.py @@ -44,8 +44,6 @@ def get_asset_create_arguments(self, options): def get_query_arguments(self, options): return { - "max_number_of_retries": self.get_max_number_of_retries(options), - "frequency": self.get_frequency(options), "paranet_ual": self.get_paranet_ual(options), "repository": self.get_repository(options), } diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 28f7972..2e2e6db 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -94,12 +94,12 @@ class NodeRequest: query = NodeCall( method=HTTPRequestMethod.POST, - path="query", + path="direct-query", data={ "query": str, "type": str, "repository": str | None, - "paranet_ual": str | None, + "paranetUAL": str | None, }, ) From daf423db684022241fb79df20e9eea8fa4712345 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 7 Feb 2025 10:33:46 +0100 Subject: [PATCH 096/146] Update async query --- dkg/modules/graph/async_graph.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/dkg/modules/graph/async_graph.py b/dkg/modules/graph/async_graph.py index 352a237..8dd071c 100644 --- a/dkg/modules/graph/async_graph.py +++ b/dkg/modules/graph/async_graph.py @@ -21,7 +21,7 @@ from dkg.managers.async_manager import AsyncRequestManager from dkg.modules.async_module import AsyncModule from dkg.types import NQuads -from dkg.constants import Operations, Status +from dkg.constants import Status from dkg.services.input_service import InputService from dkg.services.node_services.async_node_service import AsyncNodeService from dkg.types import UAL @@ -48,8 +48,6 @@ async def query( arguments = self.input_service.get_query_arguments(options) - max_number_of_retries = arguments.get("max_number_of_retries") - frequency = arguments.get("frequency") paranet_ual = arguments.get("paranet_ual") repository = arguments.get("repository") @@ -59,12 +57,8 @@ async def query( result = await self.node_service.query( query, query_type, repository, paranet_ual ) - operation_id = result.get("operationId") - operation_result = await self.node_service.get_operation_result( - operation_id, Operations.QUERY.value, max_number_of_retries, frequency - ) - return operation_result["data"] + return result.get("data") async def publish_finality(self, UAL: UAL, options=None): if options is None: From 4c8a1bcfad16c21a6a01cbe197d751c5e7eb7713 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 20 Mar 2025 10:15:10 +0100 Subject: [PATCH 097/146] bug fixes --- dkg/modules/asset/asset.py | 4 ++-- dkg/modules/asset/async_asset.py | 14 ++++++++------ examples/async_demo.py | 2 +- examples/demo.py | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/dkg/modules/asset/asset.py b/dkg/modules/asset/asset.py index 90d5ccd..a09fb24 100644 --- a/dkg/modules/asset/asset.py +++ b/dkg/modules/asset/asset.py @@ -476,7 +476,7 @@ def create( ) ) - _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) + _submit_knowledge_collection = Method(BlockchainRequest.submit_knowledge_collection) def submit_to_paranet( self, ual: UAL, paranet_ual: UAL @@ -493,7 +493,7 @@ def submit_to_paranet( parsed_paranet_ual["token_id"], ) - receipt: TxReceipt = self._submit_knowledge_asset( + receipt: TxReceipt = self._submit_knowledge_collection( paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id, knowledge_asset_storage, diff --git a/dkg/modules/asset/async_asset.py b/dkg/modules/asset/async_asset.py index 939b539..98a9693 100644 --- a/dkg/modules/asset/async_asset.py +++ b/dkg/modules/asset/async_asset.py @@ -476,10 +476,12 @@ async def create( publish_operation_result, publish_operation_id ), "finality": { - "status": "FINALIZED" - if finality_status_result - >= minimum_number_of_finalization_confirmations - else "NOT FINALIZED" + "status": ( + "FINALIZED" + if finality_status_result + >= minimum_number_of_finalization_confirmations + else "NOT FINALIZED" + ) }, "numberOfConfirmations": finality_status_result, "requiredConfirmations": minimum_number_of_finalization_confirmations, @@ -488,7 +490,7 @@ async def create( ) ) - _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) + _submit_knowledge_collection = Method(BlockchainRequest.submit_knowledge_collection) def submit_to_paranet( self, ual: UAL, paranet_ual: UAL @@ -505,7 +507,7 @@ def submit_to_paranet( parsed_paranet_ual["token_id"], ) - receipt: TxReceipt = self._submit_knowledge_asset( + receipt: TxReceipt = self._submit_knowledge_collection( paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id, knowledge_asset_storage, diff --git a/examples/async_demo.py b/examples/async_demo.py index dffa96f..9f58022 100644 --- a/examples/async_demo.py +++ b/examples/async_demo.py @@ -95,7 +95,7 @@ def print_json(json_dict: dict): start_time = time.perf_counter() query_operation_result = await dkg.graph.query( """ - PREFIX SCHEMA: + PREFIX schema: SELECT ?s ?modelName WHERE { ?s schema:model ?modelName . diff --git a/examples/demo.py b/examples/demo.py index 00060d8..0008327 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -112,7 +112,7 @@ def print_json(json_dict: dict): start_time = time.perf_counter() query_operation_result = dkg.graph.query( """ - PREFIX SCHEMA: + PREFIX schema: SELECT ?s ?modelName WHERE { ?s schema:model ?modelName . From 3e24eb859f222ede9ebe12f4ebb14cbf4252be40 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 20 Mar 2025 10:16:20 +0100 Subject: [PATCH 098/146] formatter --- dkg/modules/paranet/paranet.py | 2 -- examples/paranets_demo.py | 12 +++++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dkg/modules/paranet/paranet.py b/dkg/modules/paranet/paranet.py index b3b4507..a9b3c25 100644 --- a/dkg/modules/paranet/paranet.py +++ b/dkg/modules/paranet/paranet.py @@ -755,8 +755,6 @@ def claim_voter_reward( "operation": json.loads(Web3.to_json(receipt)), } - - def _get_incentives_pool_contract( self, ual: UAL, diff --git a/examples/paranets_demo.py b/examples/paranets_demo.py index 9c42404..de64a7f 100644 --- a/examples/paranets_demo.py +++ b/examples/paranets_demo.py @@ -27,9 +27,9 @@ node_provider = NodeHTTPProvider("http://localhost:8900") blockchain_provider = BlockchainProvider( - Environments.DEVELOPMENT.value, - BlockchainIds.HARDHAT_1.value, - ) + Environments.DEVELOPMENT.value, + BlockchainIds.HARDHAT_1.value, +) dkg = DKG(node_provider, blockchain_provider) @@ -107,7 +107,7 @@ def convert_hexbytes(data): paranet_service_ual = create_paranet_service_knowledge_collection_result["UAL"] -submit_to_paranet = dkg.asset.submit_to_paranet(paranet_service_ual, paranet_ual) +submit_to_paranet = dkg.asset.submit_to_paranet(paranet_service_ual, paranet_ual) print("======================== SUBMITED TO PARANET") print_json(submit_to_paranet) @@ -240,7 +240,9 @@ def print_reward_stats(is_voter: bool = False): divider() -submit_to_paranet_result2 = dkg.asset.submit_to_paranet(create_submit_kc1_result["UAL"], paranet_ual) +submit_to_paranet_result2 = dkg.asset.submit_to_paranet( + create_submit_kc1_result["UAL"], paranet_ual +) print("======================== SUBMITED TO PARANET") print_json(submit_to_paranet_result2) From 18a91cf6c05379a94f1a9e5b9b94c37aa5a132fa Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 20 Mar 2025 10:16:55 +0100 Subject: [PATCH 099/146] version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 26cd14a..8146f9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.1" +version = "8.0.2" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From 534a78a011ae5c115dc607467c274e11962caa40 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 20 Mar 2025 11:19:13 +0100 Subject: [PATCH 100/146] Fix publish fail due to token amount being too low --- examples/async_demo.py | 1 - examples/demo.py | 1 - 2 files changed, 2 deletions(-) diff --git a/examples/async_demo.py b/examples/async_demo.py index 9f58022..cd85f3d 100644 --- a/examples/async_demo.py +++ b/examples/async_demo.py @@ -72,7 +72,6 @@ def print_json(json_dict: dict): "epochs_num": 2, "minimum_number_of_finalization_confirmations": 3, "minimum_number_of_node_replications": 1, - "token_amount": 100, }, ) print( diff --git a/examples/demo.py b/examples/demo.py index 0008327..79bfba4 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -90,7 +90,6 @@ def print_json(json_dict: dict): "epochs_num": 2, "minimum_number_of_finalization_confirmations": 3, "minimum_number_of_node_replications": 1, - "token_amount": 100, }, ) print( From ed48fa75abb70a345647459f7b4dc56f752346f4 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 9 Apr 2025 14:37:40 +0200 Subject: [PATCH 101/146] Add new nw testnet hub and bump version --- dkg/constants.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dkg/constants.py b/dkg/constants.py index 67e9474..2193660 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -118,7 +118,7 @@ class OperationStatuses(str, Enum): "rpc": "https://rpc.chiadochain.net", }, "otp:20430": { - "hub": "0xd7d073b560412c6A7F33dD670d323D01061E5DEb", + "hub": "0xE233B5b78853A62B1E11eBe88bF083e25b0a57a6", "rpc": "https://lofar-testnet.origin-trail.network", }, }, diff --git a/pyproject.toml b/pyproject.toml index 8146f9e..870c5fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.2" +version = "8.0.3" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From 643d00629892929d7c70c1442f41c15b615edc9c Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 29 Apr 2025 12:12:03 +0200 Subject: [PATCH 102/146] fixed \b \n \f \r \t escape characters --- dkg/modules/asset/asset.py | 1 + dkg/modules/asset/async_asset.py | 1 + dkg/utils/knowledge_collection_tools.py | 26 +++++++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/dkg/modules/asset/asset.py b/dkg/modules/asset/asset.py index a09fb24..33a79f2 100644 --- a/dkg/modules/asset/asset.py +++ b/dkg/modules/asset/asset.py @@ -209,6 +209,7 @@ def create( blockchain_id = self.manager.blockchain_provider.blockchain_id dataset = {} + content = kc_tools.escape_literal_dict(content) public_content = dataset.get("public") private_content = dataset.get("private") if isinstance(content, str): diff --git a/dkg/modules/asset/async_asset.py b/dkg/modules/asset/async_asset.py index 98a9693..639b52a 100644 --- a/dkg/modules/asset/async_asset.py +++ b/dkg/modules/asset/async_asset.py @@ -240,6 +240,7 @@ async def create( blockchain_id = self.manager.blockchain_provider.blockchain_id dataset = {} + content = kc_tools.escape_literal_dict(content) public_content = dataset.get("public") private_content = dataset.get("private") if isinstance(content, str): diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index 66a13b8..b4c1a0c 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -246,3 +246,29 @@ def solidity_packed_sha256(types: list[str], values: list) -> str: sha256_hash = hashlib.sha256(packed_data).hexdigest() return f"0x{sha256_hash}" + + +def escape_literal_string(s): + escape_map = { + "\b": r"\b", + "\f": r"\f", + "\n": r"\n", + "\r": r"\r", + "\t": r"\t", + '"': r"\"", + "'": r"\'", + } + for char, replacement in escape_map.items(): + s = s.replace(char, replacement) + return s + + +def escape_literal_dict(obj): + if isinstance(obj, dict): + return {k: escape_literal_dict(v) for k, v in obj.items()} + elif isinstance(obj, list): + return [escape_literal_dict(i) for i in obj] + elif isinstance(obj, str): + return escape_literal_string(s=obj) + else: + return obj From 27424418a57e72f42f937ec81ba98141d3a2885d Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 29 Apr 2025 12:12:59 +0200 Subject: [PATCH 103/146] added run-async-demo make command --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 9a900bc..282aec0 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,9 @@ install: run-demo: python3 examples/demo.py +run-async-demo: + python3 examples/async_demo.py + ruff: ruff check --fix ruff format From 2f7bb9f635d137432a03f203469fd0ad4961f277 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 29 Apr 2025 15:51:29 +0200 Subject: [PATCH 104/146] support for utf-8 chars publishing --- dkg/utils/node_request.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 2e2e6db..5c8e0a3 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -63,6 +63,7 @@ class NodeRequest: "minimumNumberOfNodeReplications": int, }, ) + publish.headers = "Content-Type: x-nquads" ask = NodeCall( method=HTTPRequestMethod.POST, From 2c8a307f709c331b9fddd558d72fad3cba61e90d Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Wed, 30 Apr 2025 13:17:46 +0200 Subject: [PATCH 105/146] chunks handled correctly --- dkg/utils/knowledge_collection_tools.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index b4c1a0c..56e1f94 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -1,4 +1,5 @@ from typing import Literal +import codecs from dkg.constants import CHUNK_BYTE_SIZE from dkg.exceptions import DatasetInputFormatNotSupported, InvalidDataset from dkg.types import JSONLD, NQuads @@ -96,7 +97,9 @@ def split_into_chunks(quads, chunk_size_bytes=32): while start < len(encoded_bytes): end = min(start + chunk_size_bytes, len(encoded_bytes)) chunk = encoded_bytes[start:end] - chunks.append(chunk.decode("utf-8")) # Decode bytes back to string + chunks.append( + codecs.decode(chunk, "utf-8", errors="replace") + ) # Decode bytes back to string start = end return chunks From 5d75715decc809ab3e9cf8e2b12fc4c190a34e81 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Wed, 30 Apr 2025 13:48:31 +0200 Subject: [PATCH 106/146] ' fix --- dkg/utils/knowledge_collection_tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index 56e1f94..2d86323 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -259,7 +259,7 @@ def escape_literal_string(s): "\r": r"\r", "\t": r"\t", '"': r"\"", - "'": r"\'", + "'": r"'", } for char, replacement in escape_map.items(): s = s.replace(char, replacement) From 6797f205ae79215359f23a4e9b758027991575f6 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Wed, 30 Apr 2025 15:20:00 +0200 Subject: [PATCH 107/146] json.dumps fix in demo --- examples/demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/demo.py b/examples/demo.py index 79bfba4..c9de287 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -46,7 +46,7 @@ def divider(): def print_json(json_dict: dict): - print(json.dumps(json_dict, indent=4)) + print(json.dumps(json_dict, indent=4, ensure_ascii=False)) content = { From ffbf25c958396b2f2bc031a1820b633eb7a22bb3 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Wed, 30 Apr 2025 17:33:41 +0200 Subject: [PATCH 108/146] ensuring utf-8 encoding in response --- dkg/modules/graph/graph.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dkg/modules/graph/graph.py b/dkg/modules/graph/graph.py index 9608261..7278b77 100644 --- a/dkg/modules/graph/graph.py +++ b/dkg/modules/graph/graph.py @@ -50,6 +50,7 @@ def query( query_type = parsed_query[1].name.replace("Query", "").upper() result = self.node_service.query(query, query_type, repository, paranet_ual) + result.encoding = "utf-8" return result.get("data") From c4eaa66c9f56cd82b01a769d516298af0f7dd7e0 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Thu, 1 May 2025 11:25:28 +0200 Subject: [PATCH 109/146] added both \a and \v to the escape map --- dkg/utils/knowledge_collection_tools.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index 2d86323..0260297 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -253,11 +253,13 @@ def solidity_packed_sha256(types: list[str], values: list) -> str: def escape_literal_string(s): escape_map = { + "\a": r"\a", "\b": r"\b", "\f": r"\f", "\n": r"\n", "\r": r"\r", "\t": r"\t", + "\v": r"\v", '"': r"\"", "'": r"'", } From 05d19cb20e2e07b7ae7b9e1f0b3dde2c97db0711 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 5 May 2025 15:40:23 +0200 Subject: [PATCH 110/146] version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 870c5fd..5556381 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.3" +version = "8.0.8" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From ce9a18c2581ae2914d866e85ece07fcc80a14257 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 5 May 2025 15:52:44 +0200 Subject: [PATCH 111/146] moved the map into constants --- dkg/constants.py | 12 ++++++++++++ dkg/utils/knowledge_collection_tools.py | 15 ++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/dkg/constants.py b/dkg/constants.py index 2193660..4fe7a50 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -35,6 +35,18 @@ MAX_FILE_SIZE = 10000000 +ESCAPE_MAP = { + "\a": r"\a", + "\b": r"\b", + "\f": r"\f", + "\n": r"\n", + "\r": r"\r", + "\t": r"\t", + "\v": r"\v", + '"': r"\"", + "'": r"'", +} + class DefaultParameters(Enum): ENVIRONMENT: str = "mainnet" diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index 0260297..db57730 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -4,7 +4,7 @@ from dkg.exceptions import DatasetInputFormatNotSupported, InvalidDataset from dkg.types import JSONLD, NQuads from pyld import jsonld -from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM +from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM, ESCAPE_MAP from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral from uuid import uuid4 from web3 import Web3 @@ -252,18 +252,7 @@ def solidity_packed_sha256(types: list[str], values: list) -> str: def escape_literal_string(s): - escape_map = { - "\a": r"\a", - "\b": r"\b", - "\f": r"\f", - "\n": r"\n", - "\r": r"\r", - "\t": r"\t", - "\v": r"\v", - '"': r"\"", - "'": r"'", - } - for char, replacement in escape_map.items(): + for char, replacement in ESCAPE_MAP.items(): s = s.replace(char, replacement) return s From 36620ed7a37b82bac1d7d5f1b25bfbdadad9483a Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 5 May 2025 15:53:05 +0200 Subject: [PATCH 112/146] encoding fix for async graph --- dkg/modules/graph/async_graph.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dkg/modules/graph/async_graph.py b/dkg/modules/graph/async_graph.py index 8dd071c..42dc3ff 100644 --- a/dkg/modules/graph/async_graph.py +++ b/dkg/modules/graph/async_graph.py @@ -57,6 +57,7 @@ async def query( result = await self.node_service.query( query, query_type, repository, paranet_ual ) + result.encoding = "utf-8" return result.get("data") From bc2bc5e1365259d90156302cd12e755921d619aa Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 6 May 2025 10:43:58 +0200 Subject: [PATCH 113/146] removal of headers --- dkg/utils/node_request.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 5c8e0a3..2e2e6db 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -63,7 +63,6 @@ class NodeRequest: "minimumNumberOfNodeReplications": int, }, ) - publish.headers = "Content-Type: x-nquads" ask = NodeCall( method=HTTPRequestMethod.POST, From ebea626926a5f1fb2c13da572fa43c35c2a1a98e Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 6 May 2025 12:44:01 +0200 Subject: [PATCH 114/146] version bump to 8.0.11 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5556381..7843f97 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.8" +version = "8.0.11" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From d75c539798f8a33ff0a278c8bd672a32ae7c6549 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 6 May 2025 12:49:06 +0200 Subject: [PATCH 115/146] ensure ascii off in demo --- examples/async_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/async_demo.py b/examples/async_demo.py index cd85f3d..15a3167 100644 --- a/examples/async_demo.py +++ b/examples/async_demo.py @@ -30,7 +30,7 @@ def divider(): print("==================================================") def print_json(json_dict: dict): - print(json.dumps(json_dict, indent=4)) + print(json.dumps(json_dict, indent=4, ensure_ascii=False)) content = { "public": { From 6ce8f16a78fd69c1ac7b9b98176d8865dfaf0f0d Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 9 May 2025 11:16:22 +0200 Subject: [PATCH 116/146] remove devnet --- dkg/constants.py | 21 --------------------- dkg/types/blockchain.py | 2 +- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/dkg/constants.py b/dkg/constants.py index 4fe7a50..8f16459 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -75,19 +75,9 @@ class OutputTypes(Enum): JSONLD: str = "JSON-LD" -class Environments(Enum): - DEVELOPMENT: str = "development" - DEVNET: str = "devnet" - TESTNET: str = "testnet" - MAINNET: str = "mainnet" - - class BlockchainIds(Enum): HARDHAT_1: str = "hardhat1:31337" HARDHAT_2: str = "hardhat2:31337" - BASE_DEVNET: str = "base:84532" - GNOSIS_DEVNET: str = "gnosis:10200" - NEUROWEB_DEVNET: str = "otp:2160" BASE_TESTNET: str = "base:84532" GNOSIS_TESTNET: str = "gnosis:10200" NEUROWEB_TESTNET: str = "otp:20430" @@ -114,12 +104,6 @@ class OperationStatuses(str, Enum): "rpc": "http://localhost:9545", }, }, - "devnet": { - "base:84532": { - "hub": "0xE043daF4cC8ae2c720ef95fc82574a37a429c40A", - "rpc": "https://sepolia.base.org", - } - }, "testnet": { "base:84532": { "hub": "0xf21CE8f8b01548D97DCFb36869f1ccB0814a4e05", @@ -152,11 +136,6 @@ class OperationStatuses(str, Enum): DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS = { "development": {"hardhat1:31337": 2, "hardhat2:31337": 2, "otp:2043": 2}, - "devnet": { - "otp:2160": 2, - "gnosis:10200": 2, - "base:84532": 2, - }, "testnet": { "otp:20430": 2, "gnosis:10200": 2, diff --git a/dkg/types/blockchain.py b/dkg/types/blockchain.py index c7dbaf8..57af43e 100644 --- a/dkg/types/blockchain.py +++ b/dkg/types/blockchain.py @@ -50,7 +50,7 @@ class ABIError(TypedDict): ABI = list[ABIElement] -Environment = Literal["development", "devnet", "testnet", "mainnet"] +Environment = Literal["development", "testnet", "mainnet"] class AgreementData(NamedTuple): From 3d7de2d1f32d737c1c3c73f7b34b8d975ece80c5 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 9 May 2025 11:16:53 +0200 Subject: [PATCH 117/146] add example in .env.example --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 6fc16b3..6e3cd57 100644 --- a/.env.example +++ b/.env.example @@ -1 +1 @@ -PRIVATE_KEY= +PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 From 2a8e760e120fabeaf951e91c3a6ca0baad9f5227 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 9 May 2025 11:17:03 +0200 Subject: [PATCH 118/146] improve Makefile --- Makefile | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 282aec0..82d8f4f 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,15 @@ install: poetry install pre-commit install -run-demo: +demo: python3 examples/demo.py -run-async-demo: +async-demo: python3 examples/async_demo.py +paranet-demo: + python3 examples/paranets_demo.py + ruff: ruff check --fix ruff format @@ -18,4 +21,6 @@ help: @echo "Available commands:" @echo " install - Install dependencies and set up pre-commit hooks" @echo " ruff - Format code and fix linting issues using ruff" - @echo " run-demo - Run /examples/demo.py file" + @echo " demo - Run /examples/demo.py file" + @echo " async-demo - Run /examples/async_demo.py file" + @echo " paranet-demo - Run /examples/paranets_demo.py file" \ No newline at end of file From cbd78b878770e69f8c9c0b3230fe07f985564a33 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 9 May 2025 11:19:48 +0200 Subject: [PATCH 119/146] Get environment from blockchainId --- dkg/providers/blockchain/async_blockchain.py | 5 ++- dkg/providers/blockchain/base_blockchain.py | 33 ++++++++++---------- dkg/providers/blockchain/blockchain.py | 5 ++- examples/async_demo.py | 7 ++--- examples/demo.py | 7 ++--- examples/paranets_demo.py | 12 +++---- 6 files changed, 30 insertions(+), 39 deletions(-) diff --git a/dkg/providers/blockchain/async_blockchain.py b/dkg/providers/blockchain/async_blockchain.py index 6f3f382..651938d 100644 --- a/dkg/providers/blockchain/async_blockchain.py +++ b/dkg/providers/blockchain/async_blockchain.py @@ -27,7 +27,7 @@ AccountMissing, NetworkNotSupported, ) -from dkg.types import URI, Address, Environment, Wei +from dkg.types import URI, Address, Wei from web3.contract import Contract from web3.contract.contract import ContractFunction from web3.types import TxReceipt @@ -39,13 +39,12 @@ class AsyncBlockchainProvider(BaseBlockchainProvider): def __init__( self, - environment: Environment, blockchain_id: str, rpc_uri: URI | None = None, gas_price: Wei | None = None, verify: bool = True, ): - super().__init__(environment, blockchain_id, rpc_uri, gas_price) + super().__init__(blockchain_id, rpc_uri, gas_price) ssl_context = None if verify else False self.w3 = AsyncWeb3( diff --git a/dkg/providers/blockchain/base_blockchain.py b/dkg/providers/blockchain/base_blockchain.py index 5ff52d2..1411254 100644 --- a/dkg/providers/blockchain/base_blockchain.py +++ b/dkg/providers/blockchain/base_blockchain.py @@ -8,7 +8,7 @@ EnvironmentNotSupported, RPCURINotDefined, ) -from dkg.types import URI, DataHexStr, Environment, Wei +from dkg.types import URI, DataHexStr, Wei from eth_account.signers.local import LocalAccount from eth_typing import ABI, ABIFunction from web3.logs import DISCARD @@ -21,27 +21,26 @@ class BaseBlockchainProvider: def __init__( self, - environment: Environment, blockchain_id: str, rpc_uri: URI | None = None, gas_price: Wei | None = None, ): - if environment not in BLOCKCHAINS.keys(): - raise EnvironmentNotSupported(f"Environment {environment} isn't supported!") - - self.environment = environment - self.rpc_uri = rpc_uri - self.blockchain_id = ( - blockchain_id - if blockchain_id in BLOCKCHAINS[self.environment].keys() - else None - ) + self.environment = None + for env_name, chains_in_env in BLOCKCHAINS.items(): + if blockchain_id in chains_in_env: + self.environment = env_name + break + + if self.environment is None: + raise EnvironmentNotSupported( + f"Could not derive environment for blockchain_id: {blockchain_id}. " + "Ensure it's defined in BLOCKCHAINS constant." + ) - if self.rpc_uri is None and self.blockchain_id is not None: - self.blockchain_id = blockchain_id - self.rpc_uri = self.rpc_uri or BLOCKCHAINS[self.environment][ - self.blockchain_id - ].get("rpc", None) + self.blockchain_id = blockchain_id + self.rpc_uri = rpc_uri or BLOCKCHAINS[self.environment][self.blockchain_id].get( + "rpc", None + ) if self.rpc_uri is None: raise RPCURINotDefined( diff --git a/dkg/providers/blockchain/blockchain.py b/dkg/providers/blockchain/blockchain.py index 1c2f6a4..e5c646e 100644 --- a/dkg/providers/blockchain/blockchain.py +++ b/dkg/providers/blockchain/blockchain.py @@ -26,7 +26,7 @@ AccountMissing, NetworkNotSupported, ) -from dkg.types import URI, Address, Environment, Wei +from dkg.types import URI, Address, Wei from web3 import Web3 from web3.contract import Contract from web3.contract.contract import ContractFunction @@ -37,13 +37,12 @@ class BlockchainProvider(BaseBlockchainProvider): def __init__( self, - environment: Environment, blockchain_id: str, rpc_uri: URI | None = None, gas_price: Wei | None = None, verify: bool = True, ): - super().__init__(environment, blockchain_id, rpc_uri, gas_price) + super().__init__(blockchain_id, rpc_uri, gas_price) self.w3 = Web3( Web3.HTTPProvider(self.rpc_uri, request_kwargs={"verify": verify}) diff --git a/examples/async_demo.py b/examples/async_demo.py index 15a3167..c29bd9c 100644 --- a/examples/async_demo.py +++ b/examples/async_demo.py @@ -2,7 +2,7 @@ import json import time from dkg import AsyncDKG -from dkg.constants import Environments, BlockchainIds +from dkg.constants import BlockchainIds from dkg.providers import AsyncBlockchainProvider, AsyncNodeHTTPProvider @@ -13,10 +13,7 @@ async def main(): ) # make sure that you have PRIVATE_KEY in .env so the blockchain provider can load it - blockchain_provider = AsyncBlockchainProvider( - Environments.DEVELOPMENT.value, - BlockchainIds.HARDHAT_1.value, - ) + blockchain_provider = AsyncBlockchainProvider(BlockchainIds.HARDHAT_1.value) dkg = AsyncDKG( node_provider, diff --git a/examples/demo.py b/examples/demo.py index c9de287..2183f57 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -20,17 +20,14 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider -from dkg.constants import Environments, BlockchainIds +from dkg.constants import BlockchainIds node_provider = NodeHTTPProvider( endpoint_uri="http://localhost:8900", api_version="v1", ) # make sure that you have PRIVATE_KEY in .env so the blockchain provider can load it -blockchain_provider = BlockchainProvider( - Environments.DEVELOPMENT.value, - BlockchainIds.HARDHAT_1.value, -) +blockchain_provider = BlockchainProvider(BlockchainIds.HARDHAT_1.value) # here you can create your own custom values that will be applied to all the functions config = { "max_number_of_retries": 300, diff --git a/examples/paranets_demo.py b/examples/paranets_demo.py index de64a7f..6f36d59 100644 --- a/examples/paranets_demo.py +++ b/examples/paranets_demo.py @@ -22,14 +22,11 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider from dkg.dataclasses import ParanetNodesAccessPolicy, ParanetMinersAccessPolicy -from dkg.constants import Environments, BlockchainIds +from dkg.constants import BlockchainIds node_provider = NodeHTTPProvider("http://localhost:8900") -blockchain_provider = BlockchainProvider( - Environments.DEVELOPMENT.value, - BlockchainIds.HARDHAT_1.value, -) +blockchain_provider = BlockchainProvider(BlockchainIds.HARDHAT_1.value) dkg = DKG(node_provider, blockchain_provider) @@ -66,7 +63,10 @@ def convert_hexbytes(data): } } -create_paranet_knowledge_collection_result = dkg.asset.create(paranet_data, 1) +create_paranet_knowledge_collection_result = dkg.asset.create( + paranet_data, + options={"epochs_num": 2}, +) print("======================== PARANET KNOWLEDGE COLLECTION CREATED") print_json(create_paranet_knowledge_collection_result) From aa41a4535b04077a58cdf00f6103d57a486a20ba Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 9 May 2025 11:20:48 +0200 Subject: [PATCH 120/146] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7843f97..0cabdac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.11" +version = "8.0.12" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From 03e6ff278c5f1650b19e80d257aaf9a138973be6 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Fri, 16 May 2025 11:43:34 +0200 Subject: [PATCH 121/146] replaced Graph with Dataset, so nquads are parsed properly --- dkg/utils/knowledge_collection_tools.py | 38 +++++++++++-------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index db57730..4ee71f4 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -5,7 +5,7 @@ from dkg.types import JSONLD, NQuads from pyld import jsonld from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM, ESCAPE_MAP -from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral +from rdflib import Graph, Dataset, BNode, URIRef, Literal as RDFLiteral from uuid import uuid4 from web3 import Web3 import math @@ -154,29 +154,23 @@ def replace_blank_node(term): return term # Return IRIs or Literals unchanged - # Create a temporary graph for parsing individual quads - result = [] - - # Process each N-Quad string individually to maintain order - for nquad in nquads_list: - if not nquad.strip(): - continue + all_nquads = "\n".join(nquad.strip() for nquad in nquads_list if nquad.strip()) - # Parse single N-Quad - g = Graph() - g.parse(data=nquad, format="nquads") + # Create a single Dataset + ds = Dataset() + ds.parse(data=all_nquads, format="nquads") - # Get the triple and replace blank nodes - for s, p, o in g: - updated_quad = ( - replace_blank_node(s), - replace_blank_node(p), - replace_blank_node(o), - ) - # Format as N-Quad string - result.append( - f"{updated_quad[0].n3()} {updated_quad[1].n3()} {updated_quad[2].n3()} ." - ) + # Process all quads + result = [] + for s, p, o, g in ds.quads((None, None, None, None)): + updated_quad = ( + replace_blank_node(s), + replace_blank_node(p), + replace_blank_node(o), + ) + result.append( + f"{updated_quad[0].n3()} {updated_quad[1].n3()} {updated_quad[2].n3()} ." + ) return result From c2789b290a4c9945da66c5a873ca2d5b1376f9ee Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 19 May 2025 12:31:29 +0200 Subject: [PATCH 122/146] raise error for invalid jsonld data --- dkg/utils/knowledge_collection_tools.py | 52 +++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index 4ee71f4..c06f73a 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -5,7 +5,8 @@ from dkg.types import JSONLD, NQuads from pyld import jsonld from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM, ESCAPE_MAP -from rdflib import Graph, Dataset, BNode, URIRef, Literal as RDFLiteral +from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral +from rdflib.exceptions import ParserError as RDFParserError from uuid import uuid4 from web3 import Web3 import math @@ -157,12 +158,15 @@ def replace_blank_node(term): all_nquads = "\n".join(nquad.strip() for nquad in nquads_list if nquad.strip()) # Create a single Dataset - ds = Dataset() - ds.parse(data=all_nquads, format="nquads") + g = Graph() + try: + g.parse(data=all_nquads, format="nt") + except RDFParserError: + raise UnsupportedJSON_LD(nquads_list) # Process all quads result = [] - for s, p, o, g in ds.quads((None, None, None, None)): + for s, p, o in g: updated_quad = ( replace_blank_node(s), replace_blank_node(p), @@ -260,3 +264,43 @@ def escape_literal_dict(obj): return escape_literal_string(s=obj) else: return obj + + +class UnsupportedJSON_LD(Exception): + def __init__(self, nquads_list): + self.nquads_list = nquads_list + self.message = f""" +Unsupported JSON-LD input detected + +After parsing the JSON-LD input, the parser detected creation of new named graphs. +The DKG does not support custom named graphs. + +Problematic Quads: + +{self.find_problematic_quads()} + +Full Parsed N-Quads Array: + +{self.format_nquads_list()} + +""" + super().__init__(self.message) + + def __str__(self): + return f"{self.__class__.__name__}: {self.message}" + + def format_nquads_list(self): + return "\n".join(nquad.strip() for nquad in self.nquads_list) + + def find_problematic_quads(self): + problematic = [] + g = Graph() + for quad in self.nquads_list: + if not quad.strip(): + continue + try: + g.parse(data=quad, format="nt") + except RDFParserError: + problematic.append(quad) + + return "\n".join(f"{i + 1}. {quad}" for i, quad in enumerate(problematic)) From 26b8a7fa6d8652cb082399410f7095f0f5039899 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 19 May 2025 13:06:02 +0200 Subject: [PATCH 123/146] fix in rewrite --- dkg/utils/knowledge_collection_tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index c06f73a..e9be2c7 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -155,7 +155,7 @@ def replace_blank_node(term): return term # Return IRIs or Literals unchanged - all_nquads = "\n".join(nquad.strip() for nquad in nquads_list if nquad.strip()) + all_nquads = "\n".join(nquad for nquad in nquads_list if nquad.strip()) # Create a single Dataset g = Graph() From f7093ac80657bf14a160d05bb31f31906e32d0b1 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 19 May 2025 15:16:05 +0200 Subject: [PATCH 124/146] naming convention fix, and added com --- dkg/utils/knowledge_collection_tools.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index e9be2c7..14371db 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -162,7 +162,7 @@ def replace_blank_node(term): try: g.parse(data=all_nquads, format="nt") except RDFParserError: - raise UnsupportedJSON_LD(nquads_list) + raise UnsupportedJSONLD(nquads_list) # Process all quads result = [] @@ -266,7 +266,8 @@ def escape_literal_dict(obj): return obj -class UnsupportedJSON_LD(Exception): +# Used when JSON-LD parsing fails due to quads being passed instead of triples +class UnsupportedJSONLD(Exception): def __init__(self, nquads_list): self.nquads_list = nquads_list self.message = f""" From aa1f4f8c74e6f2a72e9a8514b5393d4562b1756a Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 19 May 2025 15:58:19 +0200 Subject: [PATCH 125/146] version bump to 8.0.13 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0cabdac..a3f82e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.12" +version = "8.0.13" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From 8ae055ddf099f1a16d172f5b15defce41344b4d1 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 2 Jun 2025 12:45:44 +0200 Subject: [PATCH 126/146] added test infrastructure --- Makefile | 6 +- poetry.lock | 3431 +++++++++++++++++++++++++++++------------------- pyproject.toml | 19 + 3 files changed, 2074 insertions(+), 1382 deletions(-) diff --git a/Makefile b/Makefile index 82d8f4f..b58a085 100644 --- a/Makefile +++ b/Makefile @@ -17,10 +17,14 @@ ruff: ruff check --fix ruff format +run-test: + pytest + help: @echo "Available commands:" @echo " install - Install dependencies and set up pre-commit hooks" @echo " ruff - Format code and fix linting issues using ruff" + @echo " run-test - Run tests" @echo " demo - Run /examples/demo.py file" @echo " async-demo - Run /examples/async_demo.py file" - @echo " paranet-demo - Run /examples/paranets_demo.py file" \ No newline at end of file + @echo " paranet-demo - Run /examples/paranets_demo.py file" diff --git a/poetry.lock b/poetry.lock index d705237..a2e55d7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,122 +1,136 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. + +[[package]] +name = "aiohappyeyeballs" +version = "2.6.1" +description = "Happy Eyeballs for asyncio" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8"}, + {file = "aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558"}, +] [[package]] name = "aiohttp" -version = "3.8.5" +version = "3.12.6" description = "Async http client/server framework (asyncio)" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a94159871304770da4dd371f4291b20cac04e8c94f11bdea1c3478e557fbe0d8"}, - {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:13bf85afc99ce6f9ee3567b04501f18f9f8dbbb2ea11ed1a2e079670403a7c84"}, - {file = "aiohttp-3.8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ce2ac5708501afc4847221a521f7e4b245abf5178cf5ddae9d5b3856ddb2f3a"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96943e5dcc37a6529d18766597c491798b7eb7a61d48878611298afc1fca946c"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ad5c3c4590bb3cc28b4382f031f3783f25ec223557124c68754a2231d989e2b"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c413c633d0512df4dc7fd2373ec06cc6a815b7b6d6c2f208ada7e9e93a5061d"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df72ac063b97837a80d80dec8d54c241af059cc9bb42c4de68bd5b61ceb37caa"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c48c5c0271149cfe467c0ff8eb941279fd6e3f65c9a388c984e0e6cf57538e14"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:368a42363c4d70ab52c2c6420a57f190ed3dfaca6a1b19afda8165ee16416a82"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7607ec3ce4993464368505888af5beb446845a014bc676d349efec0e05085905"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0d21c684808288a98914e5aaf2a7c6a3179d4df11d249799c32d1808e79503b5"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:312fcfbacc7880a8da0ae8b6abc6cc7d752e9caa0051a53d217a650b25e9a691"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad093e823df03bb3fd37e7dec9d4670c34f9e24aeace76808fc20a507cace825"}, - {file = "aiohttp-3.8.5-cp310-cp310-win32.whl", hash = "sha256:33279701c04351a2914e1100b62b2a7fdb9a25995c4a104259f9a5ead7ed4802"}, - {file = "aiohttp-3.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:6e4a280e4b975a2e7745573e3fc9c9ba0d1194a3738ce1cbaa80626cc9b4f4df"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae871a964e1987a943d83d6709d20ec6103ca1eaf52f7e0d36ee1b5bebb8b9b9"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:461908b2578955045efde733719d62f2b649c404189a09a632d245b445c9c975"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72a860c215e26192379f57cae5ab12b168b75db8271f111019509a1196dfc780"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14be025665dba6202b6a71cfcdb53210cc498e50068bc088076624471f8bb9"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af740fc2711ad85f1a5c034a435782fbd5b5f8314c9a3ef071424a8158d7f6b"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:841cd8233cbd2111a0ef0a522ce016357c5e3aff8a8ce92bcfa14cef890d698f"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed1c46fb119f1b59304b5ec89f834f07124cd23ae5b74288e364477641060ff"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84f8ae3e09a34f35c18fa57f015cc394bd1389bce02503fb30c394d04ee6b938"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62360cb771707cb70a6fd114b9871d20d7dd2163a0feafe43fd115cfe4fe845e"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23fb25a9f0a1ca1f24c0a371523546366bb642397c94ab45ad3aedf2941cec6a"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0ba0d15164eae3d878260d4c4df859bbdc6466e9e6689c344a13334f988bb53"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5d20003b635fc6ae3f96d7260281dfaf1894fc3aa24d1888a9b2628e97c241e5"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0175d745d9e85c40dcc51c8f88c74bfbaef9e7afeeeb9d03c37977270303064c"}, - {file = "aiohttp-3.8.5-cp311-cp311-win32.whl", hash = "sha256:2e1b1e51b0774408f091d268648e3d57f7260c1682e7d3a63cb00d22d71bb945"}, - {file = "aiohttp-3.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:043d2299f6dfdc92f0ac5e995dfc56668e1587cea7f9aa9d8a78a1b6554e5755"}, - {file = "aiohttp-3.8.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cae533195e8122584ec87531d6df000ad07737eaa3c81209e85c928854d2195c"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f21e83f355643c345177a5d1d8079f9f28b5133bcd154193b799d380331d5d3"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a75ef35f2df54ad55dbf4b73fe1da96f370e51b10c91f08b19603c64004acc"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e2e9839e14dd5308ee773c97115f1e0a1cb1d75cbeeee9f33824fa5144c7634"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44e65da1de4403d0576473e2344828ef9c4c6244d65cf4b75549bb46d40b8dd"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d847e4cde6ecc19125ccbc9bfac4a7ab37c234dd88fbb3c5c524e8e14da543"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c7a815258e5895d8900aec4454f38dca9aed71085f227537208057853f9d13f2"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:8b929b9bd7cd7c3939f8bcfffa92fae7480bd1aa425279d51a89327d600c704d"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5db3a5b833764280ed7618393832e0853e40f3d3e9aa128ac0ba0f8278d08649"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:a0215ce6041d501f3155dc219712bc41252d0ab76474615b9700d63d4d9292af"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:fd1ed388ea7fbed22c4968dd64bab0198de60750a25fe8c0c9d4bef5abe13824"}, - {file = "aiohttp-3.8.5-cp36-cp36m-win32.whl", hash = "sha256:6e6783bcc45f397fdebc118d772103d751b54cddf5b60fbcc958382d7dd64f3e"}, - {file = "aiohttp-3.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:b5411d82cddd212644cf9360879eb5080f0d5f7d809d03262c50dad02f01421a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:01d4c0c874aa4ddfb8098e85d10b5e875a70adc63db91f1ae65a4b04d3344cda"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5980a746d547a6ba173fd5ee85ce9077e72d118758db05d229044b469d9029a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a482e6da906d5e6e653be079b29bc173a48e381600161c9932d89dfae5942ef"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80bd372b8d0715c66c974cf57fe363621a02f359f1ec81cba97366948c7fc873"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1161b345c0a444ebcf46bf0a740ba5dcf50612fd3d0528883fdc0eff578006a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd56db019015b6acfaaf92e1ac40eb8434847d9bf88b4be4efe5bfd260aee692"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:153c2549f6c004d2754cc60603d4668899c9895b8a89397444a9c4efa282aaf4"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4a01951fabc4ce26ab791da5f3f24dca6d9a6f24121746eb19756416ff2d881b"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bfb9162dcf01f615462b995a516ba03e769de0789de1cadc0f916265c257e5d8"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7dde0009408969a43b04c16cbbe252c4f5ef4574ac226bc8815cd7342d2028b6"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4149d34c32f9638f38f544b3977a4c24052042affa895352d3636fa8bffd030a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-win32.whl", hash = "sha256:68c5a82c8779bdfc6367c967a4a1b2aa52cd3595388bf5961a62158ee8a59e22"}, - {file = "aiohttp-3.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2cf57fb50be5f52bda004b8893e63b48530ed9f0d6c96c84620dc92fe3cd9b9d"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:eca4bf3734c541dc4f374ad6010a68ff6c6748f00451707f39857f429ca36ced"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1274477e4c71ce8cfe6c1ec2f806d57c015ebf84d83373676036e256bc55d690"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28c543e54710d6158fc6f439296c7865b29e0b616629767e685a7185fab4a6b9"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:910bec0c49637d213f5d9877105d26e0c4a4de2f8b1b29405ff37e9fc0ad52b8"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5443910d662db951b2e58eb70b0fbe6b6e2ae613477129a5805d0b66c54b6cb7"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e460be6978fc24e3df83193dc0cc4de46c9909ed92dd47d349a452ef49325b7"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb1558def481d84f03b45888473fc5a1f35747b5f334ef4e7a571bc0dfcb11f8"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34dd0c107799dcbbf7d48b53be761a013c0adf5571bf50c4ecad5643fe9cfcd0"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aa1990247f02a54185dc0dff92a6904521172a22664c863a03ff64c42f9b5410"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0e584a10f204a617d71d359fe383406305a4b595b333721fa50b867b4a0a1548"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a3cf433f127efa43fee6b90ea4c6edf6c4a17109d1d037d1a52abec84d8f2e42"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c11f5b099adafb18e65c2c997d57108b5bbeaa9eeee64a84302c0978b1ec948b"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:84de26ddf621d7ac4c975dbea4c945860e08cccde492269db4e1538a6a6f3c35"}, - {file = "aiohttp-3.8.5-cp38-cp38-win32.whl", hash = "sha256:ab88bafedc57dd0aab55fa728ea10c1911f7e4d8b43e1d838a1739f33712921c"}, - {file = "aiohttp-3.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:5798a9aad1879f626589f3df0f8b79b3608a92e9beab10e5fda02c8a2c60db2e"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a6ce61195c6a19c785df04e71a4537e29eaa2c50fe745b732aa937c0c77169f3"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:773dd01706d4db536335fcfae6ea2440a70ceb03dd3e7378f3e815b03c97ab51"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f83a552443a526ea38d064588613aca983d0ee0038801bc93c0c916428310c28"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f7372f7341fcc16f57b2caded43e81ddd18df53320b6f9f042acad41f8e049a"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea353162f249c8097ea63c2169dd1aa55de1e8fecbe63412a9bc50816e87b761"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d47ae48db0b2dcf70bc8a3bc72b3de86e2a590fc299fdbbb15af320d2659de"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d827176898a2b0b09694fbd1088c7a31836d1a505c243811c87ae53a3f6273c1"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3562b06567c06439d8b447037bb655ef69786c590b1de86c7ab81efe1c9c15d8"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e874cbf8caf8959d2adf572a78bba17cb0e9d7e51bb83d86a3697b686a0ab4d"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6809a00deaf3810e38c628e9a33271892f815b853605a936e2e9e5129762356c"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:33776e945d89b29251b33a7e7d006ce86447b2cfd66db5e5ded4e5cd0340585c"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eaeed7abfb5d64c539e2db173f63631455f1196c37d9d8d873fc316470dfbacd"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e91d635961bec2d8f19dfeb41a539eb94bd073f075ca6dae6c8dc0ee89ad6f91"}, - {file = "aiohttp-3.8.5-cp39-cp39-win32.whl", hash = "sha256:00ad4b6f185ec67f3e6562e8a1d2b69660be43070bd0ef6fcec5211154c7df67"}, - {file = "aiohttp-3.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:c0a9034379a37ae42dea7ac1e048352d96286626251862e448933c0f59cbd79c"}, - {file = "aiohttp-3.8.5.tar.gz", hash = "sha256:b9552ec52cc147dbf1944ac7ac98af7602e51ea2dcd076ed194ca3c0d1c7d0bc"}, + {file = "aiohttp-3.12.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:77ba53286c89486e8b02fb47352a5a8270bab1084e2a43fe8e35eb261befda13"}, + {file = "aiohttp-3.12.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:93f207a64989346bbd0a9d3b31ebaa3934ea6e0242b555491af7eb97ad1c0a5a"}, + {file = "aiohttp-3.12.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce6673b73352edb17c2db86a9586dc7744e0b5009709152a1e75379f16af19e0"}, + {file = "aiohttp-3.12.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:128603479bf13479661d763e77e254139f066914227b5f2ff3284d19e416ad75"}, + {file = "aiohttp-3.12.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93a0887cea23f76e9354235b0e79b3c9922ad66529e11637940b6439849105cb"}, + {file = "aiohttp-3.12.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5fe1d74ab6cd1f16c3c2f0e3c3230481dcedc0d3ad9f0b82b1e43f44a4980aca"}, + {file = "aiohttp-3.12.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9aecb4ce110c9d321860a00b4f9ec72bef691d045f54c983fa678606f3f918b0"}, + {file = "aiohttp-3.12.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5f698e7b5b57aa4dc646c8f13ccd965c694199595d7a45cecefaf0e5c392890"}, + {file = "aiohttp-3.12.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5c6869319c0a5f4150959e065c40836b18a99e02493c3b4c73b25378aa0f0cc"}, + {file = "aiohttp-3.12.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71905d34b3bb1a6be44e986f08404987bb317d890746e71f320cd10cf3222b46"}, + {file = "aiohttp-3.12.6-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:d590b36c3497ecfba4aca71ab9342fb2c07e1b69baf4e28ad4227440c128bb22"}, + {file = "aiohttp-3.12.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a90b6f2d5ca4d3ad56034863237b59b4a5fab270eb6d11b5c0326b4501448b51"}, + {file = "aiohttp-3.12.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:7f22a0d9a995c12bb20247334b414edaf65ce8f22a1e838b90210238f9b57571"}, + {file = "aiohttp-3.12.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:30511c5e66ac4399d46b4bec57a3d56bc16cfb649255fa798ee95d8b45f97a4b"}, + {file = "aiohttp-3.12.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c05776d1854ae9d8132d7ced7ac0067f602d66589797788ed3902d5c68686db5"}, + {file = "aiohttp-3.12.6-cp310-cp310-win32.whl", hash = "sha256:8885da8ae99bbe6ce43b79e284ef8e6bc5285dea297fe2a163552f09435c8069"}, + {file = "aiohttp-3.12.6-cp310-cp310-win_amd64.whl", hash = "sha256:a1532ea3f41a818d4f50db96306a1975bf31f29787802bec4c63c58f61b6e682"}, + {file = "aiohttp-3.12.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ed4db015494a6d0acaadce035531f9fb321afab2075a4b348811e4f7795e87e6"}, + {file = "aiohttp-3.12.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:59e19517abef2af49cff79b8a863497036ff401051c79d6a3b6149a48213a7be"}, + {file = "aiohttp-3.12.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d557918fefb29884335e1a257df6c961f35ba1caf8eddaabad762b3436cf87ff"}, + {file = "aiohttp-3.12.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e4fb0d7f221c36ed8469c1d2d9a2bb6a27b543cf90aa46ca701f63fb83dd7ed"}, + {file = "aiohttp-3.12.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:deddf6b1c83ce518a156b7597a0d7a1a7ec5c1d2c973ba3f1a23f18fa2b7d65e"}, + {file = "aiohttp-3.12.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eefd98dd043c33c45123c56a79c6c39acb628304337c90f16f33569cc3aa4ba6"}, + {file = "aiohttp-3.12.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efbbde2297e4ab10d187103aba9b565277c85ac7d24d98cae201c033ce885504"}, + {file = "aiohttp-3.12.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a74a566872f41247774980334e5b0309dac11b402e188bde6db8a57de4506cd"}, + {file = "aiohttp-3.12.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24d19cbd1d21d207ee855500d2033f1852b4d2113a741246ff62eb16a3921306"}, + {file = "aiohttp-3.12.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:86fb0a5762f936606dcab1ca248f5053587a598ed44825f4744ce3c53ae9a2e9"}, + {file = "aiohttp-3.12.6-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:d7ff55a38fc9851fa5cff41b30605534dfe4d57d02f79447abfed01499fe31d3"}, + {file = "aiohttp-3.12.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:545f89c389a47bac024655b5676658f35f80b0d007e4c3c7ff865d9aa3bf343a"}, + {file = "aiohttp-3.12.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:25dac87ee297e2b5826ce8e96c7615ebe7a1613856b1614a207e3376b776021b"}, + {file = "aiohttp-3.12.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c1d8a4a5a7e28d8b9ec815ffecca8712b71130a4eee1c5b45e9f2cc4975f3f7c"}, + {file = "aiohttp-3.12.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bc4be1d8d68a62859f74f9ada9e174791895366601ce66342f54478d3518c8b3"}, + {file = "aiohttp-3.12.6-cp311-cp311-win32.whl", hash = "sha256:a057680218430231eb6ab644d166b7ef398b3ffbac0232f4f789cdce9391400e"}, + {file = "aiohttp-3.12.6-cp311-cp311-win_amd64.whl", hash = "sha256:8a88046a5adddf5d99f15a1920f6b8f659f46a4cfb5bfabbd668d06df045df7a"}, + {file = "aiohttp-3.12.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:cfbf8ed94b57e3b5a886bfe2a530c8eb067064cc4419fd94431a2cbeeddec54c"}, + {file = "aiohttp-3.12.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:012ea107092d4465aeeb681d5b2fb8b51a847a72f0b71906f40876419fba1355"}, + {file = "aiohttp-3.12.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cdb03da5ecf74a331511604f3cf91563bf29127eabb28f4e16d390a73cb826da"}, + {file = "aiohttp-3.12.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ca81cb1e41d251cc193164409c0bbb0175e696a9997491a10db9171a2f70603"}, + {file = "aiohttp-3.12.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:15817882d25e840aba85d1f5706a7128350b81050f8ca9dabfc25a5f521a792c"}, + {file = "aiohttp-3.12.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db5c402ea0aed10af2e54e5946bf32f3ebb02a7604eaaa4c41a608053889de4a"}, + {file = "aiohttp-3.12.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ea77675818fd8cac28491d0d59582e5e2e5b14dbf5e21bef797aa5b23b5ca8b"}, + {file = "aiohttp-3.12.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c232720190ca4240c15abefc7b765e987ef88df44d2384612890db87b33898f3"}, + {file = "aiohttp-3.12.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a2f3c974874bd0c76dfdcc60db5a6f96ca023a85318a5ac401603baa7e299272"}, + {file = "aiohttp-3.12.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:25de52753386b0c16d5acd2153e7819f52c9e7fc05f5eca804adc174e99b735d"}, + {file = "aiohttp-3.12.6-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3cc06a99e065ed7e766d2cd574671428261c1b8f30fedfbd91ab3c738fd9c08d"}, + {file = "aiohttp-3.12.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aac87d78f55057ab48ddcc43055620546d40bbc0888d2658d8705d183c98f901"}, + {file = "aiohttp-3.12.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:de83f567e31418fd7bc22c5a03526a2b0a82e68c7a7fec23ef91a398228f559b"}, + {file = "aiohttp-3.12.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fd1d6116c1364ab00ffed1654a01091dc7f897d315c5103bcc6e5ab7f70172c7"}, + {file = "aiohttp-3.12.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:58f79b376a426961418df1d08656ec3a01494b7ba81824ae629e6636deddfff7"}, + {file = "aiohttp-3.12.6-cp312-cp312-win32.whl", hash = "sha256:561f545dc062e6c31fc53535d8584c06516bda2fc37821a67a61b69202061e71"}, + {file = "aiohttp-3.12.6-cp312-cp312-win_amd64.whl", hash = "sha256:d83ab494eb583ba691af9d4d7c073987526bb9f73aa5a19907258ef3a1e39e8a"}, + {file = "aiohttp-3.12.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7487f707a4b8167394f6afefa690198300d8a618505583eb536b92202bdec24d"}, + {file = "aiohttp-3.12.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9dd9211229fa2f474da01d42fafff196f607a63aaf12d8b34928c43a713eb6d5"}, + {file = "aiohttp-3.12.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3331ef09dd775302aa5f4d3170bd46659ad018843fab3656f5e72e3ff68df21f"}, + {file = "aiohttp-3.12.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c88ed8c54f7fd6102ef711d24710454707cde4bb3ffdec09982dcb3cb966a3e1"}, + {file = "aiohttp-3.12.6-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:148ffa6b2b825ff8520844ce23df9e2a5b969bb6917c4e35a832fbaa025d260d"}, + {file = "aiohttp-3.12.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8da054804352e974f4349fb871b07c8ffa1978e64cfb455e88fbe6fbe4d6dcb"}, + {file = "aiohttp-3.12.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d162c4f87f9dcdc7151f6329438de96beb527820381e3159ce08544c57e9ced"}, + {file = "aiohttp-3.12.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da073f88270aa434ef16a78c21a4269c96c68badc2b9ad5011fa175c06143eee"}, + {file = "aiohttp-3.12.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2e026a9f9ac0df70f14ca5dcaf1f83a55b678e51aa6515d710dd879d2691fd7"}, + {file = "aiohttp-3.12.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5b700cf48fd04b4328965d1afe01f835fe6cdecc3b85ca2d950431e5cc0647f7"}, + {file = "aiohttp-3.12.6-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:38af291559401d13eb90259ba79ef6ac537ae6b5bdb1251604606a88cd0fd5e0"}, + {file = "aiohttp-3.12.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6860351cfba0196db2edc387cfeddaf1dae443e55f261ea2bcb77fecb33aae34"}, + {file = "aiohttp-3.12.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:06f20adcdc4f383aeb7ce884705faea44c0376cde5cdee4d32ef62d6cb1f97cc"}, + {file = "aiohttp-3.12.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:a52aa39eb1160775a6e80e3025c990e8872c8927c5dd4b51304788bc149b9549"}, + {file = "aiohttp-3.12.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:52ce7e90ee9dd25bcd2ed4513e650cc4f9a03bef07a39193b82fb58892004bd6"}, + {file = "aiohttp-3.12.6-cp313-cp313-win32.whl", hash = "sha256:259269870d9783de87c0430760b2498b770201ead3e11ee86761d268ce5d196a"}, + {file = "aiohttp-3.12.6-cp313-cp313-win_amd64.whl", hash = "sha256:938afd243c9ee76a6d78fad10ecca14b88b48b71553e0e9c74b8098efff5ddf8"}, + {file = "aiohttp-3.12.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3a0fd1f91535f64ac726a9203a2ca12e19ab7232a8e3ed070d4a952f64a7f3b8"}, + {file = "aiohttp-3.12.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ad8c000bf876f09bebdbb6122d0b83ed2047d808144dcda844b973f91a62239b"}, + {file = "aiohttp-3.12.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d10dbce6ad5fd5a635021e44696f98e6f535675c515f3ec5143a1d6b94e97c75"}, + {file = "aiohttp-3.12.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0673bdc2914fed2651837e9ce45639cf09d342850274fa0d955d15f148082ab5"}, + {file = "aiohttp-3.12.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7e839f36ff048eef10034d25a4b699e0b363b16d3951c8ef2f1b3cea9e2bf859"}, + {file = "aiohttp-3.12.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9220418982f90e5b293e36fe356f4df6953da8539b54b9ae5a9a17e8f227463c"}, + {file = "aiohttp-3.12.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:faf7c0224423106c5e0a4897c668c6cef2ca9b588295993d83d8c3e69772c7f0"}, + {file = "aiohttp-3.12.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61ed8371a645b89008910b3c7ce286ec5f19b4d67adaa15ed21e4a8fe1adedca"}, + {file = "aiohttp-3.12.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8b0dee7a763ce483c459fc2d963350d10e692e863dac985357e2eb7e7e74985f"}, + {file = "aiohttp-3.12.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e1d66b091e707a1e296ccd00903bed4f270579c5b8000a9e5861ae9a33dc250d"}, + {file = "aiohttp-3.12.6-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:41c73154bba1c8fe80ef329fee5602bc6a1992740735637f1f05112b15e1cd97"}, + {file = "aiohttp-3.12.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:7d34f87dd26a686097675fdc43c3b60174b8d6f0ae383d128648fb30535097e5"}, + {file = "aiohttp-3.12.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ef1e34409fe412825cde39be93efbe1f52d9e5c00a21abe95969c5e595595ebd"}, + {file = "aiohttp-3.12.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:29eb0a7d64eb2cf17c436cdf0b9d1b17931551a5c089fa2c63410848a9cd029d"}, + {file = "aiohttp-3.12.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2cd7c7018cee1638fc64cbdceb47c870985ce5650161c7e3c5b578850f74b113"}, + {file = "aiohttp-3.12.6-cp39-cp39-win32.whl", hash = "sha256:79ab680ff7dd0b6c36073738b5f6336e2f018fc07ef0486dd7dd68b2e888ce46"}, + {file = "aiohttp-3.12.6-cp39-cp39-win_amd64.whl", hash = "sha256:a68cb45d2b01f1599e762d382ddac7c6bd62c95210db339827e973a7ba61673c"}, + {file = "aiohttp-3.12.6.tar.gz", hash = "sha256:37b1c6034a1e14764adad1829cd710543b1699d7985e1d336f0aa52a2dd76ba9"}, ] [package.dependencies] +aiohappyeyeballs = ">=2.5.0" aiosignal = ">=1.1.2" -async-timeout = ">=4.0.0a3,<5.0" +async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" -charset-normalizer = ">=2.0,<4.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" +propcache = ">=0.2.0" +yarl = ">=1.17.0,<2.0" [package.extras] -speedups = ["Brotli", "aiodns", "cchardet"] +speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.3.0)", "brotlicffi ; platform_python_implementation != \"CPython\""] [[package]] name = "aiosignal" -version = "1.3.1" +version = "1.3.2" description = "aiosignal: a list of registered asynchronous callbacks" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, + {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, + {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, ] [package.dependencies] @@ -128,6 +142,7 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -135,164 +150,203 @@ files = [ [[package]] name = "async-timeout" -version = "4.0.3" +version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\"" files = [ - {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, - {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, + {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, + {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, ] [[package]] name = "attrs" -version = "23.1.0" +version = "25.3.0" description = "Classes Without Boilerplate" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, + {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, + {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, ] [package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] [[package]] name = "bitarray" -version = "2.8.1" +version = "3.4.2" description = "efficient arrays of booleans -- C extension" optional = false python-versions = "*" +groups = ["main"] files = [ - {file = "bitarray-2.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6be965028785413a6163dd55a639b898b22f67f9b6ed554081c23e94a602031e"}, - {file = "bitarray-2.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29e19cb80a69f6d1a64097bfbe1766c418e1a785d901b583ef0328ea10a30399"}, - {file = "bitarray-2.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0f6d705860f59721d7282496a4d29b5fd78690e1c1473503832c983e762b01b"}, - {file = "bitarray-2.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6df04efdba4e1bf9d93a1735e42005f8fcf812caf40c03934d9322412d563499"}, - {file = "bitarray-2.8.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18530ed3ddd71e9ff95440afce531efc3df7a3e0657f1c201c2c3cb41dd65869"}, - {file = "bitarray-2.8.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4cd81ffd2d58ef68c22c825aff89f4a47bd721e2ada0a3a96793169f370ae21"}, - {file = "bitarray-2.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8367768ab797105eb97dfbd4577fcde281618de4d8d3b16ad62c477bb065f347"}, - {file = "bitarray-2.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:848af80518d0ed2aee782018588c7c88805f51b01271935df5b256c8d81c726e"}, - {file = "bitarray-2.8.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c54b0af16be45de534af9d77e8a180126cd059f72db8b6550f62dda233868942"}, - {file = "bitarray-2.8.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f30cdce22af3dc7c73e70af391bfd87c4574cc40c74d651919e20efc26e014b5"}, - {file = "bitarray-2.8.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bc03bb358ae3917247d257207c79162e666d407ac473718d1b95316dac94162b"}, - {file = "bitarray-2.8.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:cf38871ed4cd89df9db7c70f729b948fa3e2848a07c69f78e4ddfbe4f23db63c"}, - {file = "bitarray-2.8.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a637bcd199c1366c65b98f18884f0d0b87403f04676b21e4635831660d722a7"}, - {file = "bitarray-2.8.1-cp310-cp310-win32.whl", hash = "sha256:904719fb7304d4115228b63c178f0cc725ad3b73e285c4b328e45a99a8e3fad6"}, - {file = "bitarray-2.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:1e859c664500d57526fe07140889a3b58dca54ff3b16ac6dc6d534a65c933084"}, - {file = "bitarray-2.8.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2d3f28a80f2e6bb96e9360a4baf3fbacb696b5aba06a14c18a15488d4b6f398f"}, - {file = "bitarray-2.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4677477a406f2a9e064920463f69172b865e4d69117e1f2160064d3f5912b0bd"}, - {file = "bitarray-2.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9061c0a50216f24c97fb2325de84200e5ad5555f25c854ddcb3ceb6f12136055"}, - {file = "bitarray-2.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:843af12991161b358b6379a8dc5f6636798f3dacdae182d30995b6a2df3b263e"}, - {file = "bitarray-2.8.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9336300fd0acf07ede92e424930176dc4b43ef1b298489e93ba9a1695e8ea752"}, - {file = "bitarray-2.8.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0af01e1f61fe627f63648c0c6f52de8eac56710a2ef1dbce4851d867084cc7e"}, - {file = "bitarray-2.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ab81c74a1805fe74330859b38e70d7525cdd80953461b59c06660046afaffcf"}, - {file = "bitarray-2.8.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2015a9dd718393e814ff7b9e80c58190eb1cef7980f86a97a33e8440e158ce2"}, - {file = "bitarray-2.8.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b0493ab66c6b8e17e9fde74c646b39ee09c236cf28a787cb8cbd3a83c05bff7"}, - {file = "bitarray-2.8.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:81e83ed7e0b1c09c5a33b97712da89e7a21fd3e5598eff3975c39540f5619792"}, - {file = "bitarray-2.8.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:741c3a2c0997c8f8878edfc65a4a8f7aa72eede337c9bc0b7bd8a45cf6e70dbc"}, - {file = "bitarray-2.8.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:57aeab27120a8a50917845bb81b0976e33d4759f2156b01359e2b43d445f5127"}, - {file = "bitarray-2.8.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:17c32ba584e8fb9322419390e0e248769ed7d59de3ffa7432562a4c0ec4f1f82"}, - {file = "bitarray-2.8.1-cp311-cp311-win32.whl", hash = "sha256:b67733a240a96f09b7597af97ac4d60c59140cfcfd180f11a7221863b82f023a"}, - {file = "bitarray-2.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:7b29d4bf3d3da1847f2be9e30105bf51caaf5922e94dc827653e250ed33f4e8a"}, - {file = "bitarray-2.8.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:5f6175c1cf07dadad3213d60075704cf2e2f1232975cfd4ac8328c24a05e8f78"}, - {file = "bitarray-2.8.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cc066c7290151600b8872865708d2d00fb785c5db8a0df20d70d518e02f172b"}, - {file = "bitarray-2.8.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ce2ef9291a193a0e0cd5e23970bf3b682cc8b95220561d05b775b8d616d665f"}, - {file = "bitarray-2.8.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c5582dd7d906e6f9ec1704f99d56d812f7d395d28c02262bc8b50834d51250c3"}, - {file = "bitarray-2.8.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2aa2267eb6d2b88ef7d139e79a6daaa84cd54d241b9797478f10dcb95a9cd620"}, - {file = "bitarray-2.8.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a04d4851e83730f03c4a6aac568c7d8b42f78f0f9cc8231d6db66192b030ce1e"}, - {file = "bitarray-2.8.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f7d2ec2174d503cbb092f8353527842633c530b4e03b9922411640ac9c018a19"}, - {file = "bitarray-2.8.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:b65a04b2e029b0694b52d60786732afd15b1ec6517de61a36afbb7808a2ffac1"}, - {file = "bitarray-2.8.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:55020d6fb9b72bd3606969f5431386c592ed3666133bd475af945aa0fa9e84ec"}, - {file = "bitarray-2.8.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:797de3465f5f6c6be9a412b4e99eb6e8cdb86b83b6756655c4d83a65d0b9a376"}, - {file = "bitarray-2.8.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:f9a66745682e175e143a180524a63e692acb2b8c86941073f6dd4ee906e69608"}, - {file = "bitarray-2.8.1-cp36-cp36m-win32.whl", hash = "sha256:443726af4bd60515e4e41ea36c5dbadb29a59bc799bcbf431011d1c6fd4363e3"}, - {file = "bitarray-2.8.1-cp36-cp36m-win_amd64.whl", hash = "sha256:2b0f754a5791635b8239abdcc0258378111b8ee7a8eb3e2bbc24bcc48a0f0b08"}, - {file = "bitarray-2.8.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d175e16419a52d54c0ac44c93309ba76dc2cfd33ee9d20624f1a5eb86b8e162e"}, - {file = "bitarray-2.8.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3128234bde3629ab301a501950587e847d30031a9cbf04d95f35cbf44469a9e"}, - {file = "bitarray-2.8.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:75104c3076676708c1ac2484ebf5c26464fb3850312de33a5b5bf61bfa7dbec5"}, - {file = "bitarray-2.8.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82bfb6ab9b1b5451a5483c9a2ae2a8f83799d7503b384b54f6ab56ea74abb305"}, - {file = "bitarray-2.8.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dc064a63445366f6b26eaf77230d326b9463e903ba59d6ff5efde0c5ec1ea0e"}, - {file = "bitarray-2.8.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cbe54685cf6b17b3e15faf6c4b76773bc1c484bc447020737d2550a9dde5f6e6"}, - {file = "bitarray-2.8.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9fed8aba8d1b09cf641b50f1e6dd079c31677106ea4b63ec29f4c49adfabd63f"}, - {file = "bitarray-2.8.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7c17dd8fb146c2c680bf1cb28b358f9e52a14076e44141c5442148863ee95d7d"}, - {file = "bitarray-2.8.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:c9efcee311d9ba0c619743060585af9a9b81496e97b945843d5e954c67722a75"}, - {file = "bitarray-2.8.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dc7acffee09822b334d1b46cd384e969804abdf18f892c82c05c2328066cd2ae"}, - {file = "bitarray-2.8.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ea71e0a50060f96ad0821e0ac785e91e44807f8b69555970979d81934961d5bd"}, - {file = "bitarray-2.8.1-cp37-cp37m-win32.whl", hash = "sha256:69ab51d551d50e4d6ca35abc95c9d04b33ad28418019bb5481ab09bdbc0df15c"}, - {file = "bitarray-2.8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:3024ab4c4906c3681408ca17c35833237d18813ebb9f24ae9f9e3157a4a66939"}, - {file = "bitarray-2.8.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:46fdd27c8fa4186d8b290bf74a28cbd91b94127b1b6a35c265a002e394fa9324"}, - {file = "bitarray-2.8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d32ccd2c0d906eae103ef84015f0545a395052b0b6eb0e02e9023ca0132557f6"}, - {file = "bitarray-2.8.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9186cf8135ca170cd907d8c4df408a87747570d192d89ec4ff23805611c702a0"}, - {file = "bitarray-2.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8d6e5ff385fea25caf26fd58b43f087deb763dcaddd18d3df2895235cf1b484"}, - {file = "bitarray-2.8.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d6a9c72354327c7aa9890ff87904cbe86830cb1fb58c39750a0afac8df5e051"}, - {file = "bitarray-2.8.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2f13b7d0694ce2024c82fc595e6ccc3918e7f069747c3de41b1ce72a9a1e346"}, - {file = "bitarray-2.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d38ceca90ed538706e3f111513073590f723f90659a7af0b992b29776a6e816"}, - {file = "bitarray-2.8.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b977c39e3734e73540a2e3a71501c2c6261c70c6ce59d427bb7c4ecf6331c7e"}, - {file = "bitarray-2.8.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:214c05a7642040f6174e29f3e099549d3c40ac44616405081bf230dcafb38767"}, - {file = "bitarray-2.8.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ad440c17ef2ff42e94286186b5bcf82bf87c4026f91822675239102ebe1f7035"}, - {file = "bitarray-2.8.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:28dee92edd0d21655e56e1870c22468d0dabe557df18aa69f6d06b1543614180"}, - {file = "bitarray-2.8.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:df9d8a9a46c46950f306394705512553c552b633f8bf3c11359c4204289f11e3"}, - {file = "bitarray-2.8.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1a0d27aad02d8abcb1d3b7d85f463877c4937e71adf9b6adb9367f2cdad91a52"}, - {file = "bitarray-2.8.1-cp38-cp38-win32.whl", hash = "sha256:6033303431a7c85a535b3f1b0ec28abc2ebc2167c263f244993b56ccb87cae6b"}, - {file = "bitarray-2.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:9b65d487451e0e287565c8436cf4da45260f958f911299f6122a20d7ec76525c"}, - {file = "bitarray-2.8.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9aad7b4670f090734b272c072c9db375c63bd503512be9a9393e657dcacfc7e2"}, - {file = "bitarray-2.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bf80804014e3736515b84044c2be0e70080616b4ceddd4e38d85f3167aeb8165"}, - {file = "bitarray-2.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7f7231ef349e8f4955d9b39561f4683a418a73443cfce797a4eddbee1ba9664"}, - {file = "bitarray-2.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67e8fb18df51e649adbc81359e1db0f202d72708fba61b06f5ac8db47c08d107"}, - {file = "bitarray-2.8.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d5df3d6358425c9dfb6bdbd4f576563ec4173d24693a9042d05aadcb23c0b98"}, - {file = "bitarray-2.8.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ea51ba4204d086d5b76e84c31d2acbb355ed1b075ded54eb9b7070b0b95415d"}, - {file = "bitarray-2.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1414582b3b7516d2282433f0914dd9846389b051b2aea592ae7cc165806c24ac"}, - {file = "bitarray-2.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5934e3a623a1d485e1dcfc1990246e3c32c6fc6e7f0fd894750800d35fdb5794"}, - {file = "bitarray-2.8.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aa08a9b03888c768b9b2383949a942804d50d8164683b39fe62f0bfbfd9b4204"}, - {file = "bitarray-2.8.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:00ff372dfaced7dd6cc2dffd052fafc118053cf81a442992b9a23367479d77d7"}, - {file = "bitarray-2.8.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:dd76bbf5a4b2ab84b8ffa229f5648e80038ba76bf8d7acc5de9dd06031b38117"}, - {file = "bitarray-2.8.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e88a706f92ad1e0e1e66f6811d10b6155d5f18f0de9356ee899a7966a4e41992"}, - {file = "bitarray-2.8.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b2560475c5a1ff96fcab01fae7cf6b9a6da590f02659556b7fccc7991e401884"}, - {file = "bitarray-2.8.1-cp39-cp39-win32.whl", hash = "sha256:74cd1725d08325b6669e6e9a5d09cec29e7c41f7d58e082286af5387414d046d"}, - {file = "bitarray-2.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:e48c45ea7944225bcee026c457a70eaea61db3659d9603f07fc8a643ab7e633b"}, - {file = "bitarray-2.8.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c2426dc7a0d92d8254def20ab7a231626397ce5b6fb3d4f44be74cc1370a60c3"}, - {file = "bitarray-2.8.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d34790a919f165b6f537935280ef5224957d9ce8ab11d339f5e6d0319a683ccc"}, - {file = "bitarray-2.8.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c26a923080bc211cab8f5a5e242e3657b32951fec8980db0616e9239aade482"}, - {file = "bitarray-2.8.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de1bc5f971aba46de88a4eb0dbb5779e30bbd7514f4dcbff743c209e0c02667"}, - {file = "bitarray-2.8.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3bb5f2954dd897b0bac13b5449e5c977534595b688120c8af054657a08b01f46"}, - {file = "bitarray-2.8.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:62ac31059a3c510ef64ed93d930581b262fd4592e6d95ede79fca91e8d3d3ef6"}, - {file = "bitarray-2.8.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae32ac7217e83646b9f64d7090bf7b737afaa569665621f110a05d9738ca841a"}, - {file = "bitarray-2.8.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3994f7dc48d21af40c0d69fca57d8040b02953f4c7c3652c2341d8947e9cbedf"}, - {file = "bitarray-2.8.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c361201e1c3ee6d6b2266f8b7a645389880bccab1b29e22e7a6b7b6e7831ad5"}, - {file = "bitarray-2.8.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:861850d6a58e7b6a7096d0b0efed9c6d993a6ab8b9d01e781df1f4d80cc00efa"}, - {file = "bitarray-2.8.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ee772c20dcb56b03d666a4e4383d0b5b942b0ccc27815e42fe0737b34cba2082"}, - {file = "bitarray-2.8.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63fa75e87ad8c57d5722cc87902ca148ef8bbbba12b5c5b3c3730a1bc9ac2886"}, - {file = "bitarray-2.8.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b999fb66980f885961d197d97d7ff5a13b7ab524ccf45ccb4704f4b82ce02e3"}, - {file = "bitarray-2.8.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3243e4b8279ff2fe4c6e7869f0e6930c17799ee9f8d07317f68d44a66b46281e"}, - {file = "bitarray-2.8.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:542358b178b025dcc95e7fb83389e9954f701c41d312cbb66bdd763cbe5414b5"}, - {file = "bitarray-2.8.1.tar.gz", hash = "sha256:e68ceef35a88625d16169550768fcc8d3894913e363c24ecbf6b8c07eb02c8f3"}, + {file = "bitarray-3.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:42b552f885c5629182928c79237b375a92bcf1bc1e725b1c8a5e8eab28ea300d"}, + {file = "bitarray-3.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3e16d6184f349587b6a5045bcf073baf763a86273aab454485ba437d0bca82e8"}, + {file = "bitarray-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ecf456f0dee61bd818011e290d922e3e3b1aeb0544f6f19c4da9c5fc2e52818"}, + {file = "bitarray-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8bbe8249ae90dc0cd78b21d5d5d27a614e15bf30737ae6e8a0e2e60cc492acc"}, + {file = "bitarray-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe7706f75f3b86e7afa516452bed9757ee301b59aea580c551c32a5e1cef082c"}, + {file = "bitarray-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c60c8d30bb6efd2c04cf82d077df6449964234aeca996f6f1df317a08feffc0"}, + {file = "bitarray-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b4cb5c22706d411010c7ce5efc0a4cc99f755a30fc7f6770eb1b1a0c0962bbb"}, + {file = "bitarray-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0fd60137a9474ce53bdace68c718a7c538f9df01d390452cc984f1ee78d7bcdb"}, + {file = "bitarray-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:cd514a8e27d0751f0254861df60335edabacccfcb2457793ff30c8b2ed8f799d"}, + {file = "bitarray-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6c8f7447cdf2faff1d176c5dd207f0134f05cfa2a238d3d3944dc5019dc41593"}, + {file = "bitarray-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:75040a2a1abe4ccd40236f4ba0d39abde981d23f3ce7691b3b3f2137f134b99b"}, + {file = "bitarray-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ba15725cd9040b9b1b2650edb33253cb2ba7b68d087974e296e5ff082198952f"}, + {file = "bitarray-3.4.2-cp310-cp310-win32.whl", hash = "sha256:2959dfc61d963546e97220cfcaab7dfc489276c6e00092b57710522e68712b28"}, + {file = "bitarray-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:97077fa0ec3b7eed57cd8d1cb0eb75d670423d20b7e4901482347a81efe2f6fd"}, + {file = "bitarray-3.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90ca8e260b75a7ac0c542093e5f29154e51fd0d2d0fa5041c038cb2b58415eeb"}, + {file = "bitarray-3.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549dabcae78fb8f9133e3138b9473c7648d6054bb6fec84d28d3861aaec5ddd1"}, + {file = "bitarray-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a3da536ac84e6911cbc8e86be0baf1cab0d4f4ccb80c0f39b4fa28509f2db1a"}, + {file = "bitarray-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7a5e84d6b737de2d773ab1bd538e6f37fa7f667ea734f00a48d9a973b181c751"}, + {file = "bitarray-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e265c5eede8316ba64bb6029832f282f6284a557b625bb3207a7680fd5da7925"}, + {file = "bitarray-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63fb45c60c7ab7a724aa64203305e56f344489e12d41619bdc9d7887d6562e01"}, + {file = "bitarray-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:083c2a9234dacf3e4e166a5844256da2a397941d3f6397e5b919bffca638f6ef"}, + {file = "bitarray-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e72606adb2438002873cb0e8e81c3fce926386a59bbafa82fea07cdb2a6d8a05"}, + {file = "bitarray-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dc994d22a3a563e1d402dc2f64c61e60605a1a3e66dd8aea7636f607b99f03cb"}, + {file = "bitarray-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:214468391680ba1c831872a7949f1b563ab3cd832d10adc52df4f36e0af24446"}, + {file = "bitarray-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c7483b97807bb018a7cd7f9741800c714c9c56ba4e5a7e962c5f956c4b858f3c"}, + {file = "bitarray-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5774bf14ec451d5ac311cfcfe0b0cf2a1a9fa74b6ca81dfbc4f56a98872a5541"}, + {file = "bitarray-3.4.2-cp311-cp311-win32.whl", hash = "sha256:e6f35567347ddb8b9e8b6bf6ab7d64be88bdb6b6c107b8edbb2c3d426c1590a0"}, + {file = "bitarray-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:ae5b0a8d3caf6284220232738dc7c05af81ec3a9f93d4a462295462dd0a492b2"}, + {file = "bitarray-3.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a0e498563e0eefa96a1b92461d083de11256f6510b7706d5f2e6473cd9b7137a"}, + {file = "bitarray-3.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:114870ab71a0ebdac211aa0a120a54206c333b74b99fdf4b58fbe904979e1fef"}, + {file = "bitarray-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fbf6121978cba4313c31f7cc5961e481242def2b8ddfea34ca27ba9da52c9c1"}, + {file = "bitarray-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:423bb4e1bec0bc5d63969e12bcc5cc0081cc5aec4d7b62a6cd8240342aa36107"}, + {file = "bitarray-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ef80a96487c82477e8def69a58a218491794f7989b3e191cbaaa7b450315a5c"}, + {file = "bitarray-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35f5c69a79047e50bc1d54a777541b0a86b213e23559b1ac3d76fa9a42cc5522"}, + {file = "bitarray-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:002f7b128ed9d18d3ecb51ca78aeea5afffbe8e80d6be4ff2984d045b1c4b937"}, + {file = "bitarray-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:999bccc72704afcf4a3d9868db4d149c032cdf910f9f7d91e30166978530af7f"}, + {file = "bitarray-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2e44cfe2bc161cde3b11604f279e3048ef7bd3413837aadbd2ca30b5233c82cb"}, + {file = "bitarray-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f408ba3e6f706a0eabae405d1906ceb539f34a318562a91ab9799c5e1712e18c"}, + {file = "bitarray-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bf94513ae559b2525e6218e41b03790f866d75df5404490420f2c25e42cf55e7"}, + {file = "bitarray-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f2c88c792815d2755c49a3a1fca256e142c4adfadf1a2142b5a3a37e4d4b871"}, + {file = "bitarray-3.4.2-cp312-cp312-win32.whl", hash = "sha256:f4dac6b942c4d7ae5f6eb555ee3993de1432bf9c8f46e3caf74b6671ac5571a3"}, + {file = "bitarray-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:6c37e6814633041307f0df281651a86372b0ccdb1e4768247a87e83e2b68f9b9"}, + {file = "bitarray-3.4.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:16263bdbb05ce379e7b8e9a9f3e0a61a9204a06a037bbc91322d2939b3079fd5"}, + {file = "bitarray-3.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:41fdc6fb8c3aabfcfe0073302c69fef0c74d6499491f133ba58755c3f2afb3d0"}, + {file = "bitarray-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c2571337b11c69206e339170516f3e72b4ec16250876c4f2bbb6e82b9caa15"}, + {file = "bitarray-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c0e3d5f37217dde9b206418c37c4d86e173f072a892670e9714e6bb20b228e95"}, + {file = "bitarray-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83202735f21fc781f27228daeae94b6c7df1a9f673b9dd6a1c0b3764d92b8e50"}, + {file = "bitarray-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53b3f8c35812d85a299d6c0ff097f93e18dfb7a324c129e20a4ec0ecfc4ba995"}, + {file = "bitarray-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3f2e8ba5d6e0f38b57960d1bfb72aa9e2115f7cdca48561fadced652798d49"}, + {file = "bitarray-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:508ec6547bdd9f0c435c322fbb127a3dfd74c943a6c7f77fa5dfcb3e9ce1de66"}, + {file = "bitarray-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1a3a08cc920f601258ea33d97b4454cd7cb04d17930e0a3bc7328ba3d732f8b0"}, + {file = "bitarray-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:60189130ae1ebaadbab27e3ad0a7d7ed44f5d9456bbfae07c72138501ce59053"}, + {file = "bitarray-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9e425eaf21a8d7b76531630029441c6d61f6064cbf4dd592af1607c79eb2e4d0"}, + {file = "bitarray-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:952cc40c593f663ba083be76d1ccdb6dc9dafab8fb6d949056405636b2e720f3"}, + {file = "bitarray-3.4.2-cp313-cp313-win32.whl", hash = "sha256:158f6b1a315eaf971f88e66f9b93431c3b580b46d2121c6a1166e7b761408fdf"}, + {file = "bitarray-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:2d24658ac96a82beb4da2f5c71bef9790f3dcabadbe8ead8dda742ab207fe2f9"}, + {file = "bitarray-3.4.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3098722521db7dcc716ffdccb26655dd12884febbf3ed479b430f46c2d81a7ce"}, + {file = "bitarray-3.4.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be4c18bcd4146891f9f5758eadddd20c32dff8defa1ceba0114245393c7ce17"}, + {file = "bitarray-3.4.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66dabfaf151a107d51e5b7f0e78cf015f8f90102b64504100aca6f876e64d83d"}, + {file = "bitarray-3.4.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dc827b7fd1c754afc9a05cfd6c506577c1383ca39e2a338d0c9137edf74fa64"}, + {file = "bitarray-3.4.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b816e1ad8f0c4717265b0b22806807be085ed4a3b3a1314228f45c0321efcdfe"}, + {file = "bitarray-3.4.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:708e586b5b6688038e5ecd44cd39381eb360917e1fb78a75efbd1fdc259cbe62"}, + {file = "bitarray-3.4.2-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:46f487ec9d8d3c43a40e4fcafb8f731bc825707326bb7d2a9223d957541b176c"}, + {file = "bitarray-3.4.2-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:fc30c3879ffe626ad44bc41c88f42a67ba66680b9649ddccc9adf74034ddaf20"}, + {file = "bitarray-3.4.2-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:a6063e803212802d52aa7a384d001f9008ff407a2eca5a380b48883e012e5615"}, + {file = "bitarray-3.4.2-cp36-cp36m-musllinux_1_2_s390x.whl", hash = "sha256:8d64c1f94f0a2f02d056466da67e60ecf66ba0c9e9237eff67d68742b9509f80"}, + {file = "bitarray-3.4.2-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:79f3bd0cfb1950585dabb528a3402c92f6ce6955302fb13334373621b5873fc2"}, + {file = "bitarray-3.4.2-cp36-cp36m-win32.whl", hash = "sha256:863ada3e0531f79b39659ca6178cbe29afae1df0085cd4cf35b7f5d8f35468fe"}, + {file = "bitarray-3.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:b52ea280392650da7fadd991bdcb9a914cc885e771fdb16f3e5a3b8ab28cda73"}, + {file = "bitarray-3.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:86c507024d8307a19f747c450766294efdfb212a29ef142ccc33b986e91cc14f"}, + {file = "bitarray-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c20cd30c8ee0a30f13d9755ddbedf4387d25dd3fcaad923c51a09a091052990d"}, + {file = "bitarray-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d49e54b6c7778b9b500ed6e2e05cfa9c4983a624b99e7ef9c12d9fd3a1274990"}, + {file = "bitarray-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4454881de8a4b417fe704adab7983dfb8b9c9b97d26d10deb1a8c5e95ac9150"}, + {file = "bitarray-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bbb179d981fd05631c4068a56327541978378f82b5b3d82a571e1f3e459c46"}, + {file = "bitarray-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:783e19b7c0b58afc54d416fea1c0527e1d6afc7af98700c0032f4b3e199f4fb0"}, + {file = "bitarray-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:c31ebf0311bd73ef2ecd2ad016f2c6c10e95801e82dfe7508b1f926b285daed4"}, + {file = "bitarray-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:0c997446bb42314bb7758edb51e39c99fdfa967ff48dcd11ec048e47517f0d5d"}, + {file = "bitarray-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:50893e03ee37d82dc81449a2cfcc959c58e2f1eb87b961d57c55744bd11f4c15"}, + {file = "bitarray-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:a89a3dd32dae555e1361d7c1ea3f30097f6d655f9a92ba592df173b44126bd73"}, + {file = "bitarray-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:8e0b0446a071e88283af3508613d65f58ac8e04ac40cb22de75eca4bb4a9665a"}, + {file = "bitarray-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:90d8fce4287da47a635f9e620e92f26916bacfb8edfa3cbb7a55bc50f5d3033a"}, + {file = "bitarray-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7c9fd487c7dc21e0112cbf8e689cd09ea68b3776b2de513a6517913182eb0cc1"}, + {file = "bitarray-3.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a9cc7b6dfc0b778e0ab4f6c602770b03d1238970bacc759046597499432e537d"}, + {file = "bitarray-3.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:df92619765e90c32c7f37e5a7437d22b7720b69543c3f7384cd8482ba76d9b1a"}, + {file = "bitarray-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebc9786ea35353324bb46c9c1ef44ab4f66f3c397ace9ed84c2c16ba191526ed"}, + {file = "bitarray-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e748c794960d811746ec7353f3f9056ffc0502fcf971836b4b6c6e20126b25b4"}, + {file = "bitarray-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b85e8f103f21ac3a725066f4abfb3ca27731c5cb2cb14087e0e014d4178f865d"}, + {file = "bitarray-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61f362d2a53f3fb237a0ab4581c22ed2b733c293d2b90dd9b90983636e8eb40d"}, + {file = "bitarray-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c69fc4325bdb40e9d71129fc3d869f18e7c5ec7cd9cf972a2270a32481de71e"}, + {file = "bitarray-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ac1b00a2c687f9fc45fd6bec63a4a2f01c11664ed6632cb8a91e5cf6e260503b"}, + {file = "bitarray-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:b24dabacfd56c55a861f14568b8654e984f31067aec4c4bb6b04d1af29c689c2"}, + {file = "bitarray-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc569c2c880a3c16ab0ed07d7b709f0c9af23568de8b5f599b934d4b639f9b1"}, + {file = "bitarray-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b2c4aa3a9134bbfb439bd48e805b2bf9a0873e56c1110f0c7bd0a9b0ee4f4ced"}, + {file = "bitarray-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b4d10c74b145f025ab37de6b503118d3f92718921595434f23e8280ff46ddaa8"}, + {file = "bitarray-3.4.2-cp38-cp38-win32.whl", hash = "sha256:cff080acfce06f304c87a73d77d286f792baaf61e6af34560788bb951365fb60"}, + {file = "bitarray-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:001d4005336ca2c8fdecbe2a278bc58e71b1f8ca8ce5c09f9c73482fa4ce065b"}, + {file = "bitarray-3.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:549c730e91b8b2a7b4502b573e333c77196bb163109c87ab19ddcd3196183c7f"}, + {file = "bitarray-3.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dd48009c478cf10f15238a808c0412e0f2b70ab8f2b753466d4f425974cbf6c6"}, + {file = "bitarray-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e0f3bb202db0235ff7698a288c7ee732a5b73736257da89af26f3975386ce02"}, + {file = "bitarray-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b2041a1f4087df044ad82f239e9bf253d9c3d21474078f496a07f26398084ea"}, + {file = "bitarray-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5211bb084b7c7b7087f8d5af0b67b283ea9519c7595d9b19ef1b52065e5853dd"}, + {file = "bitarray-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83e9df7d83ee4997e5fea3a356ba075b9112931375be97f307c9bc6344b10b8c"}, + {file = "bitarray-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c025f13e27a0596c4d3ff9e80c31b26bdda526959bbfecdb0989f3007ec4f56c"}, + {file = "bitarray-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d4359490ee83184911a35aa9959d7ce02e00d7c1208f300ccf946f161652e962"}, + {file = "bitarray-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:b7ec66b0735ee5b264b3c6adb3e05187f523b2c7f875a40dcd4c167b735c292d"}, + {file = "bitarray-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:829cd725444811eb57dd01679c245cdc994259f1ae9685298268e8267bc23637"}, + {file = "bitarray-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2b26ec3aa15163c5233dfaf67f76f9933d4e9273166830ca5f3cf3ec9d883767"}, + {file = "bitarray-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bcbe07cf0e863a98468ed2bbba674932a6eaa9fa4cbc716f9b0f0b267927b990"}, + {file = "bitarray-3.4.2-cp39-cp39-win32.whl", hash = "sha256:f1cc27aa74da3a0ec157a41fae07af34103dd5b337e92514eb9d3923d721e9d7"}, + {file = "bitarray-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:a7ffc3939371af5581e77a0529e1b90bdfb112f2d9c9e5cb065618a522ec4e77"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9c02f3234b1ec391aa235b265a3649e8078d814cdd6b42bc5aee267cc370b0c8"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:e19e5a35f53c0eaf4516cfa3f80de110eb831fd3d9785aa8b8f4a8a8c0d99523"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f633d1e92fdc6a039b118d67f23d17b9ac4046a629bde04e178b770fe83a618f"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c08bc2ec3f15fbb3a99923ef1b16b621af45ab9d5146a06f970c0f0d7cab22ba"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eed46fa39af8440b1cff09a9805d65449583d524006efa29e5262bea9e08787e"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9cf23c13c84c1559ed28bd211a6290b7326c2011f6c30c82cee052b254ac09f0"}, + {file = "bitarray-3.4.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e4dd654d6a789e23abc65cc8e193c309b0d304a74d343c4e7d18f3796e452c13"}, + {file = "bitarray-3.4.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:481e87458b4a855d905f5139fbf0717d701e9d3cbd9b9f7f033cd4af76a2a587"}, + {file = "bitarray-3.4.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6650077087b7d5953a70c46bbb9ac6004daf6d76d75f8bc10b776cfa1cd178c1"}, + {file = "bitarray-3.4.2-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ab5688d22d9e70ceac58b5ffde29bbd38767da0cea34c923cffdb2abf674a18"}, + {file = "bitarray-3.4.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6ff474b96cefcf55003eae55fd4af9df27e892008f689435a60b8d5b5c22824b"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:83850b34897be3eb13ea7a1148f92284e8f66e059c7bd3381915858b4264c16d"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:5fdbf326369a6d527be12946b19521e5a9cf9243d1a3f63510b06a848e30c424"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc4b304afc23bdeec34f3d442a5d1edcaa49fa33310dfdf1be4997d2b80947d1"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08e4a319ffc2973c4610c218fc0153d19a5866deafd0d0c87c6cbfa41add48a9"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:940c8cd97d109dd0696e6b4f6d140e37701b440a9c7ca50ef0a6f547d6b95812"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:0020522d3e865e3afd001fefcc17361f4dc86f14253fd897e28a4883d4f951b7"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1f050ba6dbea65fe490c33cebb656c721b27989fd0fee2e497c13485415a2016"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:533f02e4c815b8b40285ee8e89119a55117ca2e2e08502cfef31e6218d89b165"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b8da5f00a8daf4e64c47a65f4aa8a821269211f99525f09053b9ec701e04f34"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55d42e7b501f6ce31eed56e7d187a057aa30e8eed832806f06aa7e29dd07482a"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d7dd21f594b372bf9169e37e793a1356ecf2d0e25068c37bba16a3ef4e00299"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c5e51200bc9120e072db0f87e38047032e37f5699f9ad8c57c14263439a5a8b1"}, + {file = "bitarray-3.4.2.tar.gz", hash = "sha256:78ed2b911aabede3a31e3329b1de8abdc8104bd5e0545184ddbd9c7f668f4059"}, ] [[package]] name = "cachetools" -version = "5.3.1" +version = "6.0.0" description = "Extensible memoizing collections and decorators" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "cachetools-5.3.1-py3-none-any.whl", hash = "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590"}, - {file = "cachetools-5.3.1.tar.gz", hash = "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b"}, + {file = "cachetools-6.0.0-py3-none-any.whl", hash = "sha256:82e73ba88f7b30228b5507dce1a1f878498fc669d972aef2dde4f3a3c24f103e"}, + {file = "cachetools-6.0.0.tar.gz", hash = "sha256:f225782b84438f828328fc2ad74346522f27e5b1440f4e9fd18b20ebfd1aa2cf"}, ] [[package]] name = "certifi" -version = "2023.7.22" +version = "2025.4.26" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, + {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, ] [[package]] @@ -301,6 +355,7 @@ version = "3.4.0" description = "Validate configuration and produce human readable error messages." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, @@ -308,306 +363,421 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.3.0" +version = "3.4.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.3.0.tar.gz", hash = "sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-win32.whl", hash = "sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-win32.whl", hash = "sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-win32.whl", hash = "sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-win32.whl", hash = "sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-win32.whl", hash = "sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-win32.whl", hash = "sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884"}, - {file = "charset_normalizer-3.3.0-py3-none-any.whl", hash = "sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2"}, +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"}, + {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"}, + {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, ] [[package]] name = "ckzg" -version = "2.0.1" +version = "2.1.1" description = "Python bindings for C-KZG-4844" optional = false python-versions = "*" +groups = ["main"] files = [ - {file = "ckzg-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b7f9ba6d215f8981c5545f952aac84875bd564a63da02fb22a3d1321662ecdc0"}, - {file = "ckzg-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8fdec3ff96399acba9baeef9e1b0b5258c08f73245780e6c69f7b73def5e8d0a"}, - {file = "ckzg-2.0.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1644369af9900a9f109d417d6760693edf134118f3100d0c68f56667de775b80"}, - {file = "ckzg-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0a2146f122d489ac7e67ae0c0743f8d0db1718e6aeed8f05717340594fe07dd"}, - {file = "ckzg-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:979841be50f2782b447762db38e9bc927ae251f6ca86c54a26561a52068ee779"}, - {file = "ckzg-2.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4516d86647ee4e8ea9470f4adf68fbebb6dc1bdedff7d9592c2504fe53145908"}, - {file = "ckzg-2.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:91866fc58a29b4829201efd9ffadfac3ffeca6359254a54a360ff6a189c34bf5"}, - {file = "ckzg-2.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ed35508dac059b2c0a7994383bc7a92eaf35d0b9ce790016819e2619e0f4b8a9"}, - {file = "ckzg-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:449c4fe38017351eca362106420eeb2d28d50b7e54aa8668b3af29a8ab780132"}, - {file = "ckzg-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:260608a22e2f2cadcd31f4495832d45d6460438c38faba9761b92df885a99d88"}, - {file = "ckzg-2.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e1015f99c50215098751b07d7e459ba9a2790d3692ca81552eed29996128e90d"}, - {file = "ckzg-2.0.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dd350d97554c161dc5b8c7b32c2dc8e659632c374f60e2669fb3c9b5b294827"}, - {file = "ckzg-2.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eec7724fa8dc4ae95757efe4a87e7b2d4b880cb348c72ce7355fc0c4f64bc298"}, - {file = "ckzg-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3fa0f4398fa67fb71f0a2b34a652cc89e6e0e6af1340b0dc771db1a5f3e089c"}, - {file = "ckzg-2.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f865a0297aabeeb638187a46f7df445763360417b9df4dea60560d512c2cda09"}, - {file = "ckzg-2.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b6ec738350771dbf5974fb70cc8bbb20a4df784af770f7e655922adc08a2171"}, - {file = "ckzg-2.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9b4b669fc77edeb16adc182efc32b3737b36f741a2e33a170d40619e8b171a94"}, - {file = "ckzg-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:decb97f4a17c7338b2130dcc4b045df4cc0e7785ece872c764b554c7c73a99ff"}, - {file = "ckzg-2.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:285cf3121b8a8c5609c5b706314f68d2ba2784ab02c5bb7487c6ae1714ecb27f"}, - {file = "ckzg-2.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f927bc41c2551b0ef0056a649a7ebed29d9665680a10795f4cee5002c69ddb7"}, - {file = "ckzg-2.0.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fd9fb690c88919f30c9f3ab7cc46a7ecd734d5ff4c9ccea383c119b9b7cc4da"}, - {file = "ckzg-2.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fabc3bd41b306d1c7025d561c3281a007c2aca8ceaf998582dc3894904d9c73e"}, - {file = "ckzg-2.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eb50c53efdb9c34f762bd0c8006cf79bc92a9daf47aa6b541e496988484124f"}, - {file = "ckzg-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7960cc62f959403293fb53a3c2404778369ae7cefc6d7f202e5e00567cf98c4b"}, - {file = "ckzg-2.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d721bcd492294c70eca39da0b0a433c29b6a571dbac2f7084bab06334904af06"}, - {file = "ckzg-2.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dde2391d025b5033ef0eeacf62b11ecfe446aea25682b5f547a907766ad0a8cb"}, - {file = "ckzg-2.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fab8859d9420f6f7df4e094ee3639bc49d18c8dab0df81bee825e2363dd67a09"}, - {file = "ckzg-2.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9747d92883199d4f8f3a3d7018134745fddcf692dfe67115434e4b32609ea785"}, - {file = "ckzg-2.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b2cf58fb9e165da97f0ffe9f4a6efb73992645fac8e0fa223a6cc7ec486a434a"}, - {file = "ckzg-2.0.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d25d006899d76bb8c9d3e8b27981dd6b66a78f9826e33c1bf981af6577a69a19"}, - {file = "ckzg-2.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a04bf0b32f04f5ea5e4b8518e292d3321bc05596fde95f9c3b4f504e5e4bc780"}, - {file = "ckzg-2.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d0cf3dccd72376bff10e1833641cc9d642f34f60ca63972626d9dfcfdc8e77f"}, - {file = "ckzg-2.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:770809c7e93087470cc524724419b0f85590edb033c7c73ba94aef70b36ca18b"}, - {file = "ckzg-2.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e31b59b8124148d5e21f7e41b35532d7af98260c44a77c3917958adece84296d"}, - {file = "ckzg-2.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:174f0c356df644d6e349ce03b7284d83dbec859e11ca5d1b1b3bace8b8fbc65d"}, - {file = "ckzg-2.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:30e375cd45142e56b5dbfdec05ce4deb2368d7f7dedfc7408ba37d5639af05ff"}, - {file = "ckzg-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:abdee71958b214730a8341b16bdd413d0fab1b1a2504fbdb7b0ef2aeee9f9d22"}, - {file = "ckzg-2.0.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b4442667058db791325fe231f22e4fc7aaa3495d535d75af5595bc5f4f86036"}, - {file = "ckzg-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c3c9aa9d4477ad52f3561b717e776c1a8a442d9d8b06600c7d8a2857d1ecf05"}, - {file = "ckzg-2.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68e0a9cde35f11e80b4e560d22990f2f29dd200a95d3141acde137cb6c883f9a"}, - {file = "ckzg-2.0.1-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:4508a089e53330866d3360000d76483400eeab5f8057b8e1f3e344ce2cc0097b"}, - {file = "ckzg-2.0.1-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:828cecee16ec576dcf4386beac4eedfd058fd32ee90827f2282e7156a53600be"}, - {file = "ckzg-2.0.1-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:bd437ec1dfb4f5609979328b5f465a74307f45d46d24234868c67d44da96903b"}, - {file = "ckzg-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:70406b10acf68469ac62110047044a6c1a998f5d5fcd6e27cb3ec2d5760d0490"}, - {file = "ckzg-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2f53fba88febac17e82a96eb83dc38ecf4b28abcdd15c0246534c358bd3b26c4"}, - {file = "ckzg-2.0.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be8e0d5015e7755af4ddaab9ae1a4084f72c84b2cbb53628f4366aeed46cc380"}, - {file = "ckzg-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:261414121091042d29f28fc319d7c9a7f950f91f8bf54c010b581ee6a0499473"}, - {file = "ckzg-2.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:524e1e66edd2be2c38b660824aa7b5d4525b41b30ac029d80738a8eee491aeb5"}, - {file = "ckzg-2.0.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:4a12a1d8ef8f475d9f0af9a538e1674057e007806cb1204bb269ea00d9f8c1e5"}, - {file = "ckzg-2.0.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:4cc4bb5f62417a58065deeaf124e178cb1787ef3228e6032600d1e0a2775765b"}, - {file = "ckzg-2.0.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:e7b015f5615bcb82fa0d935481a209fc1dcd9308fb52fb1a7e5400108df67a94"}, - {file = "ckzg-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0518933ff3b9550f9dd60d833cdb74e8e97cc1cc58f0560b706916606dfd47d0"}, - {file = "ckzg-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ac0bca0795990076cde1930ecec307379b5303e34367c6e6e8a16bdba5a7ba5"}, - {file = "ckzg-2.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8086d23a41020ede312843bda7ea4ee0c9831265379027904106f99f2f8ed469"}, - {file = "ckzg-2.0.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31d1b141d41fa51aeac9440c936b812e885aef5719adfbd3a27550d8dc433997"}, - {file = "ckzg-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60a58e4d8cb91bad669ca111b7ccdd05c32de6787fdb571bb599625b043ad75b"}, - {file = "ckzg-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:633e143385622d7a43fcb5c4f400ec5ec15df0b1c74ab7d6449a41a7abed24ad"}, - {file = "ckzg-2.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4876313614ea01f9a0039b5ca2c754340ba40aa8405f8756912d90ae55718011"}, - {file = "ckzg-2.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:19c86c8102200484074afac06b3946b457ba9915636de187f63854522be2e3bd"}, - {file = "ckzg-2.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:564abf27878f129781e1df4d33b1c4e264e5b25f89c1bdf95b7d6256e4bceb6c"}, - {file = "ckzg-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:bc2da29bb970d3f5de04fb60797dbb4490c010ffc683cbc6016349dd6fa60d14"}, - {file = "ckzg-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9c1869671140ae7e698520b678b594ebd26fb59ef476711403541597d7d32c01"}, - {file = "ckzg-2.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1dd2aec2c61e8cc2ec815900f6768c6fe74b8fd29810e79b57c4150c6db32fb6"}, - {file = "ckzg-2.0.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9632ef17285dbdd3fcd9780f599c266da736d9b2897decc4ea02ba8690bdf72"}, - {file = "ckzg-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5747d7926873e3af0f6af5fca666feb0097d06cab525950e2664a6fbcb90165d"}, - {file = "ckzg-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75484ffb78aaebaeb3a30f1194a9143b904312b0f365fc4101e58e1bf5f89f66"}, - {file = "ckzg-2.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b2f72bc861b8bee9bac3314c58586d1ab2d23530f932a8f0a8562c8a4a6a45f9"}, - {file = "ckzg-2.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6f85e5802fea5b77f52fc3a14c8dec18a3f2b7c7070c811a4608940834f563cc"}, - {file = "ckzg-2.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:583a0b6b531a16974676439b23e7defb3dfe9732f18d13d2316152019c538af1"}, - {file = "ckzg-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:fafb9ac36b3398f8091d40773d9a450e5f74883dad8ca4ee22d472e7a231ef4d"}, - {file = "ckzg-2.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a12e96f20dce35e5222f898a5c8355054ef7c5ee038eeb97dbb694640b57577b"}, - {file = "ckzg-2.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:4e0ebc55253addaa24dd2cd871bbe3b8f57855f32b5f74e70bf2cb76b6f7da54"}, - {file = "ckzg-2.0.1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8f917a7bf363a3735db30559e1ed63cf1ccf414234433ba687fa72c007abd756"}, - {file = "ckzg-2.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30f08c984286853271d4adae219e9ba87275a15047dbaa262ab8dd6c01be97b0"}, - {file = "ckzg-2.0.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fa1ea4888417e1f109fd5e57965788fb7f53b674329b937a65604a3c1ca1d03"}, - {file = "ckzg-2.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0b249914aeaf05cabc71c5c3797e3d6c126cb2c64192b7eb6755ef6aa5ab2f11"}, - {file = "ckzg-2.0.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a038e26baf650e1c733dcaa066ec948e75556b0c485e8c790c9a758875c71a93"}, - {file = "ckzg-2.0.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d6deb2c822122bdd32b555fa3b9216c86a355f24a2cc6a46b9b5743b412b60c"}, - {file = "ckzg-2.0.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50f6f2fbceba9ece3fbc1d2613a246f4e6ec4d787f542859e70c358928c0e4a1"}, - {file = "ckzg-2.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33ca40ef30129e2347bff3c95ad093403a0d5703476705ab92c92fbffe89bd5a"}, - {file = "ckzg-2.0.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:700b989c2f7089edc8fac6dfbd1b4677e85b966216ebedee8eb5e7894765c188"}, - {file = "ckzg-2.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f11933c007c3df02446a81957ac6e2488058b969e2eff5357c98ab569a0c7999"}, - {file = "ckzg-2.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:3dbc9580eccecbd485f22e48f6044c48cbe6d838a7b7514cce179c085c65a960"}, - {file = "ckzg-2.0.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad6eb83f343fea6dd9a13fd1bce87b9cd26abeeb72f0674a62d26e40fe0b8aca"}, - {file = "ckzg-2.0.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:269f82b992facbd20461310cf5784551c77d11017b7d4b85d741d70359be6794"}, - {file = "ckzg-2.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:895d67cfd43130652e1ae39b90465b392d9a72c7c7e6f250eaf14689bfda6351"}, - {file = "ckzg-2.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:369cf1aeaf336c31f2050a7f54ae21cf46f4b2db23ebb013fff621144ab361bb"}, - {file = "ckzg-2.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:24fda2637598a467e7b11ff664805ee7fdf4f6c7b0c043d6d0a6ccb69b5681ee"}, - {file = "ckzg-2.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea27baabe5b22b92901c428768eacf93b992ac7681f93768ab24818ad26ccfed"}, - {file = "ckzg-2.0.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a33f71e382020f2bc4ead2bd6881a9bd3811d929f272da239ac01ad615a00802"}, - {file = "ckzg-2.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:926507c569727bb4c851a1eea702c5e902267de96e06ce2d685019f973f72968"}, - {file = "ckzg-2.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f5f29518b0a4555d8f2a28559209bd1d4080547aa629ff9ee51799346573b3f"}, - {file = "ckzg-2.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4595db84ce63c227e4448de0f7b39d3043e3477d78394ff651708c37fee6c486"}, - {file = "ckzg-2.0.1.tar.gz", hash = "sha256:62c5adc381637affa7e1df465c57750b356a761b8a3164c3106589b02532b9c9"}, + {file = "ckzg-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b9825a1458219e8b4b023012b8ef027ef1f47e903f9541cbca4615f80132730"}, + {file = "ckzg-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e2a40a3ba65cca4b52825d26829e6f7eb464aa27a9e9efb6b8b2ce183442c741"}, + {file = "ckzg-2.1.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1d753fbe85be7c21602eddc2d40e0915e25fce10329f4f801a0002a4f886cc7"}, + {file = "ckzg-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d76b50527f1d12430bf118aff6fa4051e9860eada43f29177258b8d399448ea"}, + {file = "ckzg-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44c8603e43c021d100f355f50189183135d1df3cbbddb8881552d57fbf421dde"}, + {file = "ckzg-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:38707a638c9d715b3c30b29352b969f78d8fc10faed7db5faf517f04359895c0"}, + {file = "ckzg-2.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:52c4d257bdcbe822d20c5cd24c8154ec5aac33c49a8f5a19e716d9107a1c8785"}, + {file = "ckzg-2.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1507f7bfb9bcf51d816db5d8d0f0ed53c8289605137820d437b69daea8333e16"}, + {file = "ckzg-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:d02eaaf4f841910133552b3a051dea53bcfe60cd98199fc4cf80b27609d8baa2"}, + {file = "ckzg-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:465e2b71cf9dc383f66f1979269420a0da9274a3a9e98b1a4455e84927dfe491"}, + {file = "ckzg-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ee2f26f17a64ad0aab833d637b276f28486b82a29e34f32cf54b237b8f8ab72d"}, + {file = "ckzg-2.1.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99cc2c4e9fb8c62e3e0862c7f4df9142f07ba640da17fded5f6e0fd09f75909f"}, + {file = "ckzg-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773dd016693d74aca1f5d7982db2bad7dde2e147563aeb16a783f7e5f69c01fe"}, + {file = "ckzg-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af2b2144f87ba218d8db01382a961b3ecbdde5ede4fa0d9428d35f8c8a595ba"}, + {file = "ckzg-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8f55e63d3f7c934a2cb53728ed1d815479e177aca8c84efe991c2920977cff6"}, + {file = "ckzg-2.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ecb42aaa0ffa427ff14a9dde9356ba69e5ae6014650b397af55b31bdae7a9b6e"}, + {file = "ckzg-2.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5a01514239f12fb1a7ad9009c20062a4496e13b09541c1a65f97e295da648c70"}, + {file = "ckzg-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:6516b9684aae262c85cf7fddd8b585b8139ad20e08ec03994e219663abbb0916"}, + {file = "ckzg-2.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c60e8903344ce98ce036f0fabacce952abb714cad4607198b2f0961c28b8aa72"}, + {file = "ckzg-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4299149dd72448e5a8d2d1cc6cc7472c92fc9d9f00b1377f5b017c089d9cd92"}, + {file = "ckzg-2.1.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:025dd31ffdcc799f3ff842570a2a6683b6c5b01567da0109c0c05d11768729c4"}, + {file = "ckzg-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b42ab8385c273f40a693657c09d2bba40cb4f4666141e263906ba2e519e80bd"}, + {file = "ckzg-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1be3890fc1543f4fcfc0063e4baf5c036eb14bcf736dabdc6171ab017e0f1671"}, + {file = "ckzg-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b754210ded172968b201e2d7252573af6bf52d6ad127ddd13d0b9a45a51dae7b"}, + {file = "ckzg-2.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b2f8fda87865897a269c4e951e3826c2e814427a6cdfed6731cccfe548f12b36"}, + {file = "ckzg-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:98e70b5923d77c7359432490145e9d1ab0bf873eb5de56ec53f4a551d7eaec79"}, + {file = "ckzg-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:42af7bde4ca45469cd93a96c3d15d69d51d40e7f0d30e3a20711ebd639465fcb"}, + {file = "ckzg-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7e4edfdaf87825ff43b9885fabfdea408737a714f4ce5467100d9d1d0a03b673"}, + {file = "ckzg-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:815fd2a87d6d6c57d669fda30c150bc9bf387d47e67d84535aa42b909fdc28ea"}, + {file = "ckzg-2.1.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c32466e809b1ab3ff01d3b0bb0b9912f61dcf72957885615595f75e3f7cc10e5"}, + {file = "ckzg-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f11b73ccf37b12993f39a7dbace159c6d580aacacde6ee17282848476550ddbc"}, + {file = "ckzg-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de3b9433a1f2604bd9ac1646d3c83ad84a850d454d3ac589fe8e70c94b38a6b0"}, + {file = "ckzg-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b7d7e1b5ea06234558cd95c483666fd785a629b720a7f1622b3cbffebdc62033"}, + {file = "ckzg-2.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9f5556e6675866040cc4335907be6c537051e7f668da289fa660fdd8a30c9ddb"}, + {file = "ckzg-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:55b2ba30c5c9daac0c55f1aac851f1b7bf1f7aa0028c2db4440e963dd5b866d6"}, + {file = "ckzg-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:10d201601fc8f28c0e8cec3406676797024dd374c367bbeec5a7a9eac9147237"}, + {file = "ckzg-2.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:5f46c8fd5914db62b446baf62c8599da07e6f91335779a9709c554ef300a7b60"}, + {file = "ckzg-2.1.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:60f14612c2be84f405755d734b0ad4e445db8af357378b95b72339b59e1f4fcf"}, + {file = "ckzg-2.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:929e6e793039f42325988004a90d16b0ef4fc7e1330142e180f0298f2ed4527c"}, + {file = "ckzg-2.1.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2beac2af53ea181118179570ecc81d8a8fc52c529553d7fd8786fd100a2aa39b"}, + {file = "ckzg-2.1.1-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:2432d48aec296baee79556bfde3bddd2799bcc7753cd1f0d0c9a3b0333935637"}, + {file = "ckzg-2.1.1-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:4c2e8180b54261ccae2bf8acd003ccee7394d88d073271af19c5f2ac4a54c607"}, + {file = "ckzg-2.1.1-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:c44e36bd53d9dd0ab29bd6ed2d67ea43c48eecd57f8197854a75742213938bf5"}, + {file = "ckzg-2.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:10befd86e643d38ac468151cdfb71e79b2d46aa6397b81db4224f4f6995262eb"}, + {file = "ckzg-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:138a9324ad8e8a9ade464043dc3a84afe12996516788f2ed841bdbe5d123af81"}, + {file = "ckzg-2.1.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:635af0a33a10c9ac275f3efc142880a6b46ac63f4495f600aae05266af4fadff"}, + {file = "ckzg-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:360e263677ee5aedb279b42cf54b51c905ddcac9181c65d89ec0b298d3f31ec0"}, + {file = "ckzg-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f81395f77bfd069831cbb1de9d473c7044abe9ce6cd562ef6ccd76d23abcef43"}, + {file = "ckzg-2.1.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:db1ff122f8dc10c9500a00a4d680c3c38f4e19b01d95f38e0f5bc55a77c8ab98"}, + {file = "ckzg-2.1.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:1f82f539949ff3c6a5accfdd211919a3e374d354b3665d062395ebdbf8befaeb"}, + {file = "ckzg-2.1.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:5bc8ae85df97467e84abb491b516e25dbca36079e766eafce94d1bc45e4aaa35"}, + {file = "ckzg-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:e749ce9fcb26e37101f2af8ba9c6376b66eb598880d35e457890044ba77c1cf7"}, + {file = "ckzg-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b00201979a64fd7e6029f64d791af42374febb42452537933e881b49d4e8c77"}, + {file = "ckzg-2.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c61c437ba714ab7c802b51fb30125e8f8550e1320fe9050d20777420c153a2b3"}, + {file = "ckzg-2.1.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8bd54394376598a7c081df009cfde3cc447beb640b6c6b7534582a31e6290ac7"}, + {file = "ckzg-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67d8c6680a7b370718af59cc17a983752706407cfbcace013ee707646d1f7b00"}, + {file = "ckzg-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55f6c57b24bc4fe16b1b50324ef8548f2a5053ad76bf90c618e2f88c040120d7"}, + {file = "ckzg-2.1.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f55fc10fb1b217c66bfe14e05535e5e61cfbb2a95dbb9b93a80984fa2ab4a7c0"}, + {file = "ckzg-2.1.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:2e23e3198f8933f0140ef8b2aeba717d8de03ec7b8fb1ee946f8d39986ce0811"}, + {file = "ckzg-2.1.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2f9caf88bf216756bb1361b92616c750a933c9afb67972ad05c212649a9be520"}, + {file = "ckzg-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:30e0c2d258bbc0c099c2d1854c6ffa2fd9abf6138b9c81f855e1936f6cb259aa"}, + {file = "ckzg-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a6239d3d2e30cb894ca4e7765b1097eb6a70c0ecbe5f8e0b023fbf059472d4ac"}, + {file = "ckzg-2.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:909ebabc253a98d9dc1d51f93dc75990134bfe296c947e1ecf3b7142aba5108e"}, + {file = "ckzg-2.1.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0700dace6559b288b42ca8622be89c2a43509881ed6f4f0bfb6312bcceed0cb9"}, + {file = "ckzg-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a36aeabd243e906314694b4a107de99b0c4473ff1825fcb06acd147ffb1951a"}, + {file = "ckzg-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d884e8f9c7d7839f1a95561f4479096dce21d45b0c5dd013dc0842550cea1cad"}, + {file = "ckzg-2.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:338fdf4a0b463973fc7b7e4dc289739db929e61d7cb9ba984ebbe9c49d3aa6f9"}, + {file = "ckzg-2.1.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c594036d3408eebdcd8ab2c7aab7308239ed4df3d94f3211b7cf253f228fb0b7"}, + {file = "ckzg-2.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b0912ebb328ced510250a2325b095917db19c1a014792a0bf4c389f0493e39de"}, + {file = "ckzg-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:5046aceb03482ddf7200f2f5c643787b100e6fb96919852faf1c79f8870c80a1"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:375918e25eafb9bafe5215ab91698504cba3fe51b4fe92f5896af6c5663f50c6"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:38b3b7802c76d4ad015db2b7a79a49c193babae50ee5f77e9ac2865c9e9ddb09"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:438a5009fd254ace0bc1ad974d524547f1a41e6aa5e778c5cd41f4ee3106bcd6"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ce11cc163a2e0dab3af7455aca7053f9d5bb8d157f231acc7665fd230565d48"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b53964c07f6a076e97eaa1ef35045e935d7040aff14f80bae7e9105717702d05"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cf085f15ae52ab2599c9b5a3d5842794bcf5613b7f58661fbfb0c5d9eac988b9"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4b0c850bd6cad22ac79b2a2ab884e0e7cd2b54a67d643cd616c145ebdb535a11"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:26951f36bb60c9150bbd38110f5e1625596f9779dad54d1d492d8ec38bc84e3a"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe12445e49c4bee67746b7b958e90a973b0de116d0390749b0df351d94e9a8c"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71c5d4f66f09de4a99271acac74d2acb3559a77de77a366b34a91e99e8822667"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42673c1d007372a4e8b48f6ef8f0ce31a9688a463317a98539757d1e2fb1ecc7"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:57a7dc41ec6b69c1d9117eb61cf001295e6b4f67a736020442e71fb4367fb1a5"}, + {file = "ckzg-2.1.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:22e4606857660b2ffca2f7b96c01d0b18b427776d8a93320caf2b1c7342881fe"}, + {file = "ckzg-2.1.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b55475126a9efc82d61718b2d2323502e33d9733b7368c407954592ccac87faf"}, + {file = "ckzg-2.1.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5939ae021557c64935a7649b13f4a58f1bd35c39998fd70d0cefb5cbaf77d1be"}, + {file = "ckzg-2.1.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad1ec5f9726a9946508a4a2aace298172aa778de9ebbe97e21c873c3688cc87"}, + {file = "ckzg-2.1.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93d7edea3bb1602b18b394ebeec231d89dfd8d48fdd06571cb7656107aa62226"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c450d77af61011ced3777f97431d5f1bc148ca5362c67caf516aa2f6ef7e4817"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fc8df4e17e08974961d6c14f6c57ccfd3ad5aede74598292ec6e5d6fc2dbcac"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93338da8011790ef53a68475678bc951fa7b337db027d8edbf1889e59691161c"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4889f24b4ff614f39e3584709de1a3b0f1556675b33e360dbcb28cda827296d4"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7b58fbb1a9be4ae959feede8f103e12d80ef8453bdc6483bfdaf164879a2b80"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6136c5b5377c7f7033323b25bc2c7b43c025d44ed73e338c02f9f59df9460e5b"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fa419b92a0e8766deb7157fb28b6542c1c3f8dde35d2a69d1f91ec8e41047d35"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:95cd6c8eb3ab5148cd97ab5bf44b84fd7f01adf4b36ffd070340ad2d9309b3f9"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:848191201052b48bdde18680ebb77bf8da99989270e5aea8b0290051f5ac9468"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4716c0564131b0d609fb8856966e83892b9809cf6719c7edd6495b960451f8b"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c399168ba199827dee3104b00cdc7418d4dbdf47a5fcbe7cf938fc928037534"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:724f29f9f110d9ef42a6a1a1a7439548c61070604055ef96b2ab7a884cad4192"}, + {file = "ckzg-2.1.1.tar.gz", hash = "sha256:d6b306b7ec93a24e4346aa53d07f7f75053bc0afc7398e35fa649e5f9d48fcc4"}, ] +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +markers = "sys_platform == \"win32\"" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "coverage" +version = "7.8.2" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404"}, + {file = "coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7"}, + {file = "coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54"}, + {file = "coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a"}, + {file = "coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975"}, + {file = "coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f"}, + {file = "coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8"}, + {file = "coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223"}, + {file = "coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48"}, + {file = "coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7"}, + {file = "coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3"}, + {file = "coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199"}, + {file = "coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8"}, + {file = "coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d"}, + {file = "coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7"}, + {file = "coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a"}, + {file = "coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e"}, + {file = "coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837"}, + {file = "coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32"}, + {file = "coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] + [[package]] name = "cytoolz" -version = "0.12.2" +version = "1.0.1" description = "Cython implementation of Toolz: High performance functional utilities" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["main"] +markers = "implementation_name == \"cpython\"" files = [ - {file = "cytoolz-0.12.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bff49986c9bae127928a2f9fd6313146a342bfae8292f63e562f872bd01b871"}, - {file = "cytoolz-0.12.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:908c13f305d34322e11b796de358edaeea47dd2d115c33ca22909c5e8fb036fd"}, - {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:735147aa41b8eeb104da186864b55e2a6623c758000081d19c93d759cd9523e3"}, - {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d352d4de060604e605abdc5c8a5d0429d5f156cb9866609065d3003454d4cea"}, - {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:89247ac220031a4f9f689688bcee42b38fd770d4cce294e5d914afc53b630abe"}, - {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9070ae35c410d644e6df98a8f69f3ed2807e657d0df2a26b2643127cbf6944a5"}, - {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:843500cd3e4884b92fd4037912bc42d5f047108d2c986d36352e880196d465b0"}, - {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6a93644d7996fd696ab7f1f466cd75d718d0a00d5c8118b9fe8c64231dc1f85e"}, - {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:96796594c770bc6587376e74ddc7d9c982d68f47116bb69d90873db5e0ea88b6"}, - {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:48425107fbb1af3f0f2410c004f16be10ffc9374358e5600b57fa543f46f8def"}, - {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:cde6dbb788a4cbc4a80a72aa96386ba4c2b17bdfff3ace0709799adbe16d6476"}, - {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:68ae7091cc73a752f0b938f15bb193de80ca5edf5ae2ea6360d93d3e9228357b"}, - {file = "cytoolz-0.12.2-cp310-cp310-win32.whl", hash = "sha256:997b7e0960072f6bb445402da162f964ea67387b9f18bda2361edcc026e13597"}, - {file = "cytoolz-0.12.2-cp310-cp310-win_amd64.whl", hash = "sha256:663911786dcde3e4a5d88215c722c531c7548903dc07d418418c0d1c768072c0"}, - {file = "cytoolz-0.12.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a7d8b869ded171f6cdf584fc2fc6ae03b30a0e1e37a9daf213a59857a62ed90"}, - {file = "cytoolz-0.12.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9b28787eaf2174e68f0acb3c66f9c6b98bdfeb0930c0d0b08e1941c7aedc8d27"}, - {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00547da587f124b32b072ce52dd5e4b37cf199fedcea902e33c67548523e4678"}, - {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:275d53fd769df2102d6c9fc98e553bd8a9a38926f54d6b20cf29f0dd00bf3b75"}, - {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5556acde785a61d4cf8b8534ae109b023cbd2f9df65ee2afbe070be47c410f8c"}, - {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b41a85b9b9a2530b72b0d3d10e383fc3c2647ae88169d557d5e216f881860318"}, - {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:673d6e9e3aa86949343b46ac2b7be266c36e07ce77fa1d40f349e6987a814d6e"}, - {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81e6a9a8fda78a2f4901d2915b25bf620f372997ca1f20a14f7cefef5ad6f6f4"}, - {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fa44215bc31675a6380cd896dadb7f2054a7b94cfb87e53e52af844c65406a54"}, - {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:a08b4346350660799d81d4016e748bcb134a9083301d41f9618f64a6077f89f2"}, - {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2fb740482794a72e2e5fec58e4d9b00dcd5a60a8cef68431ff12f2ba0e0d9a7e"}, - {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9007bb1290c79402be6b84bcf9e7a622a073859d61fcee146dc7bc47afe328f3"}, - {file = "cytoolz-0.12.2-cp311-cp311-win32.whl", hash = "sha256:a973f5286758f76824ecf19ae1999f6697371a9121c8f163295d181d19a819d7"}, - {file = "cytoolz-0.12.2-cp311-cp311-win_amd64.whl", hash = "sha256:1ce324d1b413636ea5ee929f79637821f13c9e55e9588f38228947294944d2ed"}, - {file = "cytoolz-0.12.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c08094b9e5d1b6dfb0845a0253cc2655ca64ce70d15162dfdb102e28c8993493"}, - {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baf020f4b708f800b353259cd7575e335a79f1ac912d9dda55b2aa0bf3616e42"}, - {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4416ee86a87180b6a28e7483102c92debc077bec59c67eda8cc63fc52a218ac0"}, - {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6ee222671eed5c5b16a5ad2aea07f0a715b8b199ee534834bc1dd2798f1ade7"}, - {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad92e37be0b106fdbc575a3a669b43b364a5ef334495c9764de4c2d7541f7a99"}, - {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:460c05238fbfe6d848141669d17a751a46c923f9f0c9fd8a3a462ab737623a44"}, - {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9e5075e30be626ef0f9bedf7a15f55ed4d7209e832bc314fdc232dbd61dcbf44"}, - {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:03b58f843f09e73414e82e57f7e8d88f087eaabf8f276b866a40661161da6c51"}, - {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5e4e612b7ecc9596e7c859cd9e0cd085e6d0c576b4f0d917299595eb56bf9c05"}, - {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:08a0e03f287e45eb694998bb55ac1643372199c659affa8319dfbbdec7f7fb3c"}, - {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b029bdd5a8b6c9a7c0e8fdbe4fc25ffaa2e09b77f6f3462314696e3a20511829"}, - {file = "cytoolz-0.12.2-cp36-cp36m-win32.whl", hash = "sha256:18580d060fa637ff01541640ecde6de832a248df02b8fb57e6dd578f189d62c7"}, - {file = "cytoolz-0.12.2-cp36-cp36m-win_amd64.whl", hash = "sha256:97cf514a9f3426228d8daf880f56488330e4b2948a6d183a106921217850d9eb"}, - {file = "cytoolz-0.12.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18a0f838677f9510aef0330c0096778dd6406d21d4ff9504bf79d85235a18460"}, - {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb081b2b02bf4405c804de1ece6f904916838ab0e057f1446e4ac12fac827960"}, - {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57233e1600560ceb719bed759dc78393edd541b9a3e7fefc3079abd83c26a6ea"}, - {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0295289c4510efa41174850e75bc9188f82b72b1b54d0ea57d1781729c2924d5"}, - {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a92aab8dd1d427ac9bc7480cfd3481dbab0ef024558f2f5a47de672d8a5ffaa"}, - {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51d3495235af09f21aa92a7cdd51504bda640b108b6be834448b774f52852c09"}, - {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9c690b359f503f18bf1c46a6456370e4f6f3fc4320b8774ae69c4f85ecc6c94"}, - {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:481e3129a76ea01adcc0e7097ccb8dbddab1cfc40b6f0e32c670153512957c0f"}, - {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:55e94124af9c8fbb1df54195cc092688fdad0765641b738970b6f1d5ea72e776"}, - {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5616d386dfbfba7c39e9418ba668c734f6ceaacc0130877e8a100cad11e6838b"}, - {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:732d08228fa8d366fec284f7032cc868d28a99fa81fc71e3adf7ecedbcf33a0f"}, - {file = "cytoolz-0.12.2-cp37-cp37m-win32.whl", hash = "sha256:f039c5373f7b314b151432c73219216857b19ab9cb834f0eb5d880f74fc7851c"}, - {file = "cytoolz-0.12.2-cp37-cp37m-win_amd64.whl", hash = "sha256:246368e983eaee9851b15d7755f82030eab4aa82098d2a34f6bef9c689d33fcc"}, - {file = "cytoolz-0.12.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:81074edf3c74bc9bd250d223408a5df0ff745d1f7a462597536cd26b9390e2d6"}, - {file = "cytoolz-0.12.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:960d85ebaa974ecea4e71fa56d098378fa51fd670ee744614cbb95bf95e28fc7"}, - {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c8d0dff4865da54ae825d43e1721925721b19f3b9aca8e730c2ce73dee2c630"}, - {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0a9d12436fd64937bd2c9609605f527af7f1a8db6e6637639b44121c0fe715d6"}, - {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd461e402e24929d866f05061d2f8337e3a8456e75e21b72c125abff2477c7f7"}, - {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0568d4da0a9ee9f9f5ab318f6501557f1cfe26d18c96c8e0dac7332ae04c6717"}, - {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:101b5bd32badfc8b1f9c7be04ba3ae04fb47f9c8736590666ce9449bff76e0b1"}, - {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8bb624dbaef4661f5e3625c1e39ad98ecceef281d1380e2774d8084ad0810275"}, - {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3e993804e6b04113d61fdb9541b6df2f096ec265a506dad7437517470919c90f"}, - {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ab911033e5937fc221a2c165acce7f66ae5ac9d3e54bec56f3c9c197a96be574"}, - {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6de6a4bdfaee382c2de2a3580b3ae76fce6105da202bbd835e5efbeae6a9c6e"}, - {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9480b4b327be83c4d29cb88bcace761b11f5e30198ffe2287889455c6819e934"}, - {file = "cytoolz-0.12.2-cp38-cp38-win32.whl", hash = "sha256:4180b2785d1278e6abb36a72ac97c92432db53fa2df00ee943d2c15a33627d31"}, - {file = "cytoolz-0.12.2-cp38-cp38-win_amd64.whl", hash = "sha256:d0086ba8d41d73647b13087a3ca9c020f6bfec338335037e8f5172b4c7c8dce5"}, - {file = "cytoolz-0.12.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d29988bde28a90a00367edcf92afa1a2f7ecf43ea3ae383291b7da6d380ccc25"}, - {file = "cytoolz-0.12.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:24c0d71e9ac91f4466b1bd280f7de43aa4d94682daaf34d85d867a9b479b87cc"}, - {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa436abd4ac9ca71859baf5794614e6ec8fa27362f0162baedcc059048da55f7"}, - {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45c7b4eac7571707269ebc2893facdf87e359cd5c7cfbfa9e6bd8b33fb1079c5"}, - {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:294d24edc747ef4e1b28e54365f713becb844e7898113fafbe3e9165dc44aeea"}, - {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:478051e5ef8278b2429864c8d148efcebdc2be948a61c9a44757cd8c816c98f5"}, - {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14108cafb140dd68fdda610c2bbc6a37bf052cd48cfebf487ed44145f7a2b67f"}, - {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5fef7b602ccf8a3c77ab483479ccd7a952a8c5bb1c263156671ba7aaa24d1035"}, - {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9bf51354e15520715f068853e6ab8190e77139940e8b8b633bdb587956a08fb0"}, - {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:388f840fd911d61a96e9e595eaf003f9dc39e847c9060b8e623ab29e556f009b"}, - {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:a67f75cc51a2dc7229a8ac84291e4d61dc5abfc8940befcf37a2836d95873340"}, - {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:63b31345e20afda2ae30dba246955517a4264464d75e071fc2fa641e88c763ec"}, - {file = "cytoolz-0.12.2-cp39-cp39-win32.whl", hash = "sha256:f6e86ac2b45a95f75c6f744147483e0fc9697ce7dfe1726083324c236f873f8b"}, - {file = "cytoolz-0.12.2-cp39-cp39-win_amd64.whl", hash = "sha256:5998f81bf6a2b28a802521efe14d9fc119f74b64e87b62ad1b0e7c3d8366d0c7"}, - {file = "cytoolz-0.12.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:593e89e2518eaf81e96edcc9ef2c5fca666e8fc922b03d5cb7a7b8964dbee336"}, - {file = "cytoolz-0.12.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff451d614ca1d4227db0ffa627fb51df71968cf0d9baf0210528dad10fdbc3ab"}, - {file = "cytoolz-0.12.2-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad9ea4a50d2948738351790047d45f2b1a023facc01bf0361988109b177e8b2f"}, - {file = "cytoolz-0.12.2-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbe038bb78d599b5a29d09c438905defaa615a522bc7e12f8016823179439497"}, - {file = "cytoolz-0.12.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d494befe648c13c98c0f3d56d05489c839c9228a32f58e9777305deb6c2c1cee"}, - {file = "cytoolz-0.12.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c26805b6c8dc8565ed91045c44040bf6c0fe5cb5b390c78cd1d9400d08a6cd39"}, - {file = "cytoolz-0.12.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df4e32badb2ccf1773e1e74020b7e3b8caf9e92f842c6be7d14888ecdefc2c6c"}, - {file = "cytoolz-0.12.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce7889dc3701826d519ede93cdff11940fb5567dbdc165dce0e78047eece02b7"}, - {file = "cytoolz-0.12.2-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c820608e7077416f766b148d75e158e454881961881b657cff808529d261dd24"}, - {file = "cytoolz-0.12.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:698da4fa1f7baeea0607738cb1f9877ed1ba50342b29891b0223221679d6f729"}, - {file = "cytoolz-0.12.2.tar.gz", hash = "sha256:31d4b0455d72d914645f803d917daf4f314d115c70de0578d3820deb8b101f66"}, + {file = "cytoolz-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cec9af61f71fc3853eb5dca3d42eb07d1f48a4599fa502cbe92adde85f74b042"}, + {file = "cytoolz-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:140bbd649dbda01e91add7642149a5987a7c3ccc251f2263de894b89f50b6608"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e90124bdc42ff58b88cdea1d24a6bc5f776414a314cc4d94f25c88badb3a16d1"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e74801b751e28f7c5cc3ad264c123954a051f546f2fdfe089f5aa7a12ccfa6da"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:582dad4545ddfb5127494ef23f3fa4855f1673a35d50c66f7638e9fb49805089"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd7bd0618e16efe03bd12f19c2a26a27e6e6b75d7105adb7be1cd2a53fa755d8"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d74cca6acf1c4af58b2e4a89cc565ed61c5e201de2e434748c93e5a0f5c541a5"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:823a3763828d8d457f542b2a45d75d6b4ced5e470b5c7cf2ed66a02f508ed442"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:51633a14e6844c61db1d68c1ffd077cf949f5c99c60ed5f1e265b9e2966f1b52"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f3ec9b01c45348f1d0d712507d54c2bfd69c62fbd7c9ef555c9d8298693c2432"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1855022b712a9c7a5bce354517ab4727a38095f81e2d23d3eabaf1daeb6a3b3c"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9930f7288c4866a1dc1cc87174f0c6ff4cad1671eb1f6306808aa6c445857d78"}, + {file = "cytoolz-1.0.1-cp310-cp310-win32.whl", hash = "sha256:a9baad795d72fadc3445ccd0f122abfdbdf94269157e6d6d4835636dad318804"}, + {file = "cytoolz-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:ad95b386a84e18e1f6136f6d343d2509d4c3aae9f5a536f3dc96808fcc56a8cf"}, + {file = "cytoolz-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2d958d4f04d9d7018e5c1850790d9d8e68b31c9a2deebca74b903706fdddd2b6"}, + {file = "cytoolz-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0f445b8b731fc0ecb1865b8e68a070084eb95d735d04f5b6c851db2daf3048ab"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f546a96460a7e28eb2ec439f4664fa646c9b3e51c6ebad9a59d3922bbe65e30"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0317681dd065532d21836f860b0563b199ee716f55d0c1f10de3ce7100c78a3b"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c0ef52febd5a7821a3fd8d10f21d460d1a3d2992f724ba9c91fbd7a96745d41"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5ebaf419acf2de73b643cf96108702b8aef8e825cf4f63209ceb078d5fbbbfd"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f7f04eeb4088947585c92d6185a618b25ad4a0f8f66ea30c8db83cf94a425e3"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f61928803bb501c17914b82d457c6f50fe838b173fb40d39c38d5961185bd6c7"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d2960cb4fa01ccb985ad1280db41f90dc97a80b397af970a15d5a5de403c8c61"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2b407cc3e9defa8df5eb46644f6f136586f70ba49eba96f43de67b9a0984fd3"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8245f929144d4d3bd7b972c9593300195c6cea246b81b4c46053c48b3f044580"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e37385db03af65763933befe89fa70faf25301effc3b0485fec1c15d4ce4f052"}, + {file = "cytoolz-1.0.1-cp311-cp311-win32.whl", hash = "sha256:50f9c530f83e3e574fc95c264c3350adde8145f4f8fc8099f65f00cc595e5ead"}, + {file = "cytoolz-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:b7f6b617454b4326af7bd3c7c49b0fc80767f134eb9fd6449917a058d17a0e3c"}, + {file = "cytoolz-1.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fcb8f7d0d65db1269022e7e0428471edee8c937bc288ebdcb72f13eaa67c2fe4"}, + {file = "cytoolz-1.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:207d4e4b445e087e65556196ff472ff134370d9a275d591724142e255f384662"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21cdf6bac6fd843f3b20280a66fd8df20dea4c58eb7214a2cd8957ec176f0bb3"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a55ec098036c0dea9f3bdc021f8acd9d105a945227d0811589f0573f21c9ce1"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a13ab79ff4ce202e03ab646a2134696988b554b6dc4b71451e948403db1331d8"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e2d944799026e1ff08a83241f1027a2d9276c41f7a74224cd98b7df6e03957d"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88ba85834cd523b91fdf10325e1e6d71c798de36ea9bdc187ca7bd146420de6f"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a750b1af7e8bf6727f588940b690d69e25dc47cce5ce467925a76561317eaf7"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:44a71870f7eae31d263d08b87da7c2bf1176f78892ed8bdade2c2850478cb126"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c8231b9abbd8e368e036f4cc2e16902c9482d4cf9e02a6147ed0e9a3cd4a9ab0"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:aa87599ccc755de5a096a4d6c34984de6cd9dc928a0c5eaa7607457317aeaf9b"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:67cd16537df51baabde3baa770ab7b8d16839c4d21219d5b96ac59fb012ebd2d"}, + {file = "cytoolz-1.0.1-cp312-cp312-win32.whl", hash = "sha256:fb988c333f05ee30ad4693fe4da55d95ec0bb05775d2b60191236493ea2e01f9"}, + {file = "cytoolz-1.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:8f89c48d8e5aec55ffd566a8ec858706d70ed0c6a50228eca30986bfa5b4da8b"}, + {file = "cytoolz-1.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6944bb93b287032a4c5ca6879b69bcd07df46f3079cf8393958cf0b0454f50c0"}, + {file = "cytoolz-1.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e027260fd2fc5cb041277158ac294fc13dca640714527219f702fb459a59823a"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88662c0e07250d26f5af9bc95911e6137e124a5c1ec2ce4a5d74de96718ab242"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:309dffa78b0961b4c0cf55674b828fbbc793cf2d816277a5c8293c0c16155296"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:edb34246e6eb40343c5860fc51b24937698e4fa1ee415917a73ad772a9a1746b"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a54da7a8e4348a18d45d4d5bc84af6c716d7f131113a4f1cc45569d37edff1b"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:241c679c3b1913c0f7259cf1d9639bed5084c86d0051641d537a0980548aa266"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5bfc860251a8f280ac79696fc3343cfc3a7c30b94199e0240b6c9e5b6b01a2a5"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c8edd1547014050c1bdad3ff85d25c82bd1c2a3c96830c6181521eb78b9a42b3"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b349bf6162e8de215403d7f35f8a9b4b1853dc2a48e6e1a609a5b1a16868b296"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1b18b35256219b6c3dd0fa037741b85d0bea39c552eab0775816e85a52834140"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:738b2350f340ff8af883eb301054eb724997f795d20d90daec7911c389d61581"}, + {file = "cytoolz-1.0.1-cp313-cp313-win32.whl", hash = "sha256:9cbd9c103df54fcca42be55ef40e7baea624ac30ee0b8bf1149f21146d1078d9"}, + {file = "cytoolz-1.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:90e577e08d3a4308186d9e1ec06876d4756b1e8164b92971c69739ea17e15297"}, + {file = "cytoolz-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f3a509e4ac8e711703c368476b9bbce921fcef6ebb87fa3501525f7000e44185"}, + {file = "cytoolz-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a7eecab6373e933dfbf4fdc0601d8fd7614f8de76793912a103b5fccf98170cd"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e55ed62087f6e3e30917b5f55350c3b6be6470b849c6566018419cd159d2cebc"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43de33d99a4ccc07234cecd81f385456b55b0ea9c39c9eebf42f024c313728a5"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:139bed875828e1727018aa0982aa140e055cbafccb7fd89faf45cbb4f2a21514"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22c12671194b518aa8ce2f4422bd5064f25ab57f410ba0b78705d0a219f4a97a"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79888f2f7dc25709cd5d37b032a8833741e6a3692c8823be181d542b5999128e"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:51628b4eb41fa25bd428f8f7b5b74fbb05f3ae65fbd265019a0dd1ded4fdf12a"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:1db9eb7179285403d2fb56ba1ff6ec35a44921b5e2fa5ca19d69f3f9f0285ea5"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:08ab7efae08e55812340bfd1b3f09f63848fe291675e2105eab1aa5327d3a16e"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e5fdc5264f884e7c0a1711a81dff112708a64b9c8561654ee578bfdccec6be09"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:90d6a2e6ab891043ee655ec99d5e77455a9bee9e1131bdfcfb745edde81200dd"}, + {file = "cytoolz-1.0.1-cp38-cp38-win32.whl", hash = "sha256:08946e083faa5147751b34fbf78ab931f149ef758af5c1092932b459e18dcf5c"}, + {file = "cytoolz-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:a91b4e10a9c03796c0dc93e47ebe25bb41ecc6fafc3cf5197c603cf767a3d44d"}, + {file = "cytoolz-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:980c323e626ba298b77ae62871b2de7c50b9d7219e2ddf706f52dd34b8be7349"}, + {file = "cytoolz-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:45f6fa1b512bc2a0f2de5123db932df06c7f69d12874fe06d67772b2828e2c8b"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93f42d9100c415155ad1f71b0de362541afd4ac95e3153467c4c79972521b6b"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a76d20dec9c090cdf4746255bbf06a762e8cc29b5c9c1d138c380bbdb3122ade"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:239039585487c69aa50c5b78f6a422016297e9dea39755761202fb9f0530fe87"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c28307640ca2ab57b9fbf0a834b9bf563958cd9e038378c3a559f45f13c3c541"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:454880477bb901cee3a60f6324ec48c95d45acc7fecbaa9d49a5af737ded0595"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:902115d1b1f360fd81e44def30ac309b8641661150fcbdde18ead446982ada6a"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e68e6b38473a3a79cee431baa22be31cac39f7df1bf23eaa737eaff42e213883"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:32fba3f63fcb76095b0a22f4bdcc22bc62a2bd2d28d58bf02fd21754c155a3ec"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0724ba4cf41eb40b6cf75250820ab069e44bdf4183ff78857aaf4f0061551075"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c42420e0686f887040d5230420ed44f0e960ccbfa29a0d65a3acd9ca52459209"}, + {file = "cytoolz-1.0.1-cp39-cp39-win32.whl", hash = "sha256:4ba8b16358ea56b1fe8e637ec421e36580866f2e787910bac1cf0a6997424a34"}, + {file = "cytoolz-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:92d27f84bf44586853d9562bfa3610ecec000149d030f793b4cb614fd9da1813"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:83d19d55738ad9c60763b94f3f6d3c6e4de979aeb8d76841c1401081e0e58d96"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f112a71fad6ea824578e6393765ce5c054603afe1471a5c753ff6c67fd872d10"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a515df8f8aa6e1eaaf397761a6e4aff2eef73b5f920aedf271416d5471ae5ee"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92c398e7b7023460bea2edffe5fcd0a76029580f06c3f6938ac3d198b47156f3"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3237e56211e03b13df47435b2369f5df281e02b04ad80a948ebd199b7bc10a47"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba0d1da50aab1909b165f615ba1125c8b01fcc30d606c42a61c42ea0269b5e2c"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25b6e8dec29aa5a390092d193abd673e027d2c0b50774ae816a31454286c45c7"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36cd6989ebb2f18fe9af8f13e3c61064b9f741a40d83dc5afeb0322338ad25f2"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47394f8ab7fca3201f40de61fdeea20a2baffb101485ae14901ea89c3f6c95d"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d00ac423542af944302e034e618fb055a0c4e87ba704cd6a79eacfa6ac83a3c9"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a5ca923d1fa632f7a4fb33c0766c6fba7f87141a055c305c3e47e256fb99c413"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:058bf996bcae9aad3acaeeb937d42e0c77c081081e67e24e9578a6a353cb7fb2"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69e2a1f41a3dad94a17aef4a5cc003323359b9f0a9d63d4cc867cb5690a2551d"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67daeeeadb012ec2b59d63cb29c4f2a2023b0c4957c3342d354b8bb44b209e9a"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:54d3d36bbf0d4344d1afa22c58725d1668e30ff9de3a8f56b03db1a6da0acb11"}, + {file = "cytoolz-1.0.1.tar.gz", hash = "sha256:89cc3161b89e1bb3ed7636f74ed2e55984fd35516904fc878cae216e42b2c7d6"}, ] [package.dependencies] @@ -622,6 +792,7 @@ version = "0.3.9" description = "Distribution utilities" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, @@ -629,13 +800,14 @@ files = [ [[package]] name = "eth-abi" -version = "5.1.0" +version = "5.2.0" description = "eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "eth_abi-5.1.0-py3-none-any.whl", hash = "sha256:84cac2626a7db8b7d9ebe62b0fdca676ab1014cc7f777189e3c0cd721a4c16d8"}, - {file = "eth_abi-5.1.0.tar.gz", hash = "sha256:33ddd756206e90f7ddff1330cc8cac4aa411a824fe779314a0a52abea2c8fc14"}, + {file = "eth_abi-5.2.0-py3-none-any.whl", hash = "sha256:17abe47560ad753f18054f5b3089fcb588f3e3a092136a416b6c1502cb7e8877"}, + {file = "eth_abi-5.2.0.tar.gz", hash = "sha256:178703fa98c07d8eecd5ae569e7e8d159e493ebb6eeb534a8fe973fbc4e40ef0"}, ] [package.dependencies] @@ -644,20 +816,21 @@ eth-utils = ">=2.0.0" parsimonious = ">=0.10.0,<0.11.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.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)"] -test = ["eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)"] -tools = ["hypothesis (>=4.18.2,<5.0.0)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "eth-hash[pycryptodome]", "hypothesis (>=6.22.0,<6.108.7)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["eth-hash[pycryptodome]", "hypothesis (>=6.22.0,<6.108.7)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)"] +tools = ["hypothesis (>=6.22.0,<6.108.7)"] [[package]] name = "eth-account" -version = "0.13.4" +version = "0.13.7" description = "eth-account: Sign Ethereum transactions and messages with local private keys" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "eth_account-0.13.4-py3-none-any.whl", hash = "sha256:a4c109e9bad3a278243fcc028b755fb72b43e25b1e6256b3f309a44f5f7d87c3"}, - {file = "eth_account-0.13.4.tar.gz", hash = "sha256:2e1f2de240bef3d9f3d8013656135d2a79b6be6d4e7885bce9cace4334a4a376"}, + {file = "eth_account-0.13.7-py3-none-any.whl", hash = "sha256:39727de8c94d004ff61d10da7587509c04d2dc7eac71e04830135300bdfc6d24"}, + {file = "eth_account-0.13.7.tar.gz", hash = "sha256:5853ecbcbb22e65411176f121f5f24b8afeeaf13492359d254b16d8b18c77a46"}, ] [package.dependencies] @@ -673,30 +846,30 @@ pydantic = ">=2.0.0" rlp = ">=1.0.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "coverage", "hypothesis (>=4.18.0,<5)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -test = ["coverage", "hypothesis (>=4.18.0,<5)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "coverage", "hypothesis (>=6.22.0,<6.108.7)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["coverage", "hypothesis (>=6.22.0,<6.108.7)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-hash" -version = "0.5.2" +version = "0.7.1" description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" optional = false -python-versions = ">=3.7, <4" +python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "eth-hash-0.5.2.tar.gz", hash = "sha256:1b5f10eca7765cc385e1430eefc5ced6e2e463bb18d1365510e2e539c1a6fe4e"}, - {file = "eth_hash-0.5.2-py3-none-any.whl", hash = "sha256:251f62f6579a1e247561679d78df37548bd5f59908da0b159982bf8293ad32f0"}, + {file = "eth_hash-0.7.1-py3-none-any.whl", hash = "sha256:0fb1add2adf99ef28883fd6228eb447ef519ea72933535ad1a0b28c6f65f868a"}, + {file = "eth_hash-0.7.1.tar.gz", hash = "sha256:d2411a403a0b0a62e8247b4117932d900ffb4c8c64b15f92620547ca5ce46be5"}, ] [package.dependencies] pycryptodome = {version = ">=3.6.6,<4", optional = true, markers = "extra == \"pycryptodome\""} [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 (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -doc = ["sphinx (>=6.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)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] pycryptodome = ["pycryptodome (>=3.6.6,<4)"] -pysha3 = ["pysha3 (>=1.0.0,<2.0.0)", "safe-pysha3 (>=1.0.0)"] +pysha3 = ["pysha3 (>=1.0.0,<2.0.0) ; python_version < \"3.9\"", "safe-pysha3 (>=1.0.0) ; python_version >= \"3.9\""] test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] @@ -705,6 +878,7 @@ version = "0.8.1" description = "eth-keyfile: A library for handling the encrypted keyfiles used to store ethereum private keys" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ {file = "eth_keyfile-0.8.1-py3-none-any.whl", hash = "sha256:65387378b82fe7e86d7cb9f8d98e6d639142661b2f6f490629da09fddbef6d64"}, {file = "eth_keyfile-0.8.1.tar.gz", hash = "sha256:9708bc31f386b52cca0969238ff35b1ac72bd7a7186f2a84b86110d3c973bec1"}, @@ -722,13 +896,14 @@ test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-keys" -version = "0.5.1" +version = "0.7.0" description = "eth-keys: Common API for Ethereum key operations" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "eth_keys-0.5.1-py3-none-any.whl", hash = "sha256:ad13d920a2217a49bed3a1a7f54fb0980f53caf86d3bbab2139fd3330a17b97e"}, - {file = "eth_keys-0.5.1.tar.gz", hash = "sha256:2b587e4bbb9ac2195215a7ab0c0fb16042b17d4ec50240ed670bbb8f53da7a48"}, + {file = "eth_keys-0.7.0-py3-none-any.whl", hash = "sha256:b0cdda8ffe8e5ba69c7c5ca33f153828edcace844f67aabd4542d7de38b159cf"}, + {file = "eth_keys-0.7.0.tar.gz", hash = "sha256:79d24fd876201df67741de3e3fefb3f4dbcbb6ace66e47e6fe662851a4547814"}, ] [package.dependencies] @@ -736,232 +911,304 @@ eth-typing = ">=3" eth-utils = ">=2" [package.extras] -coincurve = ["coincurve (>=12.0.0)"] -dev = ["asn1tools (>=0.146.2)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "coincurve (>=12.0.0)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3)", "ipython", "pre-commit (>=3.4.0)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["towncrier (>=21,<22)"] +coincurve = ["coincurve (>=17.0.0)"] +dev = ["asn1tools (>=0.146.2)", "build (>=0.9.0)", "bump_my_version (>=0.19.0)", "coincurve (>=17.0.0)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["towncrier (>=24,<25)"] test = ["asn1tools (>=0.146.2)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)"] [[package]] name = "eth-rlp" -version = "2.1.0" +version = "2.2.0" description = "eth-rlp: RLP definitions for common Ethereum objects in Python" optional = false -python-versions = ">=3.8, <4" +python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "eth-rlp-2.1.0.tar.gz", hash = "sha256:d5b408a8cd20ed496e8e66d0559560d29bc21cee482f893936a1f05d0dddc4a0"}, - {file = "eth_rlp-2.1.0-py3-none-any.whl", hash = "sha256:6f476eb7e37d81feaba5d98aed887e467be92648778c44b19fe594aea209cde1"}, + {file = "eth_rlp-2.2.0-py3-none-any.whl", hash = "sha256:5692d595a741fbaef1203db6a2fedffbd2506d31455a6ad378c8449ee5985c47"}, + {file = "eth_rlp-2.2.0.tar.gz", hash = "sha256:5e4b2eb1b8213e303d6a232dfe35ab8c29e2d3051b86e8d359def80cd21db83d"}, ] [package.dependencies] eth-utils = ">=2.0.0" hexbytes = ">=1.2.0" rlp = ">=0.6.0" -typing-extensions = {version = ">=4.0.1", markers = "python_version <= \"3.10\""} +typing_extensions = {version = ">=4.0.1", markers = "python_version <= \"3.10\""} [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "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)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "eth-hash[pycryptodome]", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] test = ["eth-hash[pycryptodome]", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-typing" -version = "5.0.0" +version = "5.2.1" description = "eth-typing: Common type annotations for ethereum python packages" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "eth_typing-5.0.0-py3-none-any.whl", hash = "sha256:c7ebc8595e7b65175bb4b4176c2b548ab21b13329f2058e84d4f8c289ba9f577"}, - {file = "eth_typing-5.0.0.tar.gz", hash = "sha256:87ce7cee75665c09d2dcff8de1b496609d5e32fcd2e2b1d8fc0370c29eedcdc0"}, + {file = "eth_typing-5.2.1-py3-none-any.whl", hash = "sha256:b0c2812ff978267563b80e9d701f487dd926f1d376d674f3b535cfe28b665d3d"}, + {file = "eth_typing-5.2.1.tar.gz", hash = "sha256:7557300dbf02a93c70fa44af352b5c4a58f94e997a0fd6797fb7d1c29d9538ee"}, ] [package.dependencies] -typing-extensions = ">=4.5.0" +typing_extensions = ">=4.5.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "ipython", "mypy (==1.10.0)", "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)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-utils" -version = "5.0.0" +version = "5.3.0" description = "eth-utils: Common utility functions for python code that interacts with Ethereum" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "eth_utils-5.0.0-py3-none-any.whl", hash = "sha256:99c44eca11db74dbb881a1d70b24cd80436fc62fe527d2f5c3e3cf7932aba7b2"}, - {file = "eth_utils-5.0.0.tar.gz", hash = "sha256:a5eb9555f43f4579eb83cb84f9dda9f3d6663bbd4a5a6b693f8d35045f305a1f"}, + {file = "eth_utils-5.3.0-py3-none-any.whl", hash = "sha256:ac184883ab299d923428bbe25dae5e356979a3993e0ef695a864db0a20bc262d"}, + {file = "eth_utils-5.3.0.tar.gz", hash = "sha256:1f096867ac6be895f456fa3acb26e9573ae66e753abad9208f316d24d6178156"}, ] [package.dependencies] cytoolz = {version = ">=0.10.1", markers = "implementation_name == \"cpython\""} eth-hash = ">=0.3.1" eth-typing = ">=5.0.0" -hexbytes = ">=1.0.0" +pydantic = ">=2.0.0,<3" toolz = {version = ">0.8.2", markers = "implementation_name == \"pypy\""} [package.extras] -dev = ["build (>=0.9.0)", "bump-my-version (>=0.19.0)", "eth-hash[pycryptodome]", "hypothesis (>=4.43.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "eth-hash[pycryptodome]", "hypothesis (>=4.43.0)", "ipython", "mypy (==1.10.0)", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] test = ["hypothesis (>=4.43.0)", "mypy (==1.10.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] +[[package]] +name = "exceptiongroup" +version = "1.3.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\"" +files = [ + {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, + {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "filelock" -version = "3.16.1" +version = "3.18.0" description = "A platform independent file lock." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, - {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, + {file = "filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"}, + {file = "filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] -typing = ["typing-extensions (>=4.12.2)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] +typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] [[package]] name = "frozendict" -version = "2.3.8" +version = "2.4.6" description = "A simple immutable dictionary" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ - {file = "frozendict-2.3.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d188d062084fba0e4bf32719ff7380b26c050b932ff164043ce82ab90587c52b"}, - {file = "frozendict-2.3.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f2a4e818ac457f6354401dcb631527af25e5a20fcfc81e6b5054b45fc245caca"}, - {file = "frozendict-2.3.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a506d807858fa961aaa5b48dab6154fdc6bd045bbe9310788bbff141bb42d13"}, - {file = "frozendict-2.3.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:750632cc890d8ee9484fe6d31b261159144b6efacc08e1317fe46accd1410373"}, - {file = "frozendict-2.3.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ee5fe2658a8ac9a57f748acaf563f6a47f80b8308cbf0a04fac0ba057d41f75"}, - {file = "frozendict-2.3.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23c4bb46e6b8246e1e7e49b5593c2bc09221db0d8f31f7c092be8dfb42b9e620"}, - {file = "frozendict-2.3.8-cp310-cp310-win_amd64.whl", hash = "sha256:c31abc8acea309b132dde441856829f6003a3d242da8b54bce4c0f2a3c8c63f0"}, - {file = "frozendict-2.3.8-cp310-cp310-win_arm64.whl", hash = "sha256:9ea5520e85447ff8d4681e181941e482662817ccba921b7cb3f87922056d892a"}, - {file = "frozendict-2.3.8-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f83fed36497af9562ead5e9fb8443224ba2781786bd3b92b1087cb7d0ff20135"}, - {file = "frozendict-2.3.8-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e27c5c1d29d0eda7979253ec88abc239da1313b38f39f4b16984db3b3e482300"}, - {file = "frozendict-2.3.8-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4c785de7f1a13f15963945f400656b18f057c2fc76c089dacf127a2bb188c03"}, - {file = "frozendict-2.3.8-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8cf35ddd25513428ec152614def9696afb93ae5ec0eb54fa6aa6206eda77ac4c"}, - {file = "frozendict-2.3.8-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ffc684773de7c88724788fa9787d0016fd75830412d58acbd9ed1a04762c675b"}, - {file = "frozendict-2.3.8-cp36-cp36m-win_amd64.whl", hash = "sha256:4c258aab9c8488338634f2ec670ef049dbf0ab0e7a2fa9bc2c7b5009cb614801"}, - {file = "frozendict-2.3.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:47fc26468407fdeb428cfc89495b7921419e670355c21b383765482fdf6c5c14"}, - {file = "frozendict-2.3.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ea638228692db2bf94bce40ea4b25f4077588497b516bd16576575560094bd9"}, - {file = "frozendict-2.3.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a75bf87e76c4386caecdbdd02a99e53ad43a6b5c38fb3d5a634a9fc9ce41462"}, - {file = "frozendict-2.3.8-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ed5a6c5c7a0f57269577c2a338a6002949aea21a23b7b7d06da7e7dced8b605b"}, - {file = "frozendict-2.3.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d086440328a465dea9bef2dbad7548d75d1a0a0d21f43a08c03e1ec79ac5240e"}, - {file = "frozendict-2.3.8-cp37-cp37m-win_amd64.whl", hash = "sha256:0bc4767e2f83db5b701c787e22380296977368b0c57e485ca71b2eedfa11c4a3"}, - {file = "frozendict-2.3.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:638cf363d3cbca31a341503cf2219eac52a5f5140449676fae3d9644cd3c5487"}, - {file = "frozendict-2.3.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b2fd8ce36277919b36e3c834d2389f3cd7ac068ae730c312671dd4439a5dd65"}, - {file = "frozendict-2.3.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3957d52f1906b0c85f641a1911d214255873f6408ab4e5ad657cc27a247fb145"}, - {file = "frozendict-2.3.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72cfe08ab8ae524e54848fa90b22d02c1b1ecfb3064438696bcaa4b953f18772"}, - {file = "frozendict-2.3.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4742e76c4111bd09198d3ab66cef94be8506212311338f9182d6ef5f5cb60493"}, - {file = "frozendict-2.3.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:313ed8d9ba6bac35d7635cd9580ee5721a0fb016f4d2d20f0efa05dbecbdb1be"}, - {file = "frozendict-2.3.8-cp38-cp38-win_amd64.whl", hash = "sha256:d3c6ce943946c2a61501c8cf116fff0892d11dd579877eb36e2aea2c27fddfef"}, - {file = "frozendict-2.3.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0f573dc4861dd7ec9e055c8cceaf45355e894e749f621f199aab7b311ac4bdb"}, - {file = "frozendict-2.3.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b3435e5f1ca5ae68a5e95e64b09d6d5c645cadd6b87569a0b3019dd248c8d00"}, - {file = "frozendict-2.3.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:145afd033ebfade28416093335261b8ec1af5cccc593482309e7add062ec8668"}, - {file = "frozendict-2.3.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da98427de26b5a2865727947480cbb53860089c4d195baa29c539da811cea617"}, - {file = "frozendict-2.3.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5e82befa7c385a668d569cebbebbdf49cee6fea4083f08e869a1b08cfb640a9f"}, - {file = "frozendict-2.3.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80abe81d36e889ceec665e06ec764a7638000fa3e7be09786ac4d3ddc64b76db"}, - {file = "frozendict-2.3.8-cp39-cp39-win_amd64.whl", hash = "sha256:8ccc94ac781710db44e142e1a11ff9b31d02c032c01c6868d51fcbef73086225"}, - {file = "frozendict-2.3.8-cp39-cp39-win_arm64.whl", hash = "sha256:e72dbc1bcc2203cef38d205f692396f5505921a5680f66aa9a7e8bb71fd38f28"}, - {file = "frozendict-2.3.8-py311-none-any.whl", hash = "sha256:ba41a7ed019bd03b62d63ed3f8dea35b8243d1936f7c9ed4b5298ca45a01928e"}, - {file = "frozendict-2.3.8.tar.gz", hash = "sha256:5526559eca8f1780a4ee5146896f59afc31435313560208dd394a3a5e537d3ff"}, + {file = "frozendict-2.4.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c3a05c0a50cab96b4bb0ea25aa752efbfceed5ccb24c007612bc63e51299336f"}, + {file = "frozendict-2.4.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f5b94d5b07c00986f9e37a38dd83c13f5fe3bf3f1ccc8e88edea8fe15d6cd88c"}, + {file = "frozendict-2.4.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4c789fd70879ccb6289a603cdebdc4953e7e5dea047d30c1b180529b28257b5"}, + {file = "frozendict-2.4.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da6a10164c8a50b34b9ab508a9420df38f4edf286b9ca7b7df8a91767baecb34"}, + {file = "frozendict-2.4.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9a8a43036754a941601635ea9c788ebd7a7efbed2becba01b54a887b41b175b9"}, + {file = "frozendict-2.4.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9905dcf7aa659e6a11b8051114c9fa76dfde3a6e50e6dc129d5aece75b449a2"}, + {file = "frozendict-2.4.6-cp310-cp310-win_amd64.whl", hash = "sha256:323f1b674a2cc18f86ab81698e22aba8145d7a755e0ac2cccf142ee2db58620d"}, + {file = "frozendict-2.4.6-cp310-cp310-win_arm64.whl", hash = "sha256:eabd21d8e5db0c58b60d26b4bb9839cac13132e88277e1376970172a85ee04b3"}, + {file = "frozendict-2.4.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:eddabeb769fab1e122d3a6872982c78179b5bcc909fdc769f3cf1964f55a6d20"}, + {file = "frozendict-2.4.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:377a65be0a700188fc21e669c07de60f4f6d35fae8071c292b7df04776a1c27b"}, + {file = "frozendict-2.4.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce1e9217b85eec6ba9560d520d5089c82dbb15f977906eb345d81459723dd7e3"}, + {file = "frozendict-2.4.6-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:7291abacf51798d5ffe632771a69c14fb423ab98d63c4ccd1aa382619afe2f89"}, + {file = "frozendict-2.4.6-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:e72fb86e48811957d66ffb3e95580af7b1af1e6fbd760ad63d7bd79b2c9a07f8"}, + {file = "frozendict-2.4.6-cp36-cp36m-win_amd64.whl", hash = "sha256:622301b1c29c4f9bba633667d592a3a2b093cb408ba3ce578b8901ace3931ef3"}, + {file = "frozendict-2.4.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a4e3737cb99ed03200cd303bdcd5514c9f34b29ee48f405c1184141bd68611c9"}, + {file = "frozendict-2.4.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49ffaf09241bc1417daa19362a2241a4aa435f758fd4375c39ce9790443a39cd"}, + {file = "frozendict-2.4.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d69418479bfb834ba75b0e764f058af46ceee3d655deb6a0dd0c0c1a5e82f09"}, + {file = "frozendict-2.4.6-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:c131f10c4d3906866454c4e89b87a7e0027d533cce8f4652aa5255112c4d6677"}, + {file = "frozendict-2.4.6-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:fc67cbb3c96af7a798fab53d52589752c1673027e516b702ab355510ddf6bdff"}, + {file = "frozendict-2.4.6-cp37-cp37m-win_amd64.whl", hash = "sha256:7730f8ebe791d147a1586cbf6a42629351d4597773317002181b66a2da0d509e"}, + {file = "frozendict-2.4.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:807862e14b0e9665042458fde692c4431d660c4219b9bb240817f5b918182222"}, + {file = "frozendict-2.4.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9647c74efe3d845faa666d4853cfeabbaee403b53270cabfc635b321f770e6b8"}, + {file = "frozendict-2.4.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:665fad3f0f815aa41294e561d98dbedba4b483b3968e7e8cab7d728d64b96e33"}, + {file = "frozendict-2.4.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f42e6b75254ea2afe428ad6d095b62f95a7ae6d4f8272f0bd44a25dddd20f67"}, + {file = "frozendict-2.4.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:02331541611f3897f260900a1815b63389654951126e6e65545e529b63c08361"}, + {file = "frozendict-2.4.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:18d50a2598350b89189da9150058191f55057581e40533e470db46c942373acf"}, + {file = "frozendict-2.4.6-cp38-cp38-win_amd64.whl", hash = "sha256:1b4a3f8f6dd51bee74a50995c39b5a606b612847862203dd5483b9cd91b0d36a"}, + {file = "frozendict-2.4.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a76cee5c4be2a5d1ff063188232fffcce05dde6fd5edd6afe7b75b247526490e"}, + {file = "frozendict-2.4.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba5ef7328706db857a2bdb2c2a17b4cd37c32a19c017cff1bb7eeebc86b0f411"}, + {file = "frozendict-2.4.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:669237c571856be575eca28a69e92a3d18f8490511eff184937283dc6093bd67"}, + {file = "frozendict-2.4.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0aaa11e7c472150efe65adbcd6c17ac0f586896096ab3963775e1c5c58ac0098"}, + {file = "frozendict-2.4.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b8f2829048f29fe115da4a60409be2130e69402e29029339663fac39c90e6e2b"}, + {file = "frozendict-2.4.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:94321e646cc39bebc66954a31edd1847d3a2a3483cf52ff051cd0996e7db07db"}, + {file = "frozendict-2.4.6-cp39-cp39-win_amd64.whl", hash = "sha256:74b6b26c15dddfefddeb89813e455b00ebf78d0a3662b89506b4d55c6445a9f4"}, + {file = "frozendict-2.4.6-cp39-cp39-win_arm64.whl", hash = "sha256:7088102345d1606450bd1801a61139bbaa2cb0d805b9b692f8d81918ea835da6"}, + {file = "frozendict-2.4.6-py311-none-any.whl", hash = "sha256:d065db6a44db2e2375c23eac816f1a022feb2fa98cbb50df44a9e83700accbea"}, + {file = "frozendict-2.4.6-py312-none-any.whl", hash = "sha256:49344abe90fb75f0f9fdefe6d4ef6d4894e640fadab71f11009d52ad97f370b9"}, + {file = "frozendict-2.4.6-py313-none-any.whl", hash = "sha256:7134a2bb95d4a16556bb5f2b9736dceb6ea848fa5b6f3f6c2d6dba93b44b4757"}, + {file = "frozendict-2.4.6.tar.gz", hash = "sha256:df7cd16470fbd26fc4969a208efadc46319334eb97def1ddf48919b351192b8e"}, ] [[package]] name = "frozenlist" -version = "1.4.0" +version = "1.6.0" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, - {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, - {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, - {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, - {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, - {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, - {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, - {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, - {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, - {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, + {file = "frozenlist-1.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e6e558ea1e47fd6fa8ac9ccdad403e5dd5ecc6ed8dda94343056fa4277d5c65e"}, + {file = "frozenlist-1.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f4b3cd7334a4bbc0c472164f3744562cb72d05002cc6fcf58adb104630bbc352"}, + {file = "frozenlist-1.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9799257237d0479736e2b4c01ff26b5c7f7694ac9692a426cb717f3dc02fff9b"}, + {file = "frozenlist-1.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a7bb0fe1f7a70fb5c6f497dc32619db7d2cdd53164af30ade2f34673f8b1fc"}, + {file = "frozenlist-1.6.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:36d2fc099229f1e4237f563b2a3e0ff7ccebc3999f729067ce4e64a97a7f2869"}, + {file = "frozenlist-1.6.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f27a9f9a86dcf00708be82359db8de86b80d029814e6693259befe82bb58a106"}, + {file = "frozenlist-1.6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75ecee69073312951244f11b8627e3700ec2bfe07ed24e3a685a5979f0412d24"}, + {file = "frozenlist-1.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2c7d5aa19714b1b01a0f515d078a629e445e667b9da869a3cd0e6fe7dec78bd"}, + {file = "frozenlist-1.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69bbd454f0fb23b51cadc9bdba616c9678e4114b6f9fa372d462ff2ed9323ec8"}, + {file = "frozenlist-1.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7daa508e75613809c7a57136dec4871a21bca3080b3a8fc347c50b187df4f00c"}, + {file = "frozenlist-1.6.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:89ffdb799154fd4d7b85c56d5fa9d9ad48946619e0eb95755723fffa11022d75"}, + {file = "frozenlist-1.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:920b6bd77d209931e4c263223381d63f76828bec574440f29eb497cf3394c249"}, + {file = "frozenlist-1.6.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d3ceb265249fb401702fce3792e6b44c1166b9319737d21495d3611028d95769"}, + {file = "frozenlist-1.6.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:52021b528f1571f98a7d4258c58aa8d4b1a96d4f01d00d51f1089f2e0323cb02"}, + {file = "frozenlist-1.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0f2ca7810b809ed0f1917293050163c7654cefc57a49f337d5cd9de717b8fad3"}, + {file = "frozenlist-1.6.0-cp310-cp310-win32.whl", hash = "sha256:0e6f8653acb82e15e5443dba415fb62a8732b68fe09936bb6d388c725b57f812"}, + {file = "frozenlist-1.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:f1a39819a5a3e84304cd286e3dc62a549fe60985415851b3337b6f5cc91907f1"}, + {file = "frozenlist-1.6.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae8337990e7a45683548ffb2fee1af2f1ed08169284cd829cdd9a7fa7470530d"}, + {file = "frozenlist-1.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8c952f69dd524558694818a461855f35d36cc7f5c0adddce37e962c85d06eac0"}, + {file = "frozenlist-1.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8f5fef13136c4e2dee91bfb9a44e236fff78fc2cd9f838eddfc470c3d7d90afe"}, + {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:716bbba09611b4663ecbb7cd022f640759af8259e12a6ca939c0a6acd49eedba"}, + {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7b8c4dc422c1a3ffc550b465090e53b0bf4839047f3e436a34172ac67c45d595"}, + {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b11534872256e1666116f6587a1592ef395a98b54476addb5e8d352925cb5d4a"}, + {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c6eceb88aaf7221f75be6ab498dc622a151f5f88d536661af3ffc486245a626"}, + {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62c828a5b195570eb4b37369fcbbd58e96c905768d53a44d13044355647838ff"}, + {file = "frozenlist-1.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1c6bd2c6399920c9622362ce95a7d74e7f9af9bfec05fff91b8ce4b9647845a"}, + {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:49ba23817781e22fcbd45fd9ff2b9b8cdb7b16a42a4851ab8025cae7b22e96d0"}, + {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:431ef6937ae0f853143e2ca67d6da76c083e8b1fe3df0e96f3802fd37626e606"}, + {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9d124b38b3c299ca68433597ee26b7819209cb8a3a9ea761dfe9db3a04bba584"}, + {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:118e97556306402e2b010da1ef21ea70cb6d6122e580da64c056b96f524fbd6a"}, + {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fb3b309f1d4086b5533cf7bbcf3f956f0ae6469664522f1bde4feed26fba60f1"}, + {file = "frozenlist-1.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54dece0d21dce4fdb188a1ffc555926adf1d1c516e493c2914d7c370e454bc9e"}, + {file = "frozenlist-1.6.0-cp311-cp311-win32.whl", hash = "sha256:654e4ba1d0b2154ca2f096bed27461cf6160bc7f504a7f9a9ef447c293caf860"}, + {file = "frozenlist-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e911391bffdb806001002c1f860787542f45916c3baf764264a52765d5a5603"}, + {file = "frozenlist-1.6.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c5b9e42ace7d95bf41e19b87cec8f262c41d3510d8ad7514ab3862ea2197bfb1"}, + {file = "frozenlist-1.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ca9973735ce9f770d24d5484dcb42f68f135351c2fc81a7a9369e48cf2998a29"}, + {file = "frozenlist-1.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6ac40ec76041c67b928ca8aaffba15c2b2ee3f5ae8d0cb0617b5e63ec119ca25"}, + {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95b7a8a3180dfb280eb044fdec562f9b461614c0ef21669aea6f1d3dac6ee576"}, + {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c444d824e22da6c9291886d80c7d00c444981a72686e2b59d38b285617cb52c8"}, + {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb52c8166499a8150bfd38478248572c924c003cbb45fe3bcd348e5ac7c000f9"}, + {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b35298b2db9c2468106278537ee529719228950a5fdda686582f68f247d1dc6e"}, + {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d108e2d070034f9d57210f22fefd22ea0d04609fc97c5f7f5a686b3471028590"}, + {file = "frozenlist-1.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e1be9111cb6756868ac242b3c2bd1f09d9aea09846e4f5c23715e7afb647103"}, + {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:94bb451c664415f02f07eef4ece976a2c65dcbab9c2f1705b7031a3a75349d8c"}, + {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d1a686d0b0949182b8faddea596f3fc11f44768d1f74d4cad70213b2e139d821"}, + {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ea8e59105d802c5a38bdbe7362822c522230b3faba2aa35c0fa1765239b7dd70"}, + {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:abc4e880a9b920bc5020bf6a431a6bb40589d9bca3975c980495f63632e8382f"}, + {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9a79713adfe28830f27a3c62f6b5406c37376c892b05ae070906f07ae4487046"}, + {file = "frozenlist-1.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a0318c2068e217a8f5e3b85e35899f5a19e97141a45bb925bb357cfe1daf770"}, + {file = "frozenlist-1.6.0-cp312-cp312-win32.whl", hash = "sha256:853ac025092a24bb3bf09ae87f9127de9fe6e0c345614ac92536577cf956dfcc"}, + {file = "frozenlist-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:2bdfe2d7e6c9281c6e55523acd6c2bf77963cb422fdc7d142fb0cb6621b66878"}, + {file = "frozenlist-1.6.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1d7fb014fe0fbfee3efd6a94fc635aeaa68e5e1720fe9e57357f2e2c6e1a647e"}, + {file = "frozenlist-1.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01bcaa305a0fdad12745502bfd16a1c75b14558dabae226852f9159364573117"}, + {file = "frozenlist-1.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b314faa3051a6d45da196a2c495e922f987dc848e967d8cfeaee8a0328b1cd4"}, + {file = "frozenlist-1.6.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da62fecac21a3ee10463d153549d8db87549a5e77eefb8c91ac84bb42bb1e4e3"}, + {file = "frozenlist-1.6.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1eb89bf3454e2132e046f9599fbcf0a4483ed43b40f545551a39316d0201cd1"}, + {file = "frozenlist-1.6.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18689b40cb3936acd971f663ccb8e2589c45db5e2c5f07e0ec6207664029a9c"}, + {file = "frozenlist-1.6.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e67ddb0749ed066b1a03fba812e2dcae791dd50e5da03be50b6a14d0c1a9ee45"}, + {file = "frozenlist-1.6.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc5e64626e6682638d6e44398c9baf1d6ce6bc236d40b4b57255c9d3f9761f1f"}, + {file = "frozenlist-1.6.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:437cfd39564744ae32ad5929e55b18ebd88817f9180e4cc05e7d53b75f79ce85"}, + {file = "frozenlist-1.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:62dd7df78e74d924952e2feb7357d826af8d2f307557a779d14ddf94d7311be8"}, + {file = "frozenlist-1.6.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a66781d7e4cddcbbcfd64de3d41a61d6bdde370fc2e38623f30b2bd539e84a9f"}, + {file = "frozenlist-1.6.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:482fe06e9a3fffbcd41950f9d890034b4a54395c60b5e61fae875d37a699813f"}, + {file = "frozenlist-1.6.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e4f9373c500dfc02feea39f7a56e4f543e670212102cc2eeb51d3a99c7ffbde6"}, + {file = "frozenlist-1.6.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e69bb81de06827147b7bfbaeb284d85219fa92d9f097e32cc73675f279d70188"}, + {file = "frozenlist-1.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7613d9977d2ab4a9141dde4a149f4357e4065949674c5649f920fec86ecb393e"}, + {file = "frozenlist-1.6.0-cp313-cp313-win32.whl", hash = "sha256:4def87ef6d90429f777c9d9de3961679abf938cb6b7b63d4a7eb8a268babfce4"}, + {file = "frozenlist-1.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:37a8a52c3dfff01515e9bbbee0e6063181362f9de3db2ccf9bc96189b557cbfd"}, + {file = "frozenlist-1.6.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:46138f5a0773d064ff663d273b309b696293d7a7c00a0994c5c13a5078134b64"}, + {file = "frozenlist-1.6.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f88bc0a2b9c2a835cb888b32246c27cdab5740059fb3688852bf91e915399b91"}, + {file = "frozenlist-1.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:777704c1d7655b802c7850255639672e90e81ad6fa42b99ce5ed3fbf45e338dd"}, + {file = "frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85ef8d41764c7de0dcdaf64f733a27352248493a85a80661f3c678acd27e31f2"}, + {file = "frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:da5cb36623f2b846fb25009d9d9215322318ff1c63403075f812b3b2876c8506"}, + {file = "frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cbb56587a16cf0fb8acd19e90ff9924979ac1431baea8681712716a8337577b0"}, + {file = "frozenlist-1.6.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6154c3ba59cda3f954c6333025369e42c3acd0c6e8b6ce31eb5c5b8116c07e0"}, + {file = "frozenlist-1.6.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e8246877afa3f1ae5c979fe85f567d220f86a50dc6c493b9b7d8191181ae01e"}, + {file = "frozenlist-1.6.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b0f6cce16306d2e117cf9db71ab3a9e8878a28176aeaf0dbe35248d97b28d0c"}, + {file = "frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1b8e8cd8032ba266f91136d7105706ad57770f3522eac4a111d77ac126a25a9b"}, + {file = "frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:e2ada1d8515d3ea5378c018a5f6d14b4994d4036591a52ceaf1a1549dec8e1ad"}, + {file = "frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:cdb2c7f071e4026c19a3e32b93a09e59b12000751fc9b0b7758da899e657d215"}, + {file = "frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:03572933a1969a6d6ab509d509e5af82ef80d4a5d4e1e9f2e1cdd22c77a3f4d2"}, + {file = "frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:77effc978947548b676c54bbd6a08992759ea6f410d4987d69feea9cd0919911"}, + {file = "frozenlist-1.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a2bda8be77660ad4089caf2223fdbd6db1858462c4b85b67fbfa22102021e497"}, + {file = "frozenlist-1.6.0-cp313-cp313t-win32.whl", hash = "sha256:a4d96dc5bcdbd834ec6b0f91027817214216b5b30316494d2b1aebffb87c534f"}, + {file = "frozenlist-1.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e18036cb4caa17ea151fd5f3d70be9d354c99eb8cf817a3ccde8a7873b074348"}, + {file = "frozenlist-1.6.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:536a1236065c29980c15c7229fbb830dedf809708c10e159b8136534233545f0"}, + {file = "frozenlist-1.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ed5e3a4462ff25ca84fb09e0fada8ea267df98a450340ead4c91b44857267d70"}, + {file = "frozenlist-1.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e19c0fc9f4f030fcae43b4cdec9e8ab83ffe30ec10c79a4a43a04d1af6c5e1ad"}, + {file = "frozenlist-1.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c608f833897501dac548585312d73a7dca028bf3b8688f0d712b7acfaf7fb3"}, + {file = "frozenlist-1.6.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0dbae96c225d584f834b8d3cc688825911960f003a85cb0fd20b6e5512468c42"}, + {file = "frozenlist-1.6.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:625170a91dd7261a1d1c2a0c1a353c9e55d21cd67d0852185a5fef86587e6f5f"}, + {file = "frozenlist-1.6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1db8b2fc7ee8a940b547a14c10e56560ad3ea6499dc6875c354e2335812f739d"}, + {file = "frozenlist-1.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4da6fc43048b648275a220e3a61c33b7fff65d11bdd6dcb9d9c145ff708b804c"}, + {file = "frozenlist-1.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ef8e7e8f2f3820c5f175d70fdd199b79e417acf6c72c5d0aa8f63c9f721646f"}, + {file = "frozenlist-1.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:aa733d123cc78245e9bb15f29b44ed9e5780dc6867cfc4e544717b91f980af3b"}, + {file = "frozenlist-1.6.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ba7f8d97152b61f22d7f59491a781ba9b177dd9f318486c5fbc52cde2db12189"}, + {file = "frozenlist-1.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:56a0b8dd6d0d3d971c91f1df75e824986667ccce91e20dca2023683814344791"}, + {file = "frozenlist-1.6.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:5c9e89bf19ca148efcc9e3c44fd4c09d5af85c8a7dd3dbd0da1cb83425ef4983"}, + {file = "frozenlist-1.6.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:1330f0a4376587face7637dfd245380a57fe21ae8f9d360c1c2ef8746c4195fa"}, + {file = "frozenlist-1.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2187248203b59625566cac53572ec8c2647a140ee2738b4e36772930377a533c"}, + {file = "frozenlist-1.6.0-cp39-cp39-win32.whl", hash = "sha256:2b8cf4cfea847d6c12af06091561a89740f1f67f331c3fa8623391905e878530"}, + {file = "frozenlist-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:1255d5d64328c5a0d066ecb0f02034d086537925f1f04b50b1ae60d37afbf572"}, + {file = "frozenlist-1.6.0-py3-none-any.whl", hash = "sha256:535eec9987adb04701266b92745d6cdcef2e77669299359c3009c3404dd5d191"}, + {file = "frozenlist-1.6.0.tar.gz", hash = "sha256:b99655c32c1c8e06d111e7f41c06c29a5318cb1835df23a45518e02a47c63b68"}, ] [[package]] name = "hexbytes" -version = "1.2.1" +version = "1.3.1" description = "hexbytes: Python `bytes` subclass that decodes hex, with a readable console output" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "hexbytes-1.2.1-py3-none-any.whl", hash = "sha256:e64890b203a31f4a23ef11470ecfcca565beaee9198df623047df322b757471a"}, - {file = "hexbytes-1.2.1.tar.gz", hash = "sha256:515f00dddf31053db4d0d7636dd16061c1d896c3109b8e751005db4ca46bcca7"}, + {file = "hexbytes-1.3.1-py3-none-any.whl", hash = "sha256:da01ff24a1a9a2b1881c4b85f0e9f9b0f51b526b379ffa23832ae7899d29c2c7"}, + {file = "hexbytes-1.3.1.tar.gz", hash = "sha256:a657eebebdfe27254336f98d8af6e2236f3f83aed164b87466b6cf6c5f5a4765"}, ] [package.extras] -dev = ["build (>=0.9.0)", "bump-my-version (>=0.19.0)", "eth-utils (>=2.0.0)", "hypothesis (>=3.44.24,<=6.31.6)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -test = ["eth-utils (>=2.0.0)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "eth_utils (>=2.0.0)", "hypothesis (>=3.44.24)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["eth_utils (>=2.0.0)", "hypothesis (>=3.44.24)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "identify" -version = "2.6.4" +version = "2.6.12" description = "File identification library for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "identify-2.6.4-py2.py3-none-any.whl", hash = "sha256:993b0f01b97e0568c179bb9196391ff391bfb88a99099dbf5ce392b68f42d0af"}, - {file = "identify-2.6.4.tar.gz", hash = "sha256:285a7d27e397652e8cafe537a6cc97dd470a970f48fb2e9d979aa38eae5513ac"}, + {file = "identify-2.6.12-py2.py3-none-any.whl", hash = "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2"}, + {file = "identify-2.6.12.tar.gz", hash = "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6"}, ] [package.extras] @@ -969,13 +1216,29 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.4" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" +groups = ["main"] +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "iniconfig" +version = "2.1.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] [[package]] @@ -984,6 +1247,7 @@ version = "0.6.1" description = "An ISO 8601 date/time/duration parser and formatter" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"}, {file = "isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9"}, @@ -994,200 +1258,277 @@ six = "*" [[package]] name = "lxml" -version = "4.9.3" +version = "5.4.0" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" -files = [ - {file = "lxml-4.9.3-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c"}, - {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d"}, - {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef"}, - {file = "lxml-4.9.3-cp27-cp27m-win32.whl", hash = "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7"}, - {file = "lxml-4.9.3-cp27-cp27m-win_amd64.whl", hash = "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1"}, - {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb"}, - {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e"}, - {file = "lxml-4.9.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76"}, - {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23"}, - {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f"}, - {file = "lxml-4.9.3-cp310-cp310-win32.whl", hash = "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85"}, - {file = "lxml-4.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d"}, - {file = "lxml-4.9.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b"}, - {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120"}, - {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6"}, - {file = "lxml-4.9.3-cp311-cp311-win32.whl", hash = "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305"}, - {file = "lxml-4.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc"}, - {file = "lxml-4.9.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4"}, - {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be"}, - {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13"}, - {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9"}, - {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5"}, - {file = "lxml-4.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8"}, - {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7"}, - {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2"}, - {file = "lxml-4.9.3-cp35-cp35m-win32.whl", hash = "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d"}, - {file = "lxml-4.9.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833"}, - {file = "lxml-4.9.3-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584"}, - {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287"}, - {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458"}, - {file = "lxml-4.9.3-cp36-cp36m-win32.whl", hash = "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477"}, - {file = "lxml-4.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4"}, - {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a"}, - {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02"}, - {file = "lxml-4.9.3-cp37-cp37m-win32.whl", hash = "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f"}, - {file = "lxml-4.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa"}, - {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40"}, - {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7"}, - {file = "lxml-4.9.3-cp38-cp38-win32.whl", hash = "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574"}, - {file = "lxml-4.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96"}, - {file = "lxml-4.9.3-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432"}, - {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69"}, - {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50"}, - {file = "lxml-4.9.3-cp39-cp39-win32.whl", hash = "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2"}, - {file = "lxml-4.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2"}, - {file = "lxml-4.9.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35"}, - {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0"}, - {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3"}, - {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9"}, - {file = "lxml-4.9.3.tar.gz", hash = "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c"}, +python-versions = ">=3.6" +groups = ["main"] +files = [ + {file = "lxml-5.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e7bc6df34d42322c5289e37e9971d6ed114e3776b45fa879f734bded9d1fea9c"}, + {file = "lxml-5.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6854f8bd8a1536f8a1d9a3655e6354faa6406621cf857dc27b681b69860645c7"}, + {file = "lxml-5.4.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:696ea9e87442467819ac22394ca36cb3d01848dad1be6fac3fb612d3bd5a12cf"}, + {file = "lxml-5.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ef80aeac414f33c24b3815ecd560cee272786c3adfa5f31316d8b349bfade28"}, + {file = "lxml-5.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b9c2754cef6963f3408ab381ea55f47dabc6f78f4b8ebb0f0b25cf1ac1f7609"}, + {file = "lxml-5.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7a62cc23d754bb449d63ff35334acc9f5c02e6dae830d78dab4dd12b78a524f4"}, + {file = "lxml-5.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f82125bc7203c5ae8633a7d5d20bcfdff0ba33e436e4ab0abc026a53a8960b7"}, + {file = "lxml-5.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:b67319b4aef1a6c56576ff544b67a2a6fbd7eaee485b241cabf53115e8908b8f"}, + {file = "lxml-5.4.0-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:a8ef956fce64c8551221f395ba21d0724fed6b9b6242ca4f2f7beb4ce2f41997"}, + {file = "lxml-5.4.0-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:0a01ce7d8479dce84fc03324e3b0c9c90b1ece9a9bb6a1b6c9025e7e4520e78c"}, + {file = "lxml-5.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:91505d3ddebf268bb1588eb0f63821f738d20e1e7f05d3c647a5ca900288760b"}, + {file = "lxml-5.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a3bcdde35d82ff385f4ede021df801b5c4a5bcdfb61ea87caabcebfc4945dc1b"}, + {file = "lxml-5.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aea7c06667b987787c7d1f5e1dfcd70419b711cdb47d6b4bb4ad4b76777a0563"}, + {file = "lxml-5.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a7fb111eef4d05909b82152721a59c1b14d0f365e2be4c742a473c5d7372f4f5"}, + {file = "lxml-5.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:43d549b876ce64aa18b2328faff70f5877f8c6dede415f80a2f799d31644d776"}, + {file = "lxml-5.4.0-cp310-cp310-win32.whl", hash = "sha256:75133890e40d229d6c5837b0312abbe5bac1c342452cf0e12523477cd3aa21e7"}, + {file = "lxml-5.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:de5b4e1088523e2b6f730d0509a9a813355b7f5659d70eb4f319c76beea2e250"}, + {file = "lxml-5.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:98a3912194c079ef37e716ed228ae0dcb960992100461b704aea4e93af6b0bb9"}, + {file = "lxml-5.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ea0252b51d296a75f6118ed0d8696888e7403408ad42345d7dfd0d1e93309a7"}, + {file = "lxml-5.4.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b92b69441d1bd39f4940f9eadfa417a25862242ca2c396b406f9272ef09cdcaa"}, + {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20e16c08254b9b6466526bc1828d9370ee6c0d60a4b64836bc3ac2917d1e16df"}, + {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7605c1c32c3d6e8c990dd28a0970a3cbbf1429d5b92279e37fda05fb0c92190e"}, + {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ecf4c4b83f1ab3d5a7ace10bafcb6f11df6156857a3c418244cef41ca9fa3e44"}, + {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cef4feae82709eed352cd7e97ae062ef6ae9c7b5dbe3663f104cd2c0e8d94ba"}, + {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:df53330a3bff250f10472ce96a9af28628ff1f4efc51ccba351a8820bca2a8ba"}, + {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:aefe1a7cb852fa61150fcb21a8c8fcea7b58c4cb11fbe59c97a0a4b31cae3c8c"}, + {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:ef5a7178fcc73b7d8c07229e89f8eb45b2908a9238eb90dcfc46571ccf0383b8"}, + {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d2ed1b3cb9ff1c10e6e8b00941bb2e5bb568b307bfc6b17dffbbe8be5eecba86"}, + {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:72ac9762a9f8ce74c9eed4a4e74306f2f18613a6b71fa065495a67ac227b3056"}, + {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f5cb182f6396706dc6cc1896dd02b1c889d644c081b0cdec38747573db88a7d7"}, + {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:3a3178b4873df8ef9457a4875703488eb1622632a9cee6d76464b60e90adbfcd"}, + {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e094ec83694b59d263802ed03a8384594fcce477ce484b0cbcd0008a211ca751"}, + {file = "lxml-5.4.0-cp311-cp311-win32.whl", hash = "sha256:4329422de653cdb2b72afa39b0aa04252fca9071550044904b2e7036d9d97fe4"}, + {file = "lxml-5.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd3be6481ef54b8cfd0e1e953323b7aa9d9789b94842d0e5b142ef4bb7999539"}, + {file = "lxml-5.4.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b5aff6f3e818e6bdbbb38e5967520f174b18f539c2b9de867b1e7fde6f8d95a4"}, + {file = "lxml-5.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:942a5d73f739ad7c452bf739a62a0f83e2578afd6b8e5406308731f4ce78b16d"}, + {file = "lxml-5.4.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:460508a4b07364d6abf53acaa0a90b6d370fafde5693ef37602566613a9b0779"}, + {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:529024ab3a505fed78fe3cc5ddc079464e709f6c892733e3f5842007cec8ac6e"}, + {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ca56ebc2c474e8f3d5761debfd9283b8b18c76c4fc0967b74aeafba1f5647f9"}, + {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a81e1196f0a5b4167a8dafe3a66aa67c4addac1b22dc47947abd5d5c7a3f24b5"}, + {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00b8686694423ddae324cf614e1b9659c2edb754de617703c3d29ff568448df5"}, + {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:c5681160758d3f6ac5b4fea370495c48aac0989d6a0f01bb9a72ad8ef5ab75c4"}, + {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:2dc191e60425ad70e75a68c9fd90ab284df64d9cd410ba8d2b641c0c45bc006e"}, + {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:67f779374c6b9753ae0a0195a892a1c234ce8416e4448fe1e9f34746482070a7"}, + {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:79d5bfa9c1b455336f52343130b2067164040604e41f6dc4d8313867ed540079"}, + {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3d3c30ba1c9b48c68489dc1829a6eede9873f52edca1dda900066542528d6b20"}, + {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1af80c6316ae68aded77e91cd9d80648f7dd40406cef73df841aa3c36f6907c8"}, + {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4d885698f5019abe0de3d352caf9466d5de2baded00a06ef3f1216c1a58ae78f"}, + {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aea53d51859b6c64e7c51d522c03cc2c48b9b5d6172126854cc7f01aa11f52bc"}, + {file = "lxml-5.4.0-cp312-cp312-win32.whl", hash = "sha256:d90b729fd2732df28130c064aac9bb8aff14ba20baa4aee7bd0795ff1187545f"}, + {file = "lxml-5.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1dc4ca99e89c335a7ed47d38964abcb36c5910790f9bd106f2a8fa2ee0b909d2"}, + {file = "lxml-5.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:773e27b62920199c6197130632c18fb7ead3257fce1ffb7d286912e56ddb79e0"}, + {file = "lxml-5.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ce9c671845de9699904b1e9df95acfe8dfc183f2310f163cdaa91a3535af95de"}, + {file = "lxml-5.4.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9454b8d8200ec99a224df8854786262b1bd6461f4280064c807303c642c05e76"}, + {file = "lxml-5.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cccd007d5c95279e529c146d095f1d39ac05139de26c098166c4beb9374b0f4d"}, + {file = "lxml-5.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0fce1294a0497edb034cb416ad3e77ecc89b313cff7adbee5334e4dc0d11f422"}, + {file = "lxml-5.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:24974f774f3a78ac12b95e3a20ef0931795ff04dbb16db81a90c37f589819551"}, + {file = "lxml-5.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:497cab4d8254c2a90bf988f162ace2ddbfdd806fce3bda3f581b9d24c852e03c"}, + {file = "lxml-5.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:e794f698ae4c5084414efea0f5cc9f4ac562ec02d66e1484ff822ef97c2cadff"}, + {file = "lxml-5.4.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:2c62891b1ea3094bb12097822b3d44b93fc6c325f2043c4d2736a8ff09e65f60"}, + {file = "lxml-5.4.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:142accb3e4d1edae4b392bd165a9abdee8a3c432a2cca193df995bc3886249c8"}, + {file = "lxml-5.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1a42b3a19346e5601d1b8296ff6ef3d76038058f311902edd574461e9c036982"}, + {file = "lxml-5.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4291d3c409a17febf817259cb37bc62cb7eb398bcc95c1356947e2871911ae61"}, + {file = "lxml-5.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4f5322cf38fe0e21c2d73901abf68e6329dc02a4994e483adbcf92b568a09a54"}, + {file = "lxml-5.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0be91891bdb06ebe65122aa6bf3fc94489960cf7e03033c6f83a90863b23c58b"}, + {file = "lxml-5.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:15a665ad90054a3d4f397bc40f73948d48e36e4c09f9bcffc7d90c87410e478a"}, + {file = "lxml-5.4.0-cp313-cp313-win32.whl", hash = "sha256:d5663bc1b471c79f5c833cffbc9b87d7bf13f87e055a5c86c363ccd2348d7e82"}, + {file = "lxml-5.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:bcb7a1096b4b6b24ce1ac24d4942ad98f983cd3810f9711bcd0293f43a9d8b9f"}, + {file = "lxml-5.4.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7be701c24e7f843e6788353c055d806e8bd8466b52907bafe5d13ec6a6dbaecd"}, + {file = "lxml-5.4.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb54f7c6bafaa808f27166569b1511fc42701a7713858dddc08afdde9746849e"}, + {file = "lxml-5.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97dac543661e84a284502e0cf8a67b5c711b0ad5fb661d1bd505c02f8cf716d7"}, + {file = "lxml-5.4.0-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:c70e93fba207106cb16bf852e421c37bbded92acd5964390aad07cb50d60f5cf"}, + {file = "lxml-5.4.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9c886b481aefdf818ad44846145f6eaf373a20d200b5ce1a5c8e1bc2d8745410"}, + {file = "lxml-5.4.0-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:fa0e294046de09acd6146be0ed6727d1f42ded4ce3ea1e9a19c11b6774eea27c"}, + {file = "lxml-5.4.0-cp36-cp36m-win32.whl", hash = "sha256:61c7bbf432f09ee44b1ccaa24896d21075e533cd01477966a5ff5a71d88b2f56"}, + {file = "lxml-5.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7ce1a171ec325192c6a636b64c94418e71a1964f56d002cc28122fceff0b6121"}, + {file = "lxml-5.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:795f61bcaf8770e1b37eec24edf9771b307df3af74d1d6f27d812e15a9ff3872"}, + {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29f451a4b614a7b5b6c2e043d7b64a15bd8304d7e767055e8ab68387a8cacf4e"}, + {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:891f7f991a68d20c75cb13c5c9142b2a3f9eb161f1f12a9489c82172d1f133c0"}, + {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4aa412a82e460571fad592d0f93ce9935a20090029ba08eca05c614f99b0cc92"}, + {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:ac7ba71f9561cd7d7b55e1ea5511543c0282e2b6450f122672a2694621d63b7e"}, + {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:c5d32f5284012deaccd37da1e2cd42f081feaa76981f0eaa474351b68df813c5"}, + {file = "lxml-5.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:ce31158630a6ac85bddd6b830cffd46085ff90498b397bd0a259f59d27a12188"}, + {file = "lxml-5.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:31e63621e073e04697c1b2d23fcb89991790eef370ec37ce4d5d469f40924ed6"}, + {file = "lxml-5.4.0-cp37-cp37m-win32.whl", hash = "sha256:be2ba4c3c5b7900246a8f866580700ef0d538f2ca32535e991027bdaba944063"}, + {file = "lxml-5.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:09846782b1ef650b321484ad429217f5154da4d6e786636c38e434fa32e94e49"}, + {file = "lxml-5.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eaf24066ad0b30917186420d51e2e3edf4b0e2ea68d8cd885b14dc8afdcf6556"}, + {file = "lxml-5.4.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b31a3a77501d86d8ade128abb01082724c0dfd9524f542f2f07d693c9f1175f"}, + {file = "lxml-5.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e108352e203c7afd0eb91d782582f00a0b16a948d204d4dec8565024fafeea5"}, + {file = "lxml-5.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11a96c3b3f7551c8a8109aa65e8594e551d5a84c76bf950da33d0fb6dfafab7"}, + {file = "lxml-5.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:ca755eebf0d9e62d6cb013f1261e510317a41bf4650f22963474a663fdfe02aa"}, + {file = "lxml-5.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:4cd915c0fb1bed47b5e6d6edd424ac25856252f09120e3e8ba5154b6b921860e"}, + {file = "lxml-5.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:226046e386556a45ebc787871d6d2467b32c37ce76c2680f5c608e25823ffc84"}, + {file = "lxml-5.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b108134b9667bcd71236c5a02aad5ddd073e372fb5d48ea74853e009fe38acb6"}, + {file = "lxml-5.4.0-cp38-cp38-win32.whl", hash = "sha256:1320091caa89805df7dcb9e908add28166113dcd062590668514dbd510798c88"}, + {file = "lxml-5.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:073eb6dcdf1f587d9b88c8c93528b57eccda40209cf9be549d469b942b41d70b"}, + {file = "lxml-5.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bda3ea44c39eb74e2488297bb39d47186ed01342f0022c8ff407c250ac3f498e"}, + {file = "lxml-5.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9ceaf423b50ecfc23ca00b7f50b64baba85fb3fb91c53e2c9d00bc86150c7e40"}, + {file = "lxml-5.4.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:664cdc733bc87449fe781dbb1f309090966c11cc0c0cd7b84af956a02a8a4729"}, + {file = "lxml-5.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67ed8a40665b84d161bae3181aa2763beea3747f748bca5874b4af4d75998f87"}, + {file = "lxml-5.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b4a3bd174cc9cdaa1afbc4620c049038b441d6ba07629d89a83b408e54c35cd"}, + {file = "lxml-5.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:b0989737a3ba6cf2a16efb857fb0dfa20bc5c542737fddb6d893fde48be45433"}, + {file = "lxml-5.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:dc0af80267edc68adf85f2a5d9be1cdf062f973db6790c1d065e45025fa26140"}, + {file = "lxml-5.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:639978bccb04c42677db43c79bdaa23785dc7f9b83bfd87570da8207872f1ce5"}, + {file = "lxml-5.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a99d86351f9c15e4a901fc56404b485b1462039db59288b203f8c629260a142"}, + {file = "lxml-5.4.0-cp39-cp39-win32.whl", hash = "sha256:3e6d5557989cdc3ebb5302bbdc42b439733a841891762ded9514e74f60319ad6"}, + {file = "lxml-5.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:a8c9b7f16b63e65bbba889acb436a1034a82d34fa09752d754f88d708eca80e1"}, + {file = "lxml-5.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1b717b00a71b901b4667226bba282dd462c42ccf618ade12f9ba3674e1fabc55"}, + {file = "lxml-5.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27a9ded0f0b52098ff89dd4c418325b987feed2ea5cc86e8860b0f844285d740"}, + {file = "lxml-5.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b7ce10634113651d6f383aa712a194179dcd496bd8c41e191cec2099fa09de5"}, + {file = "lxml-5.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:53370c26500d22b45182f98847243efb518d268374a9570409d2e2276232fd37"}, + {file = "lxml-5.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c6364038c519dffdbe07e3cf42e6a7f8b90c275d4d1617a69bb59734c1a2d571"}, + {file = "lxml-5.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b12cb6527599808ada9eb2cd6e0e7d3d8f13fe7bbb01c6311255a15ded4c7ab4"}, + {file = "lxml-5.4.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5f11a1526ebd0dee85e7b1e39e39a0cc0d9d03fb527f56d8457f6df48a10dc0c"}, + {file = "lxml-5.4.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48b4afaf38bf79109bb060d9016fad014a9a48fb244e11b94f74ae366a64d252"}, + {file = "lxml-5.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de6f6bb8a7840c7bf216fb83eec4e2f79f7325eca8858167b68708b929ab2172"}, + {file = "lxml-5.4.0-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5cca36a194a4eb4e2ed6be36923d3cffd03dcdf477515dea687185506583d4c9"}, + {file = "lxml-5.4.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b7c86884ad23d61b025989d99bfdd92a7351de956e01c61307cb87035960bcb1"}, + {file = "lxml-5.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:53d9469ab5460402c19553b56c3648746774ecd0681b1b27ea74d5d8a3ef5590"}, + {file = "lxml-5.4.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:56dbdbab0551532bb26c19c914848d7251d73edb507c3079d6805fa8bba5b706"}, + {file = "lxml-5.4.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14479c2ad1cb08b62bb941ba8e0e05938524ee3c3114644df905d2331c76cd57"}, + {file = "lxml-5.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32697d2ea994e0db19c1df9e40275ffe84973e4232b5c274f47e7c1ec9763cdd"}, + {file = "lxml-5.4.0-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:24f6df5f24fc3385f622c0c9d63fe34604893bc1a5bdbb2dbf5870f85f9a404a"}, + {file = "lxml-5.4.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:151d6c40bc9db11e960619d2bf2ec5829f0aaffb10b41dcf6ad2ce0f3c0b2325"}, + {file = "lxml-5.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4025bf2884ac4370a3243c5aa8d66d3cb9e15d3ddd0af2d796eccc5f0244390e"}, + {file = "lxml-5.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9459e6892f59ecea2e2584ee1058f5d8f629446eab52ba2305ae13a32a059530"}, + {file = "lxml-5.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47fb24cc0f052f0576ea382872b3fc7e1f7e3028e53299ea751839418ade92a6"}, + {file = "lxml-5.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50441c9de951a153c698b9b99992e806b71c1f36d14b154592580ff4a9d0d877"}, + {file = "lxml-5.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ab339536aa798b1e17750733663d272038bf28069761d5be57cb4a9b0137b4f8"}, + {file = "lxml-5.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9776af1aad5a4b4a1317242ee2bea51da54b2a7b7b48674be736d463c999f37d"}, + {file = "lxml-5.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:63e7968ff83da2eb6fdda967483a7a023aa497d85ad8f05c3ad9b1f2e8c84987"}, + {file = "lxml-5.4.0.tar.gz", hash = "sha256:d12832e1dbea4be280b22fd0ea7c9b87f0d8fc51ba06e92dc62d52f804f78ebd"}, ] [package.extras] cssselect = ["cssselect (>=0.7)"] +html-clean = ["lxml_html_clean"] html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=0.29.35)"] +source = ["Cython (>=3.0.11,<3.1.0)"] [[package]] name = "multidict" -version = "6.0.4" +version = "6.4.4" description = "multidict implementation" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, + {file = "multidict-6.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8adee3ac041145ffe4488ea73fa0a622b464cc25340d98be76924d0cda8545ff"}, + {file = "multidict-6.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b61e98c3e2a861035aaccd207da585bdcacef65fe01d7a0d07478efac005e028"}, + {file = "multidict-6.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:75493f28dbadecdbb59130e74fe935288813301a8554dc32f0c631b6bdcdf8b0"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc3c6a37e048b5395ee235e4a2a0d639c2349dffa32d9367a42fc20d399772"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:87cb72263946b301570b0f63855569a24ee8758aaae2cd182aae7d95fbc92ca7"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bbf7bd39822fd07e3609b6b4467af4c404dd2b88ee314837ad1830a7f4a8299"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1f7cbd4f1f44ddf5fd86a8675b7679176eae770f2fc88115d6dddb6cefb59bc"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb5ac9e5bfce0e6282e7f59ff7b7b9a74aa8e5c60d38186a4637f5aa764046ad"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4efc31dfef8c4eeb95b6b17d799eedad88c4902daba39ce637e23a17ea078915"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9fcad2945b1b91c29ef2b4050f590bfcb68d8ac8e0995a74e659aa57e8d78e01"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:d877447e7368c7320832acb7159557e49b21ea10ffeb135c1077dbbc0816b598"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:33a12ebac9f380714c298cbfd3e5b9c0c4e89c75fe612ae496512ee51028915f"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0f14ea68d29b43a9bf37953881b1e3eb75b2739e896ba4a6aa4ad4c5b9ffa145"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0327ad2c747a6600e4797d115d3c38a220fdb28e54983abe8964fd17e95ae83c"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d1a20707492db9719a05fc62ee215fd2c29b22b47c1b1ba347f9abc831e26683"}, + {file = "multidict-6.4.4-cp310-cp310-win32.whl", hash = "sha256:d83f18315b9fca5db2452d1881ef20f79593c4aa824095b62cb280019ef7aa3d"}, + {file = "multidict-6.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:9c17341ee04545fd962ae07330cb5a39977294c883485c8d74634669b1f7fe04"}, + {file = "multidict-6.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4f5f29794ac0e73d2a06ac03fd18870adc0135a9d384f4a306a951188ed02f95"}, + {file = "multidict-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c04157266344158ebd57b7120d9b0b35812285d26d0e78193e17ef57bfe2979a"}, + {file = "multidict-6.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bb61ffd3ab8310d93427e460f565322c44ef12769f51f77277b4abad7b6f7223"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e0ba18a9afd495f17c351d08ebbc4284e9c9f7971d715f196b79636a4d0de44"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9faf1b1dcaadf9f900d23a0e6d6c8eadd6a95795a0e57fcca73acce0eb912065"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a4d1cb1327c6082c4fce4e2a438483390964c02213bc6b8d782cf782c9b1471f"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:941f1bec2f5dbd51feeb40aea654c2747f811ab01bdd3422a48a4e4576b7d76a"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5f8a146184da7ea12910a4cec51ef85e44f6268467fb489c3caf0cd512f29c2"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:232b7237e57ec3c09be97206bfb83a0aa1c5d7d377faa019c68a210fa35831f1"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:55ae0721c1513e5e3210bca4fc98456b980b0c2c016679d3d723119b6b202c42"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:51d662c072579f63137919d7bb8fc250655ce79f00c82ecf11cab678f335062e"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0e05c39962baa0bb19a6b210e9b1422c35c093b651d64246b6c2e1a7e242d9fd"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5b1cc3ab8c31d9ebf0faa6e3540fb91257590da330ffe6d2393d4208e638925"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:93ec84488a384cd7b8a29c2c7f467137d8a73f6fe38bb810ecf29d1ade011a7c"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b308402608493638763abc95f9dc0030bbd6ac6aff784512e8ac3da73a88af08"}, + {file = "multidict-6.4.4-cp311-cp311-win32.whl", hash = "sha256:343892a27d1a04d6ae455ecece12904d242d299ada01633d94c4f431d68a8c49"}, + {file = "multidict-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:73484a94f55359780c0f458bbd3c39cb9cf9c182552177d2136e828269dee529"}, + {file = "multidict-6.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dc388f75a1c00000824bf28b7633e40854f4127ede80512b44c3cfeeea1839a2"}, + {file = "multidict-6.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:98af87593a666f739d9dba5d0ae86e01b0e1a9cfcd2e30d2d361fbbbd1a9162d"}, + {file = "multidict-6.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aff4cafea2d120327d55eadd6b7f1136a8e5a0ecf6fb3b6863e8aca32cd8e50a"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:169c4ba7858176b797fe551d6e99040c531c775d2d57b31bcf4de6d7a669847f"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b9eb4c59c54421a32b3273d4239865cb14ead53a606db066d7130ac80cc8ec93"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7cf3bd54c56aa16fdb40028d545eaa8d051402b61533c21e84046e05513d5780"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f682c42003c7264134bfe886376299db4cc0c6cd06a3295b41b347044bcb5482"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920f9cf2abdf6e493c519492d892c362007f113c94da4c239ae88429835bad1"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:530d86827a2df6504526106b4c104ba19044594f8722d3e87714e847c74a0275"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ecde56ea2439b96ed8a8d826b50c57364612ddac0438c39e473fafad7ae1c23b"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:dc8c9736d8574b560634775ac0def6bdc1661fc63fa27ffdfc7264c565bcb4f2"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7f3d3b3c34867579ea47cbd6c1f2ce23fbfd20a273b6f9e3177e256584f1eacc"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:87a728af265e08f96b6318ebe3c0f68b9335131f461efab2fc64cc84a44aa6ed"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9f193eeda1857f8e8d3079a4abd258f42ef4a4bc87388452ed1e1c4d2b0c8740"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be06e73c06415199200e9a2324a11252a3d62030319919cde5e6950ffeccf72e"}, + {file = "multidict-6.4.4-cp312-cp312-win32.whl", hash = "sha256:622f26ea6a7e19b7c48dd9228071f571b2fbbd57a8cd71c061e848f281550e6b"}, + {file = "multidict-6.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:5e2bcda30d5009996ff439e02a9f2b5c3d64a20151d34898c000a6281faa3781"}, + {file = "multidict-6.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:82ffabefc8d84c2742ad19c37f02cde5ec2a1ee172d19944d380f920a340e4b9"}, + {file = "multidict-6.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6a2f58a66fe2c22615ad26156354005391e26a2f3721c3621504cd87c1ea87bf"}, + {file = "multidict-6.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5883d6ee0fd9d8a48e9174df47540b7545909841ac82354c7ae4cbe9952603bd"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9abcf56a9511653fa1d052bfc55fbe53dbee8f34e68bd6a5a038731b0ca42d15"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6ed5ae5605d4ad5a049fad2a28bb7193400700ce2f4ae484ab702d1e3749c3f9"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbfcb60396f9bcfa63e017a180c3105b8c123a63e9d1428a36544e7d37ca9e20"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0f1987787f5f1e2076b59692352ab29a955b09ccc433c1f6b8e8e18666f608b"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d0121ccce8c812047d8d43d691a1ad7641f72c4f730474878a5aeae1b8ead8c"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83ec4967114295b8afd120a8eec579920c882831a3e4c3331d591a8e5bfbbc0f"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:995f985e2e268deaf17867801b859a282e0448633f1310e3704b30616d269d69"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d832c608f94b9f92a0ec8b7e949be7792a642b6e535fcf32f3e28fab69eeb046"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d21c1212171cf7da703c5b0b7a0e85be23b720818aef502ad187d627316d5645"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:cbebaa076aaecad3d4bb4c008ecc73b09274c952cf6a1b78ccfd689e51f5a5b0"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:c93a6fb06cc8e5d3628b2b5fda215a5db01e8f08fc15fadd65662d9b857acbe4"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8cd8f81f1310182362fb0c7898145ea9c9b08a71081c5963b40ee3e3cac589b1"}, + {file = "multidict-6.4.4-cp313-cp313-win32.whl", hash = "sha256:3e9f1cd61a0ab857154205fb0b1f3d3ace88d27ebd1409ab7af5096e409614cd"}, + {file = "multidict-6.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:8ffb40b74400e4455785c2fa37eba434269149ec525fc8329858c862e4b35373"}, + {file = "multidict-6.4.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:6a602151dbf177be2450ef38966f4be3467d41a86c6a845070d12e17c858a156"}, + {file = "multidict-6.4.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0d2b9712211b860d123815a80b859075d86a4d54787e247d7fbee9db6832cf1c"}, + {file = "multidict-6.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d2fa86af59f8fc1972e121ade052145f6da22758f6996a197d69bb52f8204e7e"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50855d03e9e4d66eab6947ba688ffb714616f985838077bc4b490e769e48da51"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5bce06b83be23225be1905dcdb6b789064fae92499fbc458f59a8c0e68718601"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66ed0731f8e5dfd8369a883b6e564aca085fb9289aacabd9decd70568b9a30de"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:329ae97fc2f56f44d91bc47fe0972b1f52d21c4b7a2ac97040da02577e2daca2"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c27e5dcf520923d6474d98b96749e6805f7677e93aaaf62656005b8643f907ab"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:058cc59b9e9b143cc56715e59e22941a5d868c322242278d28123a5d09cdf6b0"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:69133376bc9a03f8c47343d33f91f74a99c339e8b58cea90433d8e24bb298031"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:d6b15c55721b1b115c5ba178c77104123745b1417527ad9641a4c5e2047450f0"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:a887b77f51d3d41e6e1a63cf3bc7ddf24de5939d9ff69441387dfefa58ac2e26"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:632a3bf8f1787f7ef7d3c2f68a7bde5be2f702906f8b5842ad6da9d974d0aab3"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:a145c550900deb7540973c5cdb183b0d24bed6b80bf7bddf33ed8f569082535e"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc5d83c6619ca5c9672cb78b39ed8542f1975a803dee2cda114ff73cbb076edd"}, + {file = "multidict-6.4.4-cp313-cp313t-win32.whl", hash = "sha256:3312f63261b9df49be9d57aaa6abf53a6ad96d93b24f9cc16cf979956355ce6e"}, + {file = "multidict-6.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:ba852168d814b2c73333073e1c7116d9395bea69575a01b0b3c89d2d5a87c8fb"}, + {file = "multidict-6.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:603f39bd1cf85705c6c1ba59644b480dfe495e6ee2b877908de93322705ad7cf"}, + {file = "multidict-6.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc60f91c02e11dfbe3ff4e1219c085695c339af72d1641800fe6075b91850c8f"}, + {file = "multidict-6.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:496bcf01c76a70a31c3d746fd39383aad8d685ce6331e4c709e9af4ced5fa221"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4219390fb5bf8e548e77b428bb36a21d9382960db5321b74d9d9987148074d6b"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef4e9096ff86dfdcbd4a78253090ba13b1d183daa11b973e842465d94ae1772"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49a29d7133b1fc214e818bbe025a77cc6025ed9a4f407d2850373ddde07fd04a"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e32053d6d3a8b0dfe49fde05b496731a0e6099a4df92154641c00aa76786aef5"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc403092a49509e8ef2d2fd636a8ecefc4698cc57bbe894606b14579bc2a955"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5363f9b2a7f3910e5c87d8b1855c478c05a2dc559ac57308117424dfaad6805c"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e543a40e4946cf70a88a3be87837a3ae0aebd9058ba49e91cacb0b2cd631e2b"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:60d849912350da557fe7de20aa8cf394aada6980d0052cc829eeda4a0db1c1db"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:19d08b4f22eae45bb018b9f06e2838c1e4b853c67628ef8ae126d99de0da6395"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d693307856d1ef08041e8b6ff01d5b4618715007d288490ce2c7e29013c12b9a"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fad6daaed41021934917f4fb03ca2db8d8a4d79bf89b17ebe77228eb6710c003"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c10d17371bff801af0daf8b073c30b6cf14215784dc08cd5c43ab5b7b8029bbc"}, + {file = "multidict-6.4.4-cp39-cp39-win32.whl", hash = "sha256:7e23f2f841fcb3ebd4724a40032d32e0892fbba4143e43d2a9e7695c5e50e6bd"}, + {file = "multidict-6.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:4d7b50b673ffb4ff4366e7ab43cf1f0aef4bd3608735c5fbdf0bdb6f690da411"}, + {file = "multidict-6.4.4-py3-none-any.whl", hash = "sha256:bd4557071b561a8b3b6075c3ce93cf9bfb6182cb241805c3d66ced3b75eff4ac"}, + {file = "multidict-6.4.4.tar.gz", hash = "sha256:69ee9e6ba214b5245031b76233dd95408a0fd57fdb019ddcc1ead4790932a8e8"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} + [[package]] name = "nodeenv" version = "1.9.1" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, @@ -1195,64 +1536,67 @@ files = [ [[package]] name = "numpy" -version = "2.1.2" +version = "2.2.6" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ - {file = "numpy-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30d53720b726ec36a7f88dc873f0eec8447fbc93d93a8f079dfac2629598d6ee"}, - {file = "numpy-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d3ca0a72dd8846eb6f7dfe8f19088060fcb76931ed592d29128e0219652884"}, - {file = "numpy-2.1.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:fc44e3c68ff00fd991b59092a54350e6e4911152682b4782f68070985aa9e648"}, - {file = "numpy-2.1.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:7c1c60328bd964b53f8b835df69ae8198659e2b9302ff9ebb7de4e5a5994db3d"}, - {file = "numpy-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6cdb606a7478f9ad91c6283e238544451e3a95f30fb5467fbf715964341a8a86"}, - {file = "numpy-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d666cb72687559689e9906197e3bec7b736764df6a2e58ee265e360663e9baf7"}, - {file = "numpy-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6eef7a2dbd0abfb0d9eaf78b73017dbfd0b54051102ff4e6a7b2980d5ac1a03"}, - {file = "numpy-2.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12edb90831ff481f7ef5f6bc6431a9d74dc0e5ff401559a71e5e4611d4f2d466"}, - {file = "numpy-2.1.2-cp310-cp310-win32.whl", hash = "sha256:a65acfdb9c6ebb8368490dbafe83c03c7e277b37e6857f0caeadbbc56e12f4fb"}, - {file = "numpy-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:860ec6e63e2c5c2ee5e9121808145c7bf86c96cca9ad396c0bd3e0f2798ccbe2"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b42a1a511c81cc78cbc4539675713bbcf9d9c3913386243ceff0e9429ca892fe"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:faa88bc527d0f097abdc2c663cddf37c05a1c2f113716601555249805cf573f1"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:c82af4b2ddd2ee72d1fc0c6695048d457e00b3582ccde72d8a1c991b808bb20f"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:13602b3174432a35b16c4cfb5de9a12d229727c3dd47a6ce35111f2ebdf66ff4"}, - {file = "numpy-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ebec5fd716c5a5b3d8dfcc439be82a8407b7b24b230d0ad28a81b61c2f4659a"}, - {file = "numpy-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2b49c3c0804e8ecb05d59af8386ec2f74877f7ca8fd9c1e00be2672e4d399b1"}, - {file = "numpy-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2cbba4b30bf31ddbe97f1c7205ef976909a93a66bb1583e983adbd155ba72ac2"}, - {file = "numpy-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8e00ea6fc82e8a804433d3e9cedaa1051a1422cb6e443011590c14d2dea59146"}, - {file = "numpy-2.1.2-cp311-cp311-win32.whl", hash = "sha256:5006b13a06e0b38d561fab5ccc37581f23c9511879be7693bd33c7cd15ca227c"}, - {file = "numpy-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:f1eb068ead09f4994dec71c24b2844f1e4e4e013b9629f812f292f04bd1510d9"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7bf0a4f9f15b32b5ba53147369e94296f5fffb783db5aacc1be15b4bf72f43b"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b1d0fcae4f0949f215d4632be684a539859b295e2d0cb14f78ec231915d644db"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:f751ed0a2f250541e19dfca9f1eafa31a392c71c832b6bb9e113b10d050cb0f1"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:bd33f82e95ba7ad632bc57837ee99dba3d7e006536200c4e9124089e1bf42426"}, - {file = "numpy-2.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b8cde4f11f0a975d1fd59373b32e2f5a562ade7cde4f85b7137f3de8fbb29a0"}, - {file = "numpy-2.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d95f286b8244b3649b477ac066c6906fbb2905f8ac19b170e2175d3d799f4df"}, - {file = "numpy-2.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ab4754d432e3ac42d33a269c8567413bdb541689b02d93788af4131018cbf366"}, - {file = "numpy-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e585c8ae871fd38ac50598f4763d73ec5497b0de9a0ab4ef5b69f01c6a046142"}, - {file = "numpy-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9c6c754df29ce6a89ed23afb25550d1c2d5fdb9901d9c67a16e0b16eaf7e2550"}, - {file = "numpy-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:456e3b11cb79ac9946c822a56346ec80275eaf2950314b249b512896c0d2505e"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a84498e0d0a1174f2b3ed769b67b656aa5460c92c9554039e11f20a05650f00d"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4d6ec0d4222e8ffdab1744da2560f07856421b367928026fb540e1945f2eeeaf"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:259ec80d54999cc34cd1eb8ded513cb053c3bf4829152a2e00de2371bd406f5e"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:675c741d4739af2dc20cd6c6a5c4b7355c728167845e3c6b0e824e4e5d36a6c3"}, - {file = "numpy-2.1.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b2d4e667895cc55e3ff2b56077e4c8a5604361fc21a042845ea3ad67465aa8"}, - {file = "numpy-2.1.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43cca367bf94a14aca50b89e9bc2061683116cfe864e56740e083392f533ce7a"}, - {file = "numpy-2.1.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:76322dcdb16fccf2ac56f99048af32259dcc488d9b7e25b51e5eca5147a3fb98"}, - {file = "numpy-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:32e16a03138cabe0cb28e1007ee82264296ac0983714094380b408097a418cfe"}, - {file = "numpy-2.1.2-cp313-cp313-win32.whl", hash = "sha256:242b39d00e4944431a3cd2db2f5377e15b5785920421993770cddb89992c3f3a"}, - {file = "numpy-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:f2ded8d9b6f68cc26f8425eda5d3877b47343e68ca23d0d0846f4d312ecaa445"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ffef621c14ebb0188a8633348504a35c13680d6da93ab5cb86f4e54b7e922b5"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ad369ed238b1959dfbade9018a740fb9392c5ac4f9b5173f420bd4f37ba1f7a0"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d82075752f40c0ddf57e6e02673a17f6cb0f8eb3f587f63ca1eaab5594da5b17"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:1600068c262af1ca9580a527d43dc9d959b0b1d8e56f8a05d830eea39b7c8af6"}, - {file = "numpy-2.1.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a26ae94658d3ba3781d5e103ac07a876b3e9b29db53f68ed7df432fd033358a8"}, - {file = "numpy-2.1.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13311c2db4c5f7609b462bc0f43d3c465424d25c626d95040f073e30f7570e35"}, - {file = "numpy-2.1.2-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:2abbf905a0b568706391ec6fa15161fad0fb5d8b68d73c461b3c1bab6064dd62"}, - {file = "numpy-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ef444c57d664d35cac4e18c298c47d7b504c66b17c2ea91312e979fcfbdfb08a"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:bdd407c40483463898b84490770199d5714dcc9dd9b792f6c6caccc523c00952"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:da65fb46d4cbb75cb417cddf6ba5e7582eb7bb0b47db4b99c9fe5787ce5d91f5"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c193d0b0238638e6fc5f10f1b074a6993cb13b0b431f64079a509d63d3aa8b7"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a7d80b2e904faa63068ead63107189164ca443b42dd1930299e0d1cb041cec2e"}, - {file = "numpy-2.1.2.tar.gz", hash = "sha256:13532a088217fa624c99b843eeb54640de23b3414b14aa66d023805eb731066c"}, + {file = "numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb"}, + {file = "numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90"}, + {file = "numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163"}, + {file = "numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf"}, + {file = "numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83"}, + {file = "numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915"}, + {file = "numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680"}, + {file = "numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289"}, + {file = "numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d"}, + {file = "numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3"}, + {file = "numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae"}, + {file = "numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a"}, + {file = "numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42"}, + {file = "numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491"}, + {file = "numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a"}, + {file = "numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf"}, + {file = "numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1"}, + {file = "numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab"}, + {file = "numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47"}, + {file = "numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303"}, + {file = "numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff"}, + {file = "numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c"}, + {file = "numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3"}, + {file = "numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282"}, + {file = "numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87"}, + {file = "numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249"}, + {file = "numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49"}, + {file = "numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de"}, + {file = "numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4"}, + {file = "numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2"}, + {file = "numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84"}, + {file = "numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b"}, + {file = "numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d"}, + {file = "numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566"}, + {file = "numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f"}, + {file = "numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f"}, + {file = "numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868"}, + {file = "numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d"}, + {file = "numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd"}, + {file = "numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c"}, + {file = "numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6"}, + {file = "numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda"}, + {file = "numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40"}, + {file = "numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8"}, + {file = "numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f"}, + {file = "numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa"}, + {file = "numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571"}, + {file = "numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1"}, + {file = "numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff"}, + {file = "numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06"}, + {file = "numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d"}, + {file = "numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db"}, + {file = "numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543"}, + {file = "numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00"}, + {file = "numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd"}, ] [[package]] @@ -1261,6 +1605,7 @@ version = "2.1.1" description = "Python implementation of the JSON-LD API" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "OT-PyLD-2.1.1.tar.gz", hash = "sha256:2fa40126a09a238bcbf96e903a36744675dfd2ad6e1579928ce9f2225faeeb26"}, {file = "OT_PyLD-2.1.1-py3-none-any.whl", hash = "sha256:106ce2a7d0026fa22ef2777b88a44dc1d1c9f87116aefe743289b566947cc67f"}, @@ -1277,12 +1622,25 @@ cachetools = ["cachetools"] frozendict = ["frozendict"] requests = ["requests"] +[[package]] +name = "packaging" +version = "25.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, +] + [[package]] name = "pandas" version = "2.2.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, @@ -1369,6 +1727,7 @@ version = "0.10.0" description = "(Soon to be) the fastest pure-Python PEG parser I could muster" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f"}, {file = "parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c"}, @@ -1379,29 +1738,47 @@ regex = ">=2022.3.15" [[package]] name = "platformdirs" -version = "4.3.6" +version = "4.3.8" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, + {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] + +[[package]] +name = "pluggy" +version = "1.6.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, - {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.11.2)"] +dev = ["pre-commit", "tox"] +testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "4.0.1" +version = "4.2.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "pre_commit-4.0.1-py2.py3-none-any.whl", hash = "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878"}, - {file = "pre_commit-4.0.1.tar.gz", hash = "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2"}, + {file = "pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd"}, + {file = "pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146"}, ] [package.dependencies] @@ -1411,166 +1788,294 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" +[[package]] +name = "propcache" +version = "0.3.1" +description = "Accelerated property cache" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "propcache-0.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f27785888d2fdd918bc36de8b8739f2d6c791399552333721b58193f68ea3e98"}, + {file = "propcache-0.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4e89cde74154c7b5957f87a355bb9c8ec929c167b59c83d90654ea36aeb6180"}, + {file = "propcache-0.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:730178f476ef03d3d4d255f0c9fa186cb1d13fd33ffe89d39f2cda4da90ceb71"}, + {file = "propcache-0.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:967a8eec513dbe08330f10137eacb427b2ca52118769e82ebcfcab0fba92a649"}, + {file = "propcache-0.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b9145c35cc87313b5fd480144f8078716007656093d23059e8993d3a8fa730f"}, + {file = "propcache-0.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e64e948ab41411958670f1093c0a57acfdc3bee5cf5b935671bbd5313bcf229"}, + {file = "propcache-0.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:319fa8765bfd6a265e5fa661547556da381e53274bc05094fc9ea50da51bfd46"}, + {file = "propcache-0.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c66d8ccbc902ad548312b96ed8d5d266d0d2c6d006fd0f66323e9d8f2dd49be7"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2d219b0dbabe75e15e581fc1ae796109b07c8ba7d25b9ae8d650da582bed01b0"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:cd6a55f65241c551eb53f8cf4d2f4af33512c39da5d9777694e9d9c60872f519"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9979643ffc69b799d50d3a7b72b5164a2e97e117009d7af6dfdd2ab906cb72cd"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4cf9e93a81979f1424f1a3d155213dc928f1069d697e4353edb8a5eba67c6259"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2fce1df66915909ff6c824bbb5eb403d2d15f98f1518e583074671a30fe0c21e"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4d0dfdd9a2ebc77b869a0b04423591ea8823f791293b527dc1bb896c1d6f1136"}, + {file = "propcache-0.3.1-cp310-cp310-win32.whl", hash = "sha256:1f6cc0ad7b4560e5637eb2c994e97b4fa41ba8226069c9277eb5ea7101845b42"}, + {file = "propcache-0.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:47ef24aa6511e388e9894ec16f0fbf3313a53ee68402bc428744a367ec55b833"}, + {file = "propcache-0.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5"}, + {file = "propcache-0.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371"}, + {file = "propcache-0.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da"}, + {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744"}, + {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0"}, + {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5"}, + {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256"}, + {file = "propcache-0.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9"}, + {file = "propcache-0.3.1-cp311-cp311-win32.whl", hash = "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005"}, + {file = "propcache-0.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7"}, + {file = "propcache-0.3.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723"}, + {file = "propcache-0.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976"}, + {file = "propcache-0.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b"}, + {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f"}, + {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70"}, + {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7"}, + {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25"}, + {file = "propcache-0.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7"}, + {file = "propcache-0.3.1-cp312-cp312-win32.whl", hash = "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b"}, + {file = "propcache-0.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3"}, + {file = "propcache-0.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8"}, + {file = "propcache-0.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f"}, + {file = "propcache-0.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111"}, + {file = "propcache-0.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d249609e547c04d190e820d0d4c8ca03ed4582bcf8e4e160a6969ddfb57b62e5"}, + {file = "propcache-0.3.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ced33d827625d0a589e831126ccb4f5c29dfdf6766cac441d23995a65825dcb"}, + {file = "propcache-0.3.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4114c4ada8f3181af20808bedb250da6bae56660e4b8dfd9cd95d4549c0962f7"}, + {file = "propcache-0.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:975af16f406ce48f1333ec5e912fe11064605d5c5b3f6746969077cc3adeb120"}, + {file = "propcache-0.3.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a34aa3a1abc50740be6ac0ab9d594e274f59960d3ad253cd318af76b996dd654"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9cec3239c85ed15bfaded997773fdad9fb5662b0a7cbc854a43f291eb183179e"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:05543250deac8e61084234d5fc54f8ebd254e8f2b39a16b1dce48904f45b744b"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5cb5918253912e088edbf023788de539219718d3b10aef334476b62d2b53de53"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f3bbecd2f34d0e6d3c543fdb3b15d6b60dd69970c2b4c822379e5ec8f6f621d5"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aca63103895c7d960a5b9b044a83f544b233c95e0dcff114389d64d762017af7"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a0a9898fdb99bf11786265468571e628ba60af80dc3f6eb89a3545540c6b0ef"}, + {file = "propcache-0.3.1-cp313-cp313-win32.whl", hash = "sha256:3a02a28095b5e63128bcae98eb59025924f121f048a62393db682f049bf4ac24"}, + {file = "propcache-0.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:813fbb8b6aea2fc9659815e585e548fe706d6f663fa73dff59a1677d4595a037"}, + {file = "propcache-0.3.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a444192f20f5ce8a5e52761a031b90f5ea6288b1eef42ad4c7e64fef33540b8f"}, + {file = "propcache-0.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0fbe94666e62ebe36cd652f5fc012abfbc2342de99b523f8267a678e4dfdee3c"}, + {file = "propcache-0.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f011f104db880f4e2166bcdcf7f58250f7a465bc6b068dc84c824a3d4a5c94dc"}, + {file = "propcache-0.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e584b6d388aeb0001d6d5c2bd86b26304adde6d9bb9bfa9c4889805021b96de"}, + {file = "propcache-0.3.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a17583515a04358b034e241f952f1715243482fc2c2945fd99a1b03a0bd77d6"}, + {file = "propcache-0.3.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5aed8d8308215089c0734a2af4f2e95eeb360660184ad3912686c181e500b2e7"}, + {file = "propcache-0.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d8e309ff9a0503ef70dc9a0ebd3e69cf7b3894c9ae2ae81fc10943c37762458"}, + {file = "propcache-0.3.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b655032b202028a582d27aeedc2e813299f82cb232f969f87a4fde491a233f11"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f64d91b751df77931336b5ff7bafbe8845c5770b06630e27acd5dbb71e1931c"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:19a06db789a4bd896ee91ebc50d059e23b3639c25d58eb35be3ca1cbe967c3bf"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:bef100c88d8692864651b5f98e871fb090bd65c8a41a1cb0ff2322db39c96c27"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:87380fb1f3089d2a0b8b00f006ed12bd41bd858fabfa7330c954c70f50ed8757"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e474fc718e73ba5ec5180358aa07f6aded0ff5f2abe700e3115c37d75c947e18"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:17d1c688a443355234f3c031349da69444be052613483f3e4158eef751abcd8a"}, + {file = "propcache-0.3.1-cp313-cp313t-win32.whl", hash = "sha256:359e81a949a7619802eb601d66d37072b79b79c2505e6d3fd8b945538411400d"}, + {file = "propcache-0.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e7fb9a84c9abbf2b2683fa3e7b0d7da4d8ecf139a1c635732a8bda29c5214b0e"}, + {file = "propcache-0.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ed5f6d2edbf349bd8d630e81f474d33d6ae5d07760c44d33cd808e2f5c8f4ae6"}, + {file = "propcache-0.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:668ddddc9f3075af019f784456267eb504cb77c2c4bd46cc8402d723b4d200bf"}, + {file = "propcache-0.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0c86e7ceea56376216eba345aa1fc6a8a6b27ac236181f840d1d7e6a1ea9ba5c"}, + {file = "propcache-0.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83be47aa4e35b87c106fc0c84c0fc069d3f9b9b06d3c494cd404ec6747544894"}, + {file = "propcache-0.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:27c6ac6aa9fc7bc662f594ef380707494cb42c22786a558d95fcdedb9aa5d035"}, + {file = "propcache-0.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64a956dff37080b352c1c40b2966b09defb014347043e740d420ca1eb7c9b908"}, + {file = "propcache-0.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82de5da8c8893056603ac2d6a89eb8b4df49abf1a7c19d536984c8dd63f481d5"}, + {file = "propcache-0.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c3c3a203c375b08fd06a20da3cf7aac293b834b6f4f4db71190e8422750cca5"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b303b194c2e6f171cfddf8b8ba30baefccf03d36a4d9cab7fd0bb68ba476a3d7"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:916cd229b0150129d645ec51614d38129ee74c03293a9f3f17537be0029a9641"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a461959ead5b38e2581998700b26346b78cd98540b5524796c175722f18b0294"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:069e7212890b0bcf9b2be0a03afb0c2d5161d91e1bf51569a64f629acc7defbf"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ef2e4e91fb3945769e14ce82ed53007195e616a63aa43b40fb7ebaaf907c8d4c"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8638f99dca15b9dff328fb6273e09f03d1c50d9b6512f3b65a4154588a7595fe"}, + {file = "propcache-0.3.1-cp39-cp39-win32.whl", hash = "sha256:6f173bbfe976105aaa890b712d1759de339d8a7cef2fc0a1714cc1a1e1c47f64"}, + {file = "propcache-0.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:603f1fe4144420374f1a69b907494c3acbc867a581c2d49d4175b0de7cc64566"}, + {file = "propcache-0.3.1-py3-none-any.whl", hash = "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40"}, + {file = "propcache-0.3.1.tar.gz", hash = "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf"}, +] + [[package]] name = "pycryptodome" -version = "3.19.0" +version = "3.23.0" description = "Cryptographic library for Python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "pycryptodome-3.19.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3006c44c4946583b6de24fe0632091c2653d6256b99a02a3db71ca06472ea1e4"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:7c760c8a0479a4042111a8dd2f067d3ae4573da286c53f13cf6f5c53a5c1f631"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:08ce3558af5106c632baf6d331d261f02367a6bc3733086ae43c0f988fe042db"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45430dfaf1f421cf462c0dd824984378bef32b22669f2635cb809357dbaab405"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:a9bcd5f3794879e91970f2bbd7d899780541d3ff439d8f2112441769c9f2ccea"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-win32.whl", hash = "sha256:190c53f51e988dceb60472baddce3f289fa52b0ec38fbe5fd20dd1d0f795c551"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-win_amd64.whl", hash = "sha256:22e0ae7c3a7f87dcdcf302db06ab76f20e83f09a6993c160b248d58274473bfa"}, - {file = "pycryptodome-3.19.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:7822f36d683f9ad7bc2145b2c2045014afdbbd1d9922a6d4ce1cbd6add79a01e"}, - {file = "pycryptodome-3.19.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:05e33267394aad6db6595c0ce9d427fe21552f5425e116a925455e099fdf759a"}, - {file = "pycryptodome-3.19.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:829b813b8ee00d9c8aba417621b94bc0b5efd18c928923802ad5ba4cf1ec709c"}, - {file = "pycryptodome-3.19.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:fc7a79590e2b5d08530175823a242de6790abc73638cc6dc9d2684e7be2f5e49"}, - {file = "pycryptodome-3.19.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:542f99d5026ac5f0ef391ba0602f3d11beef8e65aae135fa5b762f5ebd9d3bfb"}, - {file = "pycryptodome-3.19.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:61bb3ccbf4bf32ad9af32da8badc24e888ae5231c617947e0f5401077f8b091f"}, - {file = "pycryptodome-3.19.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d49a6c715d8cceffedabb6adb7e0cbf41ae1a2ff4adaeec9432074a80627dea1"}, - {file = "pycryptodome-3.19.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e249a784cc98a29c77cea9df54284a44b40cafbfae57636dd2f8775b48af2434"}, - {file = "pycryptodome-3.19.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d033947e7fd3e2ba9a031cb2d267251620964705a013c5a461fa5233cc025270"}, - {file = "pycryptodome-3.19.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:84c3e4fffad0c4988aef0d5591be3cad4e10aa7db264c65fadbc633318d20bde"}, - {file = "pycryptodome-3.19.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:139ae2c6161b9dd5d829c9645d781509a810ef50ea8b657e2257c25ca20efe33"}, - {file = "pycryptodome-3.19.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:5b1986c761258a5b4332a7f94a83f631c1ffca8747d75ab8395bf2e1b93283d9"}, - {file = "pycryptodome-3.19.0-cp35-abi3-win32.whl", hash = "sha256:536f676963662603f1f2e6ab01080c54d8cd20f34ec333dcb195306fa7826997"}, - {file = "pycryptodome-3.19.0-cp35-abi3-win_amd64.whl", hash = "sha256:04dd31d3b33a6b22ac4d432b3274588917dcf850cc0c51c84eca1d8ed6933810"}, - {file = "pycryptodome-3.19.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:8999316e57abcbd8085c91bc0ef75292c8618f41ca6d2b6132250a863a77d1e7"}, - {file = "pycryptodome-3.19.0-pp27-pypy_73-win32.whl", hash = "sha256:a0ab84755f4539db086db9ba9e9f3868d2e3610a3948cbd2a55e332ad83b01b0"}, - {file = "pycryptodome-3.19.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0101f647d11a1aae5a8ce4f5fad6644ae1b22bb65d05accc7d322943c69a74a6"}, - {file = "pycryptodome-3.19.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c1601e04d32087591d78e0b81e1e520e57a92796089864b20e5f18c9564b3fa"}, - {file = "pycryptodome-3.19.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:506c686a1eee6c00df70010be3b8e9e78f406af4f21b23162bbb6e9bdf5427bc"}, - {file = "pycryptodome-3.19.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7919ccd096584b911f2a303c593280869ce1af9bf5d36214511f5e5a1bed8c34"}, - {file = "pycryptodome-3.19.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:560591c0777f74a5da86718f70dfc8d781734cf559773b64072bbdda44b3fc3e"}, - {file = "pycryptodome-3.19.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1cc2f2ae451a676def1a73c1ae9120cd31af25db3f381893d45f75e77be2400"}, - {file = "pycryptodome-3.19.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17940dcf274fcae4a54ec6117a9ecfe52907ed5e2e438fe712fe7ca502672ed5"}, - {file = "pycryptodome-3.19.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d04f5f623a280fbd0ab1c1d8ecbd753193ab7154f09b6161b0f857a1a676c15f"}, - {file = "pycryptodome-3.19.0.tar.gz", hash = "sha256:bc35d463222cdb4dbebd35e0784155c81e161b9284e567e7e933d722e533331e"}, +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main"] +files = [ + {file = "pycryptodome-3.23.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a176b79c49af27d7f6c12e4b178b0824626f40a7b9fed08f712291b6d54bf566"}, + {file = "pycryptodome-3.23.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:573a0b3017e06f2cffd27d92ef22e46aa3be87a2d317a5abf7cc0e84e321bd75"}, + {file = "pycryptodome-3.23.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:63dad881b99ca653302b2c7191998dd677226222a3f2ea79999aa51ce695f720"}, + {file = "pycryptodome-3.23.0-cp27-cp27m-win32.whl", hash = "sha256:b34e8e11d97889df57166eda1e1ddd7676da5fcd4d71a0062a760e75060514b4"}, + {file = "pycryptodome-3.23.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:7ac1080a8da569bde76c0a104589c4f414b8ba296c0b3738cf39a466a9fb1818"}, + {file = "pycryptodome-3.23.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6fe8258e2039eceb74dfec66b3672552b6b7d2c235b2dfecc05d16b8921649a8"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39"}, + {file = "pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27"}, + {file = "pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843"}, + {file = "pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490"}, + {file = "pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575"}, + {file = "pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b"}, + {file = "pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a"}, + {file = "pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f"}, + {file = "pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa"}, + {file = "pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886"}, + {file = "pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2"}, + {file = "pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c"}, + {file = "pycryptodome-3.23.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:350ebc1eba1da729b35ab7627a833a1a355ee4e852d8ba0447fafe7b14504d56"}, + {file = "pycryptodome-3.23.0-pp27-pypy_73-win32.whl", hash = "sha256:93837e379a3e5fd2bb00302a47aee9fdf7940d83595be3915752c74033d17ca7"}, + {file = "pycryptodome-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddb95b49df036ddd264a0ad246d1be5b672000f12d6961ea2c267083a5e19379"}, + {file = "pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e95564beb8782abfd9e431c974e14563a794a4944c29d6d3b7b5ea042110b4"}, + {file = "pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e15c081e912c4b0d75632acd8382dfce45b258667aa3c67caf7a4d4c13f630"}, + {file = "pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7fc76bf273353dc7e5207d172b83f569540fc9a28d63171061c42e361d22353"}, + {file = "pycryptodome-3.23.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:45c69ad715ca1a94f778215a11e66b7ff989d792a4d63b68dc586a1da1392ff5"}, + {file = "pycryptodome-3.23.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:865d83c906b0fc6a59b510deceee656b6bc1c4fa0d82176e2b77e97a420a996a"}, + {file = "pycryptodome-3.23.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89d4d56153efc4d81defe8b65fd0821ef8b2d5ddf8ed19df31ba2f00872b8002"}, + {file = "pycryptodome-3.23.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3f2d0aaf8080bda0587d58fc9fe4766e012441e2eed4269a77de6aea981c8be"}, + {file = "pycryptodome-3.23.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64093fc334c1eccfd3933c134c4457c34eaca235eeae49d69449dc4728079339"}, + {file = "pycryptodome-3.23.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ce64e84a962b63a47a592690bdc16a7eaf709d2c2697ababf24a0def566899a6"}, + {file = "pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef"}, ] [[package]] name = "pydantic" -version = "2.9.2" +version = "2.11.5" description = "Data validation using Python type hints" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"}, - {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"}, + {file = "pydantic-2.11.5-py3-none-any.whl", hash = "sha256:f9c26ba06f9747749ca1e5c94d6a85cb84254577553c8785576fd38fa64dc0f7"}, + {file = "pydantic-2.11.5.tar.gz", hash = "sha256:7f853db3d0ce78ce8bbb148c401c2cdd6431b3473c0cdff2755c7690952a7b7a"}, ] [package.dependencies] annotated-types = ">=0.6.0" -pydantic-core = "2.23.4" -typing-extensions = [ - {version = ">=4.6.1", markers = "python_version < \"3.13\""}, - {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, -] +pydantic-core = "2.33.2" +typing-extensions = ">=4.12.2" +typing-inspection = ">=0.4.0" [package.extras] email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] [[package]] name = "pydantic-core" -version = "2.23.4" +version = "2.33.2" description = "Core functionality for Pydantic validation and serialization" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"}, - {file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"}, - {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"}, - {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"}, - {file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"}, - {file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"}, - {file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"}, - {file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"}, - {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"}, - {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"}, - {file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"}, - {file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"}, - {file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"}, - {file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"}, - {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"}, - {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"}, - {file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"}, - {file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"}, - {file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"}, - {file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"}, - {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"}, - {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"}, - {file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"}, - {file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"}, - {file = "pydantic_core-2.23.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555"}, - {file = "pydantic_core-2.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12"}, - {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2"}, - {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb"}, - {file = "pydantic_core-2.23.4-cp38-none-win32.whl", hash = "sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6"}, - {file = "pydantic_core-2.23.4-cp38-none-win_amd64.whl", hash = "sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556"}, - {file = "pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a"}, - {file = "pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55"}, - {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040"}, - {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605"}, - {file = "pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6"}, - {file = "pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e"}, - {file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"}, + {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, + {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, + {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, + {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, + {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, + {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, + {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, + {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, + {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, + {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, + {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, + {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, + {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, ] [package.dependencies] @@ -1578,27 +2083,71 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pyparsing" -version = "3.1.1" +version = "3.2.3" description = "pyparsing module - Classes and methods to define and execute parsing grammars" optional = false -python-versions = ">=3.6.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, - {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, + {file = "pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf"}, + {file = "pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be"}, ] [package.extras] diagrams = ["jinja2", "railroad-diagrams"] +[[package]] +name = "pytest" +version = "8.3.5" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, + {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.5,<2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + [[package]] name = "python-dateutil" -version = "2.8.2" +version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] [package.dependencies] @@ -1606,13 +2155,14 @@ six = ">=1.5" [[package]] name = "python-dotenv" -version = "1.0.1" +version = "1.1.0" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, - {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, + {file = "python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d"}, + {file = "python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5"}, ] [package.extras] @@ -1620,46 +2170,53 @@ cli = ["click (>=5.0)"] [[package]] name = "pytz" -version = "2023.3.post1" +version = "2025.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" +groups = ["main"] files = [ - {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, - {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, + {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"}, + {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"}, ] [[package]] name = "pyunormalize" -version = "15.0.0" -description = "Unicode normalization forms (NFC, NFKC, NFD, NFKD). A library independent from the Python core Unicode database." +version = "16.0.0" +description = "Unicode normalization forms (NFC, NFKC, NFD, NFKD). A library independent of the Python core Unicode database." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ - {file = "pyunormalize-15.0.0.tar.gz", hash = "sha256:e63fdba0d85ea04579dde2fc29a072dba773dcae600b04faf6cc90714c8b1302"}, + {file = "pyunormalize-16.0.0-py3-none-any.whl", hash = "sha256:c647d95e5d1e2ea9a2f448d1d95d8518348df24eab5c3fd32d2b5c3300a49152"}, + {file = "pyunormalize-16.0.0.tar.gz", hash = "sha256:2e1dfbb4a118154ae26f70710426a52a364b926c9191f764601f5a8cb12761f7"}, ] [[package]] name = "pywin32" -version = "306" +version = "310" description = "Python for Window Extensions" optional = false python-versions = "*" +groups = ["main"] +markers = "platform_system == \"Windows\"" files = [ - {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, - {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, - {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, - {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, - {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, - {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, - {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, - {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, - {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, - {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, - {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, - {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, - {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, - {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, + {file = "pywin32-310-cp310-cp310-win32.whl", hash = "sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1"}, + {file = "pywin32-310-cp310-cp310-win_amd64.whl", hash = "sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d"}, + {file = "pywin32-310-cp310-cp310-win_arm64.whl", hash = "sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213"}, + {file = "pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd"}, + {file = "pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c"}, + {file = "pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582"}, + {file = "pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d"}, + {file = "pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060"}, + {file = "pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966"}, + {file = "pywin32-310-cp313-cp313-win32.whl", hash = "sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab"}, + {file = "pywin32-310-cp313-cp313-win_amd64.whl", hash = "sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e"}, + {file = "pywin32-310-cp313-cp313-win_arm64.whl", hash = "sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33"}, + {file = "pywin32-310-cp38-cp38-win32.whl", hash = "sha256:0867beb8addefa2e3979d4084352e4ac6e991ca45373390775f7084cc0209b9c"}, + {file = "pywin32-310-cp38-cp38-win_amd64.whl", hash = "sha256:30f0a9b3138fb5e07eb4973b7077e1883f558e40c578c6925acc7a94c34eaa36"}, + {file = "pywin32-310-cp39-cp39-win32.whl", hash = "sha256:851c8d927af0d879221e616ae1f66145253537bbdd321a77e8ef701b443a9a1a"}, + {file = "pywin32-310-cp39-cp39-win_amd64.whl", hash = "sha256:96867217335559ac619f00ad70e513c0fcf84b8a3af9fc2bba3b59b97da70475"}, ] [[package]] @@ -1668,6 +2225,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1730,6 +2288,7 @@ version = "6.3.2" description = "RDFLib is a Python library for working with RDF, a simple yet powerful language for representing information." optional = false python-versions = ">=3.7,<4.0" +groups = ["main"] files = [ {file = "rdflib-6.3.2-py3-none-any.whl", hash = "sha256:36b4e74a32aa1e4fa7b8719876fb192f19ecd45ff932ea5ebbd2e417a0247e63"}, {file = "rdflib-6.3.2.tar.gz", hash = "sha256:72af591ff704f4caacea7ecc0c5a9056b8553e0489dd4f35a9bc52dbd41522e0"}, @@ -1747,110 +2306,118 @@ networkx = ["networkx (>=2.0.0,<3.0.0)"] [[package]] name = "regex" -version = "2023.8.8" +version = "2024.11.6" description = "Alternative regular expression module, to replace re." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "regex-2023.8.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:88900f521c645f784260a8d346e12a1590f79e96403971241e64c3a265c8ecdb"}, - {file = "regex-2023.8.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3611576aff55918af2697410ff0293d6071b7e00f4b09e005d614686ac4cd57c"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8a0ccc8f2698f120e9e5742f4b38dc944c38744d4bdfc427616f3a163dd9de5"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c662a4cbdd6280ee56f841f14620787215a171c4e2d1744c9528bed8f5816c96"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf0633e4a1b667bfe0bb10b5e53fe0d5f34a6243ea2530eb342491f1adf4f739"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:551ad543fa19e94943c5b2cebc54c73353ffff08228ee5f3376bd27b3d5b9800"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54de2619f5ea58474f2ac211ceea6b615af2d7e4306220d4f3fe690c91988a61"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5ec4b3f0aebbbe2fc0134ee30a791af522a92ad9f164858805a77442d7d18570"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ae646c35cb9f820491760ac62c25b6d6b496757fda2d51be429e0e7b67ae0ab"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca339088839582d01654e6f83a637a4b8194d0960477b9769d2ff2cfa0fa36d2"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:d9b6627408021452dcd0d2cdf8da0534e19d93d070bfa8b6b4176f99711e7f90"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:bd3366aceedf274f765a3a4bc95d6cd97b130d1dda524d8f25225d14123c01db"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7aed90a72fc3654fba9bc4b7f851571dcc368120432ad68b226bd593f3f6c0b7"}, - {file = "regex-2023.8.8-cp310-cp310-win32.whl", hash = "sha256:80b80b889cb767cc47f31d2b2f3dec2db8126fbcd0cff31b3925b4dc6609dcdb"}, - {file = "regex-2023.8.8-cp310-cp310-win_amd64.whl", hash = "sha256:b82edc98d107cbc7357da7a5a695901b47d6eb0420e587256ba3ad24b80b7d0b"}, - {file = "regex-2023.8.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1e7d84d64c84ad97bf06f3c8cb5e48941f135ace28f450d86af6b6512f1c9a71"}, - {file = "regex-2023.8.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ce0f9fbe7d295f9922c0424a3637b88c6c472b75eafeaff6f910494a1fa719ef"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06c57e14ac723b04458df5956cfb7e2d9caa6e9d353c0b4c7d5d54fcb1325c46"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7a9aaa5a1267125eef22cef3b63484c3241aaec6f48949b366d26c7250e0357"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b7408511fca48a82a119d78a77c2f5eb1b22fe88b0d2450ed0756d194fe7a9a"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14dc6f2d88192a67d708341f3085df6a4f5a0c7b03dec08d763ca2cd86e9f559"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48c640b99213643d141550326f34f0502fedb1798adb3c9eb79650b1ecb2f177"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0085da0f6c6393428bf0d9c08d8b1874d805bb55e17cb1dfa5ddb7cfb11140bf"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:964b16dcc10c79a4a2be9f1273fcc2684a9eedb3906439720598029a797b46e6"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7ce606c14bb195b0e5108544b540e2c5faed6843367e4ab3deb5c6aa5e681208"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:40f029d73b10fac448c73d6eb33d57b34607f40116e9f6e9f0d32e9229b147d7"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3b8e6ea6be6d64104d8e9afc34c151926f8182f84e7ac290a93925c0db004bfd"}, - {file = "regex-2023.8.8-cp311-cp311-win32.whl", hash = "sha256:942f8b1f3b223638b02df7df79140646c03938d488fbfb771824f3d05fc083a8"}, - {file = "regex-2023.8.8-cp311-cp311-win_amd64.whl", hash = "sha256:51d8ea2a3a1a8fe4f67de21b8b93757005213e8ac3917567872f2865185fa7fb"}, - {file = "regex-2023.8.8-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e951d1a8e9963ea51efd7f150450803e3b95db5939f994ad3d5edac2b6f6e2b4"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704f63b774218207b8ccc6c47fcef5340741e5d839d11d606f70af93ee78e4d4"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22283c769a7b01c8ac355d5be0715bf6929b6267619505e289f792b01304d898"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91129ff1bb0619bc1f4ad19485718cc623a2dc433dff95baadbf89405c7f6b57"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de35342190deb7b866ad6ba5cbcccb2d22c0487ee0cbb251efef0843d705f0d4"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b993b6f524d1e274a5062488a43e3f9f8764ee9745ccd8e8193df743dbe5ee61"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3026cbcf11d79095a32d9a13bbc572a458727bd5b1ca332df4a79faecd45281c"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:293352710172239bf579c90a9864d0df57340b6fd21272345222fb6371bf82b3"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d909b5a3fff619dc7e48b6b1bedc2f30ec43033ba7af32f936c10839e81b9217"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:3d370ff652323c5307d9c8e4c62efd1956fb08051b0e9210212bc51168b4ff56"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:b076da1ed19dc37788f6a934c60adf97bd02c7eea461b73730513921a85d4235"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e9941a4ada58f6218694f382e43fdd256e97615db9da135e77359da257a7168b"}, - {file = "regex-2023.8.8-cp36-cp36m-win32.whl", hash = "sha256:a8c65c17aed7e15a0c824cdc63a6b104dfc530f6fa8cb6ac51c437af52b481c7"}, - {file = "regex-2023.8.8-cp36-cp36m-win_amd64.whl", hash = "sha256:aadf28046e77a72f30dcc1ab185639e8de7f4104b8cb5c6dfa5d8ed860e57236"}, - {file = "regex-2023.8.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:423adfa872b4908843ac3e7a30f957f5d5282944b81ca0a3b8a7ccbbfaa06103"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ae594c66f4a7e1ea67232a0846649a7c94c188d6c071ac0210c3e86a5f92109"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e51c80c168074faa793685656c38eb7a06cbad7774c8cbc3ea05552d615393d8"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:09b7f4c66aa9d1522b06e31a54f15581c37286237208df1345108fcf4e050c18"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e73e5243af12d9cd6a9d6a45a43570dbe2e5b1cdfc862f5ae2b031e44dd95a8"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:941460db8fe3bd613db52f05259c9336f5a47ccae7d7def44cc277184030a116"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f0ccf3e01afeb412a1a9993049cb160d0352dba635bbca7762b2dc722aa5742a"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2e9216e0d2cdce7dbc9be48cb3eacb962740a09b011a116fd7af8c832ab116ca"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:5cd9cd7170459b9223c5e592ac036e0704bee765706445c353d96f2890e816c8"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4873ef92e03a4309b3ccd8281454801b291b689f6ad45ef8c3658b6fa761d7ac"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:239c3c2a339d3b3ddd51c2daef10874410917cd2b998f043c13e2084cb191684"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1005c60ed7037be0d9dea1f9c53cc42f836188227366370867222bda4c3c6bd7"}, - {file = "regex-2023.8.8-cp37-cp37m-win32.whl", hash = "sha256:e6bd1e9b95bc5614a7a9c9c44fde9539cba1c823b43a9f7bc11266446dd568e3"}, - {file = "regex-2023.8.8-cp37-cp37m-win_amd64.whl", hash = "sha256:9a96edd79661e93327cfeac4edec72a4046e14550a1d22aa0dd2e3ca52aec921"}, - {file = "regex-2023.8.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2181c20ef18747d5f4a7ea513e09ea03bdd50884a11ce46066bb90fe4213675"}, - {file = "regex-2023.8.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a2ad5add903eb7cdde2b7c64aaca405f3957ab34f16594d2b78d53b8b1a6a7d6"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9233ac249b354c54146e392e8a451e465dd2d967fc773690811d3a8c240ac601"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:920974009fb37b20d32afcdf0227a2e707eb83fe418713f7a8b7de038b870d0b"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2b6c5dfe0929b6c23dde9624483380b170b6e34ed79054ad131b20203a1a63"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96979d753b1dc3b2169003e1854dc67bfc86edf93c01e84757927f810b8c3c93"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ae54a338191e1356253e7883d9d19f8679b6143703086245fb14d1f20196be9"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2162ae2eb8b079622176a81b65d486ba50b888271302190870b8cc488587d280"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c884d1a59e69e03b93cf0dfee8794c63d7de0ee8f7ffb76e5f75be8131b6400a"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf9273e96f3ee2ac89ffcb17627a78f78e7516b08f94dc435844ae72576a276e"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:83215147121e15d5f3a45d99abeed9cf1fe16869d5c233b08c56cdf75f43a504"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f7454aa427b8ab9101f3787eb178057c5250478e39b99540cfc2b889c7d0586"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0640913d2c1044d97e30d7c41728195fc37e54d190c5385eacb52115127b882"}, - {file = "regex-2023.8.8-cp38-cp38-win32.whl", hash = "sha256:0c59122ceccb905a941fb23b087b8eafc5290bf983ebcb14d2301febcbe199c7"}, - {file = "regex-2023.8.8-cp38-cp38-win_amd64.whl", hash = "sha256:c12f6f67495ea05c3d542d119d270007090bad5b843f642d418eb601ec0fa7be"}, - {file = "regex-2023.8.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:82cd0a69cd28f6cc3789cc6adeb1027f79526b1ab50b1f6062bbc3a0ccb2dbc3"}, - {file = "regex-2023.8.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bb34d1605f96a245fc39790a117ac1bac8de84ab7691637b26ab2c5efb8f228c"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:987b9ac04d0b38ef4f89fbc035e84a7efad9cdd5f1e29024f9289182c8d99e09"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dd6082f4e2aec9b6a0927202c85bc1b09dcab113f97265127c1dc20e2e32495"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7eb95fe8222932c10d4436e7a6f7c99991e3fdd9f36c949eff16a69246dee2dc"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7098c524ba9f20717a56a8d551d2ed491ea89cbf37e540759ed3b776a4f8d6eb"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b694430b3f00eb02c594ff5a16db30e054c1b9589a043fe9174584c6efa8033"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2aeab3895d778155054abea5238d0eb9a72e9242bd4b43f42fd911ef9a13470"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:988631b9d78b546e284478c2ec15c8a85960e262e247b35ca5eaf7ee22f6050a"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:67ecd894e56a0c6108ec5ab1d8fa8418ec0cff45844a855966b875d1039a2e34"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:14898830f0a0eb67cae2bbbc787c1a7d6e34ecc06fbd39d3af5fe29a4468e2c9"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f2200e00b62568cfd920127782c61bc1c546062a879cdc741cfcc6976668dfcf"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9691a549c19c22d26a4f3b948071e93517bdf86e41b81d8c6ac8a964bb71e5a6"}, - {file = "regex-2023.8.8-cp39-cp39-win32.whl", hash = "sha256:6ab2ed84bf0137927846b37e882745a827458689eb969028af8032b1b3dac78e"}, - {file = "regex-2023.8.8-cp39-cp39-win_amd64.whl", hash = "sha256:5543c055d8ec7801901e1193a51570643d6a6ab8751b1f7dd9af71af467538bb"}, - {file = "regex-2023.8.8.tar.gz", hash = "sha256:fcbdc5f2b0f1cd0f6a56cdb46fe41d2cce1e644e3b68832f3eeebc5fb0f7712e"}, + {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, + {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, + {file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"}, + {file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"}, + {file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}, + {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}, + {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}, + {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}, + {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"}, + {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"}, + {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"}, + {file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"}, + {file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"}, + {file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"}, + {file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"}, + {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"}, ] [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -1865,82 +2432,131 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rlp" -version = "4.0.1" +version = "4.1.0" description = "rlp: A package for Recursive Length Prefix encoding and decoding" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "rlp-4.0.1-py3-none-any.whl", hash = "sha256:ff6846c3c27b97ee0492373aa074a7c3046aadd973320f4fffa7ac45564b0258"}, - {file = "rlp-4.0.1.tar.gz", hash = "sha256:bcefb11013dfadf8902642337923bd0c786dc8a27cb4c21da6e154e52869ecb1"}, + {file = "rlp-4.1.0-py3-none-any.whl", hash = "sha256:8eca394c579bad34ee0b937aecb96a57052ff3716e19c7a578883e767bc5da6f"}, + {file = "rlp-4.1.0.tar.gz", hash = "sha256:be07564270a96f3e225e2c107db263de96b5bc1f27722d2855bd3459a08e95a9"}, ] [package.dependencies] eth-utils = ">=2" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "hypothesis (==5.19.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "hypothesis (>=6.22.0,<6.108.7)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] rust-backend = ["rusty-rlp (>=0.2.1)"] -test = ["hypothesis (==5.19.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] +test = ["hypothesis (>=6.22.0,<6.108.7)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "ruff" -version = "0.8.4" +version = "0.8.6" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "ruff-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:58072f0c06080276804c6a4e21a9045a706584a958e644353603d36ca1eb8a60"}, - {file = "ruff-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ffb60904651c00a1e0b8df594591770018a0f04587f7deeb3838344fe3adabac"}, - {file = "ruff-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ddf5d654ac0d44389f6bf05cee4caeefc3132a64b58ea46738111d687352296"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e248b1f0fa2749edd3350a2a342b67b43a2627434c059a063418e3d375cfe643"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf197b98ed86e417412ee3b6c893f44c8864f816451441483253d5ff22c0e81e"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c41319b85faa3aadd4d30cb1cffdd9ac6b89704ff79f7664b853785b48eccdf3"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9f8402b7c4f96463f135e936d9ab77b65711fcd5d72e5d67597b543bbb43cf3f"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e56b3baa9c23d324ead112a4fdf20db9a3f8f29eeabff1355114dd96014604"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:736272574e97157f7edbbb43b1d046125fce9e7d8d583d5d65d0c9bf2c15addf"}, - {file = "ruff-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fe710ab6061592521f902fca7ebcb9fabd27bc7c57c764298b1c1f15fff720"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:13e9ec6d6b55f6da412d59953d65d66e760d583dd3c1c72bf1f26435b5bfdbae"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:97d9aefef725348ad77d6db98b726cfdb075a40b936c7984088804dfd38268a7"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ab78e33325a6f5374e04c2ab924a3367d69a0da36f8c9cb6b894a62017506111"}, - {file = "ruff-0.8.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8ef06f66f4a05c3ddbc9121a8b0cecccd92c5bf3dd43b5472ffe40b8ca10f0f8"}, - {file = "ruff-0.8.4-py3-none-win32.whl", hash = "sha256:552fb6d861320958ca5e15f28b20a3d071aa83b93caee33a87b471f99a6c0835"}, - {file = "ruff-0.8.4-py3-none-win_amd64.whl", hash = "sha256:f21a1143776f8656d7f364bd264a9d60f01b7f52243fbe90e7670c0dfe0cf65d"}, - {file = "ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08"}, - {file = "ruff-0.8.4.tar.gz", hash = "sha256:0d5f89f254836799af1615798caa5f80b7f935d7a670fad66c5007928e57ace8"}, + {file = "ruff-0.8.6-py3-none-linux_armv6l.whl", hash = "sha256:defed167955d42c68b407e8f2e6f56ba52520e790aba4ca707a9c88619e580e3"}, + {file = "ruff-0.8.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:54799ca3d67ae5e0b7a7ac234baa657a9c1784b48ec954a094da7c206e0365b1"}, + {file = "ruff-0.8.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e88b8f6d901477c41559ba540beeb5a671e14cd29ebd5683903572f4b40a9807"}, + {file = "ruff-0.8.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0509e8da430228236a18a677fcdb0c1f102dd26d5520f71f79b094963322ed25"}, + {file = "ruff-0.8.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91a7ddb221779871cf226100e677b5ea38c2d54e9e2c8ed847450ebbdf99b32d"}, + {file = "ruff-0.8.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:248b1fb3f739d01d528cc50b35ee9c4812aa58cc5935998e776bf8ed5b251e75"}, + {file = "ruff-0.8.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:bc3c083c50390cf69e7e1b5a5a7303898966be973664ec0c4a4acea82c1d4315"}, + {file = "ruff-0.8.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52d587092ab8df308635762386f45f4638badb0866355b2b86760f6d3c076188"}, + {file = "ruff-0.8.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:61323159cf21bc3897674e5adb27cd9e7700bab6b84de40d7be28c3d46dc67cf"}, + {file = "ruff-0.8.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ae4478b1471fc0c44ed52a6fb787e641a2ac58b1c1f91763bafbc2faddc5117"}, + {file = "ruff-0.8.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0c000a471d519b3e6cfc9c6680025d923b4ca140ce3e4612d1a2ef58e11f11fe"}, + {file = "ruff-0.8.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9257aa841e9e8d9b727423086f0fa9a86b6b420fbf4bf9e1465d1250ce8e4d8d"}, + {file = "ruff-0.8.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:45a56f61b24682f6f6709636949ae8cc82ae229d8d773b4c76c09ec83964a95a"}, + {file = "ruff-0.8.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:496dd38a53aa173481a7d8866bcd6451bd934d06976a2505028a50583e001b76"}, + {file = "ruff-0.8.6-py3-none-win32.whl", hash = "sha256:e169ea1b9eae61c99b257dc83b9ee6c76f89042752cb2d83486a7d6e48e8f764"}, + {file = "ruff-0.8.6-py3-none-win_amd64.whl", hash = "sha256:f1d70bef3d16fdc897ee290d7d20da3cbe4e26349f62e8a0274e7a3f4ce7a905"}, + {file = "ruff-0.8.6-py3-none-win_arm64.whl", hash = "sha256:7d7fc2377a04b6e04ffe588caad613d0c460eb2ecba4c0ccbbfe2bc973cbc162"}, + {file = "ruff-0.8.6.tar.gz", hash = "sha256:dcad24b81b62650b0eb8814f576fc65cfee8674772a6e24c9b747911801eeaa5"}, ] [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, +] + +[[package]] +name = "tomli" +version = "2.2.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\"" +files = [ + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] name = "toolz" -version = "0.12.0" +version = "1.0.0" description = "List processing tools and functional utilities" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" +groups = ["main"] +markers = "implementation_name == \"pypy\" or implementation_name == \"cpython\"" files = [ - {file = "toolz-0.12.0-py3-none-any.whl", hash = "sha256:2059bd4148deb1884bb0eb770a3cde70e7f954cfbbdc2285f1f2de01fd21eb6f"}, - {file = "toolz-0.12.0.tar.gz", hash = "sha256:88c570861c440ee3f2f6037c4654613228ff40c93a6c25e0eba70d17282c6194"}, + {file = "toolz-1.0.0-py3-none-any.whl", hash = "sha256:292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236"}, + {file = "toolz-1.0.0.tar.gz", hash = "sha256:2c86e3d9a04798ac556793bced838816296a2f085017664e4995cb40a1047a02"}, ] [[package]] name = "types-requests" -version = "2.32.0.20240914" +version = "2.32.0.20250602" description = "Typing stubs for requests" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "types-requests-2.32.0.20240914.tar.gz", hash = "sha256:2850e178db3919d9bf809e434eef65ba49d0e7e33ac92d588f4a5e295fffd405"}, - {file = "types_requests-2.32.0.20240914-py3-none-any.whl", hash = "sha256:59c2f673eb55f32a99b2894faf6020e1a9f4a402ad0f192bfee0b64469054310"}, + {file = "types_requests-2.32.0.20250602-py3-none-any.whl", hash = "sha256:f4f335f87779b47ce10b8b8597b409130299f6971ead27fead4fe7ba6ea3e726"}, + {file = "types_requests-2.32.0.20250602.tar.gz", hash = "sha256:ee603aeefec42051195ae62ca7667cd909a2f8128fdf8aad9e8a5219ecfab3bf"}, ] [package.dependencies] @@ -1948,52 +2564,72 @@ urllib3 = ">=2" [[package]] name = "typing-extensions" -version = "4.12.2" +version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, ] +markers = {dev = "python_version == \"3.10\""} + +[[package]] +name = "typing-inspection" +version = "0.4.1" +description = "Runtime typing introspection tools" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51"}, + {file = "typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28"}, +] + +[package.dependencies] +typing-extensions = ">=4.12.0" [[package]] name = "tzdata" -version = "2024.2" +version = "2025.2" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" +groups = ["main"] files = [ - {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"}, - {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"}, + {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, + {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, ] [[package]] name = "urllib3" -version = "2.0.6" +version = "2.4.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "urllib3-2.0.6-py3-none-any.whl", hash = "sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2"}, - {file = "urllib3-2.0.6.tar.gz", hash = "sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564"}, + {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"}, + {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.28.0" +version = "20.31.2" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0"}, - {file = "virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa"}, + {file = "virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11"}, + {file = "virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af"}, ] [package.dependencies] @@ -2003,23 +2639,24 @@ platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "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)"] +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) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] [[package]] name = "web3" -version = "7.3.0" +version = "7.12.0" description = "web3: A Python library for interacting with Ethereum" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "web3-7.3.0-py3-none-any.whl", hash = "sha256:afcbab05040fecff205394713458ffc64bb8b5966164339a397d63f29cbe6ba1"}, - {file = "web3-7.3.0.tar.gz", hash = "sha256:74d52cfcc23b8e99c837190128b932923f38fca290ae2cf2d690edbf622252a0"}, + {file = "web3-7.12.0-py3-none-any.whl", hash = "sha256:c7e2b9c1db5a379ef53b45fe8a19bdc2d47ad262039fbf6675794bc40f74bf06"}, + {file = "web3-7.12.0.tar.gz", hash = "sha256:08fbe79a2e2503c9820132ebad24ba0372831588cabac5f467999c97ace7dda3"}, ] [package.dependencies] aiohttp = ">=3.7.4.post0" eth-abi = ">=5.0.1" -eth-account = ">=0.13.1" +eth-account = ">=0.13.6" eth-hash = {version = ">=0.5.1", extras = ["pycryptodome"]} eth-typing = ">=5.0.0" eth-utils = ">=5.0.0" @@ -2030,181 +2667,213 @@ pywin32 = {version = ">=223", markers = "platform_system == \"Windows\""} requests = ">=2.23.0" types-requests = ">=2.0.0" typing-extensions = ">=4.0.1" -websockets = ">=10.0.0" +websockets = ">=10.0.0,<16.0.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-tester[py-evm] (>=0.11.0b1,<0.13.0b1)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "py-geth (>=5.0.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1,<0.23)", "pytest-mock (>=1.10)", "pytest-xdist (>=2.4.0)", "setuptools (>=38.6.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "tqdm (>4.32)", "twine (>=1.13)", "wheel"] -docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -test = ["eth-tester[py-evm] (>=0.11.0b1,<0.13.0b1)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "py-geth (>=5.0.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1,<0.23)", "pytest-mock (>=1.10)", "pytest-xdist (>=2.4.0)", "tox (>=4.0.0)"] -tester = ["eth-tester[py-evm] (>=0.11.0b1,<0.13.0b1)", "py-geth (>=5.0.0)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "eth-tester[py-evm] (>=0.13.0b1,<0.14.0b1)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "py-geth (>=5.1.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1,<0.23)", "pytest-mock (>=1.10)", "pytest-xdist (>=2.4.0)", "setuptools (>=38.6.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "tqdm (>4.32)", "twine (>=1.13)", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["eth-tester[py-evm] (>=0.13.0b1,<0.14.0b1)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "py-geth (>=5.1.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1,<0.23)", "pytest-mock (>=1.10)", "pytest-xdist (>=2.4.0)", "tox (>=4.0.0)"] +tester = ["eth-tester[py-evm] (>=0.13.0b1,<0.14.0b1)", "py-geth (>=5.1.0)"] [[package]] name = "websockets" -version = "11.0.3" +version = "15.0.1" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3ccc8a0c387629aec40f2fc9fdcb4b9d5431954f934da3eaf16cdc94f67dbfac"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d67ac60a307f760c6e65dad586f556dde58e683fab03323221a4e530ead6f74d"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d27a4832cc1a0ee07cdcf2b0629a8a72db73f4cf6de6f0904f6661227f256f"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7622a89d696fc87af8e8d280d9b421db5133ef5b29d3f7a1ce9f1a7bf7fcfa11"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bceab846bac555aff6427d060f2fcfff71042dba6f5fca7dc4f75cac815e57ca"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54c6e5b3d3a8936a4ab6870d46bdd6ec500ad62bde9e44462c32d18f1e9a8e54"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41f696ba95cd92dc047e46b41b26dd24518384749ed0d99bea0a941ca87404c4"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86d2a77fd490ae3ff6fae1c6ceaecad063d3cc2320b44377efdde79880e11526"}, - {file = "websockets-11.0.3-cp310-cp310-win32.whl", hash = "sha256:2d903ad4419f5b472de90cd2d40384573b25da71e33519a67797de17ef849b69"}, - {file = "websockets-11.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1d2256283fa4b7f4c7d7d3e84dc2ece74d341bce57d5b9bf385df109c2a1a82f"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e848f46a58b9fcf3d06061d17be388caf70ea5b8cc3466251963c8345e13f7eb"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa5003845cdd21ac0dc6c9bf661c5beddd01116f6eb9eb3c8e272353d45b3288"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b58cbf0697721120866820b89f93659abc31c1e876bf20d0b3d03cef14faf84d"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:660e2d9068d2bedc0912af508f30bbeb505bbbf9774d98def45f68278cea20d3"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1f0524f203e3bd35149f12157438f406eff2e4fb30f71221c8a5eceb3617b6b"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b30c6590146e53149f04e85a6e4fcae068df4289e31e4aee1fdf56a0dead8f97"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:619d9f06372b3a42bc29d0cd0354c9bb9fb39c2cbc1a9c5025b4538738dbffaf"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd"}, - {file = "websockets-11.0.3-cp311-cp311-win32.whl", hash = "sha256:e1459677e5d12be8bbc7584c35b992eea142911a6236a3278b9b5ce3326f282c"}, - {file = "websockets-11.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:e7837cb169eca3b3ae94cc5787c4fed99eef74c0ab9506756eea335e0d6f3ed8"}, - {file = "websockets-11.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f59a3c656fef341a99e3d63189852be7084c0e54b75734cde571182c087b152"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2529338a6ff0eb0b50c7be33dc3d0e456381157a31eefc561771ee431134a97f"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fd59a4ac42dff6d4681d8843217137f6bc85ed29722f2f7222bd619d15e95b"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:332d126167ddddec94597c2365537baf9ff62dfcc9db4266f263d455f2f031cb"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6505c1b31274723ccaf5f515c1824a4ad2f0d191cec942666b3d0f3aa4cb4007"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f467ba0050b7de85016b43f5a22b46383ef004c4f672148a8abf32bc999a87f0"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9d9acd80072abcc98bd2c86c3c9cd4ac2347b5a5a0cae7ed5c0ee5675f86d9af"}, - {file = "websockets-11.0.3-cp37-cp37m-win32.whl", hash = "sha256:e590228200fcfc7e9109509e4d9125eace2042fd52b595dd22bbc34bb282307f"}, - {file = "websockets-11.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b16fff62b45eccb9c7abb18e60e7e446998093cdcb50fed33134b9b6878836de"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a34e13a62a59c871064dfd8ffb150867e54291e46d4a7cf11d02c94a5275bae"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4841ed00f1026dfbced6fca7d963c4e7043aa832648671b5138008dc5a8f6d99"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a073fc9ab1c8aff37c99f11f1641e16da517770e31a37265d2755282a5d28aa"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68b977f21ce443d6d378dbd5ca38621755f2063d6fdb3335bda981d552cfff86"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a99a7a71631f0efe727c10edfba09ea6bee4166a6f9c19aafb6c0b5917d09c"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bee9fcb41db2a23bed96c6b6ead6489702c12334ea20a297aa095ce6d31370d0"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4b253869ea05a5a073ebfdcb5cb3b0266a57c3764cf6fe114e4cd90f4bfa5f5e"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1553cb82942b2a74dd9b15a018dce645d4e68674de2ca31ff13ebc2d9f283788"}, - {file = "websockets-11.0.3-cp38-cp38-win32.whl", hash = "sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74"}, - {file = "websockets-11.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:03aae4edc0b1c68498f41a6772d80ac7c1e33c06c6ffa2ac1c27a07653e79d6f"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:777354ee16f02f643a4c7f2b3eff8027a33c9861edc691a2003531f5da4f6bc8"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c82f11964f010053e13daafdc7154ce7385ecc538989a354ccc7067fd7028fd"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3580dd9c1ad0701169e4d6fc41e878ffe05e6bdcaf3c412f9d559389d0c9e016"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f1a3f10f836fab6ca6efa97bb952300b20ae56b409414ca85bff2ad241d2a61"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df41b9bc27c2c25b486bae7cf42fccdc52ff181c8c387bfd026624a491c2671b"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279e5de4671e79a9ac877427f4ac4ce93751b8823f276b681d04b2156713b9dd"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1fdf26fa8a6a592f8f9235285b8affa72748dc12e964a5518c6c5e8f916716f7"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69269f3a0b472e91125b503d3c0b3566bda26da0a3261c49f0027eb6075086d1"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97b52894d948d2f6ea480171a27122d77af14ced35f62e5c892ca2fae9344311"}, - {file = "websockets-11.0.3-cp39-cp39-win32.whl", hash = "sha256:c7f3cb904cce8e1be667c7e6fef4516b98d1a6a0635a58a57528d577ac18a128"}, - {file = "websockets-11.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c792ea4eabc0159535608fc5658a74d1a81020eb35195dd63214dcf07556f67e"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e58f2c36cc52d41f2659e4c0cbf7353e28c8c9e63e30d8c6d3494dc9fdedcf"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de36fe9c02995c7e6ae6efe2e205816f5f00c22fd1fbf343d4d18c3d5ceac2f5"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ac56b661e60edd453585f4bd68eb6a29ae25b5184fd5ba51e97652580458998"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e052b8467dd07d4943936009f46ae5ce7b908ddcac3fda581656b1b19c083d9b"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42cc5452a54a8e46a032521d7365da775823e21bfba2895fb7b77633cce031bb"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e6316827e3e79b7b8e7d8e3b08f4e331af91a48e794d5d8b099928b6f0b85f20"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8531fdcad636d82c517b26a448dcfe62f720e1922b33c81ce695d0edb91eb931"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c114e8da9b475739dde229fd3bc6b05a6537a88a578358bc8eb29b4030fac9c9"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e063b1865974611313a3849d43f2c3f5368093691349cf3c7c8f8f75ad7cb280"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:92b2065d642bf8c0a82d59e59053dd2fdde64d4ed44efe4870fa816c1232647b"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ee68fe502f9031f19d495dae2c268830df2760c0524cbac5d759921ba8c8e82"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcacf2c7a6c3a84e720d1bb2b543c675bf6c40e460300b628bab1b1efc7c034c"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b67c6f5e5a401fc56394f191f00f9b3811fe843ee93f4a70df3c389d1adf857d"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5023a4b6a5b183dc838808087033ec5df77580485fc533e7dab2567851b0a4"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ed058398f55163a79bb9f06a90ef9ccc063b204bb346c4de78efc5d15abfe602"}, - {file = "websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6"}, - {file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"}, + {file = "websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b"}, + {file = "websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205"}, + {file = "websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a"}, + {file = "websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e"}, + {file = "websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf"}, + {file = "websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb"}, + {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d"}, + {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9"}, + {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c"}, + {file = "websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256"}, + {file = "websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41"}, + {file = "websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431"}, + {file = "websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57"}, + {file = "websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905"}, + {file = "websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562"}, + {file = "websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792"}, + {file = "websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413"}, + {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8"}, + {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3"}, + {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf"}, + {file = "websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85"}, + {file = "websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065"}, + {file = "websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3"}, + {file = "websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665"}, + {file = "websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2"}, + {file = "websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215"}, + {file = "websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5"}, + {file = "websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65"}, + {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe"}, + {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4"}, + {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597"}, + {file = "websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9"}, + {file = "websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7"}, + {file = "websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931"}, + {file = "websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675"}, + {file = "websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151"}, + {file = "websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22"}, + {file = "websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f"}, + {file = "websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8"}, + {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375"}, + {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d"}, + {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4"}, + {file = "websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa"}, + {file = "websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561"}, + {file = "websockets-15.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5"}, + {file = "websockets-15.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a"}, + {file = "websockets-15.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b"}, + {file = "websockets-15.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770"}, + {file = "websockets-15.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb"}, + {file = "websockets-15.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054"}, + {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee"}, + {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed"}, + {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880"}, + {file = "websockets-15.0.1-cp39-cp39-win32.whl", hash = "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411"}, + {file = "websockets-15.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4"}, + {file = "websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3"}, + {file = "websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1"}, + {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475"}, + {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9"}, + {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04"}, + {file = "websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122"}, + {file = "websockets-15.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940"}, + {file = "websockets-15.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e"}, + {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9"}, + {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b"}, + {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f"}, + {file = "websockets-15.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123"}, + {file = "websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f"}, + {file = "websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee"}, ] [[package]] name = "yarl" -version = "1.9.2" +version = "1.20.0" description = "Yet another URL library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, - {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, - {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, - {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, - {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, - {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, - {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, - {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, - {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, - {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, - {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, - {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, - {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, + {file = "yarl-1.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f1f6670b9ae3daedb325fa55fbe31c22c8228f6e0b513772c2e1c623caa6ab22"}, + {file = "yarl-1.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:85a231fa250dfa3308f3c7896cc007a47bc76e9e8e8595c20b7426cac4884c62"}, + {file = "yarl-1.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a06701b647c9939d7019acdfa7ebbfbb78ba6aa05985bb195ad716ea759a569"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7595498d085becc8fb9203aa314b136ab0516c7abd97e7d74f7bb4eb95042abe"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af5607159085dcdb055d5678fc2d34949bd75ae6ea6b4381e784bbab1c3aa195"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95b50910e496567434cb77a577493c26bce0f31c8a305135f3bda6a2483b8e10"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b594113a301ad537766b4e16a5a6750fcbb1497dcc1bc8a4daae889e6402a634"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:083ce0393ea173cd37834eb84df15b6853b555d20c52703e21fbababa8c129d2"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f1a350a652bbbe12f666109fbddfdf049b3ff43696d18c9ab1531fbba1c977a"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fb0caeac4a164aadce342f1597297ec0ce261ec4532bbc5a9ca8da5622f53867"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:d88cc43e923f324203f6ec14434fa33b85c06d18d59c167a0637164863b8e995"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e52d6ed9ea8fd3abf4031325dc714aed5afcbfa19ee4a89898d663c9976eb487"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ce360ae48a5e9961d0c730cf891d40698a82804e85f6e74658fb175207a77cb2"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:06d06c9d5b5bc3eb56542ceeba6658d31f54cf401e8468512447834856fb0e61"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c27d98f4e5c4060582f44e58309c1e55134880558f1add7a87c1bc36ecfade19"}, + {file = "yarl-1.20.0-cp310-cp310-win32.whl", hash = "sha256:f4d3fa9b9f013f7050326e165c3279e22850d02ae544ace285674cb6174b5d6d"}, + {file = "yarl-1.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:bc906b636239631d42eb8a07df8359905da02704a868983265603887ed68c076"}, + {file = "yarl-1.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fdb5204d17cb32b2de2d1e21c7461cabfacf17f3645e4b9039f210c5d3378bf3"}, + {file = "yarl-1.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:eaddd7804d8e77d67c28d154ae5fab203163bd0998769569861258e525039d2a"}, + {file = "yarl-1.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:634b7ba6b4a85cf67e9df7c13a7fb2e44fa37b5d34501038d174a63eaac25ee2"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d409e321e4addf7d97ee84162538c7258e53792eb7c6defd0c33647d754172e"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ea52f7328a36960ba3231c6677380fa67811b414798a6e071c7085c57b6d20a9"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8703517b924463994c344dcdf99a2d5ce9eca2b6882bb640aa555fb5efc706a"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:077989b09ffd2f48fb2d8f6a86c5fef02f63ffe6b1dd4824c76de7bb01e4f2e2"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0acfaf1da020253f3533526e8b7dd212838fdc4109959a2c53cafc6db611bff2"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4230ac0b97ec5eeb91d96b324d66060a43fd0d2a9b603e3327ed65f084e41f8"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a6a1e6ae21cdd84011c24c78d7a126425148b24d437b5702328e4ba640a8902"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:86de313371ec04dd2531f30bc41a5a1a96f25a02823558ee0f2af0beaa7ca791"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dd59c9dd58ae16eaa0f48c3d0cbe6be8ab4dc7247c3ff7db678edecbaf59327f"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a0bc5e05f457b7c1994cc29e83b58f540b76234ba6b9648a4971ddc7f6aa52da"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c9471ca18e6aeb0e03276b5e9b27b14a54c052d370a9c0c04a68cefbd1455eb4"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:40ed574b4df723583a26c04b298b283ff171bcc387bc34c2683235e2487a65a5"}, + {file = "yarl-1.20.0-cp311-cp311-win32.whl", hash = "sha256:db243357c6c2bf3cd7e17080034ade668d54ce304d820c2a58514a4e51d0cfd6"}, + {file = "yarl-1.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:8c12cd754d9dbd14204c328915e23b0c361b88f3cffd124129955e60a4fbfcfb"}, + {file = "yarl-1.20.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e06b9f6cdd772f9b665e5ba8161968e11e403774114420737f7884b5bd7bdf6f"}, + {file = "yarl-1.20.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b9ae2fbe54d859b3ade40290f60fe40e7f969d83d482e84d2c31b9bff03e359e"}, + {file = "yarl-1.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d12b8945250d80c67688602c891237994d203d42427cb14e36d1a732eda480e"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:087e9731884621b162a3e06dc0d2d626e1542a617f65ba7cc7aeab279d55ad33"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:69df35468b66c1a6e6556248e6443ef0ec5f11a7a4428cf1f6281f1879220f58"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b2992fe29002fd0d4cbaea9428b09af9b8686a9024c840b8a2b8f4ea4abc16f"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c903e0b42aab48abfbac668b5a9d7b6938e721a6341751331bcd7553de2dcae"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf099e2432131093cc611623e0b0bcc399b8cddd9a91eded8bfb50402ec35018"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a7f62f5dc70a6c763bec9ebf922be52aa22863d9496a9a30124d65b489ea672"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:54ac15a8b60382b2bcefd9a289ee26dc0920cf59b05368c9b2b72450751c6eb8"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:25b3bc0763a7aca16a0f1b5e8ef0f23829df11fb539a1b70476dcab28bd83da7"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b2586e36dc070fc8fad6270f93242124df68b379c3a251af534030a4a33ef594"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:866349da9d8c5290cfefb7fcc47721e94de3f315433613e01b435473be63daa6"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:33bb660b390a0554d41f8ebec5cd4475502d84104b27e9b42f5321c5192bfcd1"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:737e9f171e5a07031cbee5e9180f6ce21a6c599b9d4b2c24d35df20a52fabf4b"}, + {file = "yarl-1.20.0-cp312-cp312-win32.whl", hash = "sha256:839de4c574169b6598d47ad61534e6981979ca2c820ccb77bf70f4311dd2cc64"}, + {file = "yarl-1.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:3d7dbbe44b443b0c4aa0971cb07dcb2c2060e4a9bf8d1301140a33a93c98e18c"}, + {file = "yarl-1.20.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2137810a20b933b1b1b7e5cf06a64c3ed3b4747b0e5d79c9447c00db0e2f752f"}, + {file = "yarl-1.20.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:447c5eadd750db8389804030d15f43d30435ed47af1313303ed82a62388176d3"}, + {file = "yarl-1.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:42fbe577272c203528d402eec8bf4b2d14fd49ecfec92272334270b850e9cd7d"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18e321617de4ab170226cd15006a565d0fa0d908f11f724a2c9142d6b2812ab0"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4345f58719825bba29895011e8e3b545e6e00257abb984f9f27fe923afca2501"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d9b980d7234614bc4674468ab173ed77d678349c860c3af83b1fffb6a837ddc"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af4baa8a445977831cbaa91a9a84cc09debb10bc8391f128da2f7bd070fc351d"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123393db7420e71d6ce40d24885a9e65eb1edefc7a5228db2d62bcab3386a5c0"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab47acc9332f3de1b39e9b702d9c916af7f02656b2a86a474d9db4e53ef8fd7a"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4a34c52ed158f89876cba9c600b2c964dfc1ca52ba7b3ab6deb722d1d8be6df2"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:04d8cfb12714158abf2618f792c77bc5c3d8c5f37353e79509608be4f18705c9"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7dc63ad0d541c38b6ae2255aaa794434293964677d5c1ec5d0116b0e308031f5"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d02b591a64e4e6ca18c5e3d925f11b559c763b950184a64cf47d74d7e41877"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:95fc9876f917cac7f757df80a5dda9de59d423568460fe75d128c813b9af558e"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bb769ae5760cd1c6a712135ee7915f9d43f11d9ef769cb3f75a23e398a92d384"}, + {file = "yarl-1.20.0-cp313-cp313-win32.whl", hash = "sha256:70e0c580a0292c7414a1cead1e076c9786f685c1fc4757573d2967689b370e62"}, + {file = "yarl-1.20.0-cp313-cp313-win_amd64.whl", hash = "sha256:4c43030e4b0af775a85be1fa0433119b1565673266a70bf87ef68a9d5ba3174c"}, + {file = "yarl-1.20.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b6c4c3d0d6a0ae9b281e492b1465c72de433b782e6b5001c8e7249e085b69051"}, + {file = "yarl-1.20.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8681700f4e4df891eafa4f69a439a6e7d480d64e52bf460918f58e443bd3da7d"}, + {file = "yarl-1.20.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:84aeb556cb06c00652dbf87c17838eb6d92cfd317799a8092cee0e570ee11229"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f166eafa78810ddb383e930d62e623d288fb04ec566d1b4790099ae0f31485f1"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5d3d6d14754aefc7a458261027a562f024d4f6b8a798adb472277f675857b1eb"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a8f64df8ed5d04c51260dbae3cc82e5649834eebea9eadfd829837b8093eb00"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d9949eaf05b4d30e93e4034a7790634bbb41b8be2d07edd26754f2e38e491de"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c366b254082d21cc4f08f522ac201d0d83a8b8447ab562732931d31d80eb2a5"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91bc450c80a2e9685b10e34e41aef3d44ddf99b3a498717938926d05ca493f6a"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c2aa4387de4bc3a5fe158080757748d16567119bef215bec643716b4fbf53f9"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:d2cbca6760a541189cf87ee54ff891e1d9ea6406079c66341008f7ef6ab61145"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:798a5074e656f06b9fad1a162be5a32da45237ce19d07884d0b67a0aa9d5fdda"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f106e75c454288472dbe615accef8248c686958c2e7dd3b8d8ee2669770d020f"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:3b60a86551669c23dc5445010534d2c5d8a4e012163218fc9114e857c0586fdd"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e429857e341d5e8e15806118e0294f8073ba9c4580637e59ab7b238afca836f"}, + {file = "yarl-1.20.0-cp313-cp313t-win32.whl", hash = "sha256:65a4053580fe88a63e8e4056b427224cd01edfb5f951498bfefca4052f0ce0ac"}, + {file = "yarl-1.20.0-cp313-cp313t-win_amd64.whl", hash = "sha256:53b2da3a6ca0a541c1ae799c349788d480e5144cac47dba0266c7cb6c76151fe"}, + {file = "yarl-1.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:119bca25e63a7725b0c9d20ac67ca6d98fa40e5a894bd5d4686010ff73397914"}, + {file = "yarl-1.20.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:35d20fb919546995f1d8c9e41f485febd266f60e55383090010f272aca93edcc"}, + {file = "yarl-1.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:484e7a08f72683c0f160270566b4395ea5412b4359772b98659921411d32ad26"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d8a3d54a090e0fff5837cd3cc305dd8a07d3435a088ddb1f65e33b322f66a94"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f0cf05ae2d3d87a8c9022f3885ac6dea2b751aefd66a4f200e408a61ae9b7f0d"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a884b8974729e3899d9287df46f015ce53f7282d8d3340fa0ed57536b440621c"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8d8aa8dd89ffb9a831fedbcb27d00ffd9f4842107d52dc9d57e64cb34073d5c"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4e88d6c3c8672f45a30867817e4537df1bbc6f882a91581faf1f6d9f0f1b5a"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdb77efde644d6f1ad27be8a5d67c10b7f769804fff7a966ccb1da5a4de4b656"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4ba5e59f14bfe8d261a654278a0f6364feef64a794bd456a8c9e823071e5061c"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:d0bf955b96ea44ad914bc792c26a0edcd71b4668b93cbcd60f5b0aeaaed06c64"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:27359776bc359ee6eaefe40cb19060238f31228799e43ebd3884e9c589e63b20"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:04d9c7a1dc0a26efb33e1acb56c8849bd57a693b85f44774356c92d610369efa"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:faa709b66ae0e24c8e5134033187a972d849d87ed0a12a0366bedcc6b5dc14a5"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:44869ee8538208fe5d9342ed62c11cc6a7a1af1b3d0bb79bb795101b6e77f6e0"}, + {file = "yarl-1.20.0-cp39-cp39-win32.whl", hash = "sha256:b7fa0cb9fd27ffb1211cde944b41f5c67ab1c13a13ebafe470b1e206b8459da8"}, + {file = "yarl-1.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:d4fad6e5189c847820288286732075f213eabf81be4d08d6cc309912e62be5b7"}, + {file = "yarl-1.20.0-py3-none-any.whl", hash = "sha256:5d0fe6af927a47a230f31e6004621fd0959eaa915fc62acfafa67ff7229a3124"}, + {file = "yarl-1.20.0.tar.gz", hash = "sha256:686d51e51ee5dfe62dec86e4866ee0e9ed66df700d55c828a615640adc885307"}, ] [package.dependencies] idna = ">=2.0" multidict = ">=4.0" +propcache = ">=0.2.1" [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = "^3.10" -content-hash = "2bd261f92e6198e0e7c08d6c5dfa8a4a7852dd59a2119c7c0b453cbaa31612bd" +content-hash = "38626addbd24a8eaa57b9f993d2aaf96aed4afd84df3c71a6887b31a268692d5" diff --git a/pyproject.toml b/pyproject.toml index a3f82e2..8c200a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,7 @@ authors = ["Uladzislau Hubar , Zvonimir Sculac Date: Mon, 2 Jun 2025 12:48:29 +0200 Subject: [PATCH 127/146] created kc-tools unit tests --- test/.gitkeep | 0 test/knowledge_collection_tools_test.py | 13 +++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 test/.gitkeep create mode 100644 test/knowledge_collection_tools_test.py diff --git a/test/.gitkeep b/test/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/knowledge_collection_tools_test.py b/test/knowledge_collection_tools_test.py new file mode 100644 index 0000000..16bfb27 --- /dev/null +++ b/test/knowledge_collection_tools_test.py @@ -0,0 +1,13 @@ +import dkg.utils.knowledge_collection_tools as kc_tools + + +class TestGroupNQuadsBySubject: + def test_resource_object_quad(self): + quads = [ + " .", + " .", + ] + grouped = kc_tools.group_nquads_by_subject(quads) + assert len(grouped) == 1 + assert quads[0] in grouped[0] + assert quads[1] in grouped[0] From 20fe95debbc82616595145593e2b85e940828e7d Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 2 Jun 2025 12:48:54 +0200 Subject: [PATCH 128/146] deleted .gitkeep (rename) --- tests/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/.gitkeep diff --git a/tests/.gitkeep b/tests/.gitkeep deleted file mode 100644 index e69de29..0000000 From 7c91c6d561f5c9af6c44431cad83fc75e425aa9b Mon Sep 17 00:00:00 2001 From: Bojan Date: Mon, 2 Jun 2025 14:25:02 +0200 Subject: [PATCH 129/146] add github actions --- .github/workflows/checks.yml | 32 ++++++++++++++++++++++++++++++++ .gitignore | 1 + 2 files changed, 33 insertions(+) create mode 100644 .github/workflows/checks.yml diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 0000000..2601dd0 --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,32 @@ +name: Python Tests + +on: + push: + branches: ["**"] + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install Poetry + run: | + curl -sSL https://install.python-poetry.org | python3 - + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Install dependencies + run: | + poetry install + + - name: Run tests + run: | + make run-test diff --git a/.gitignore b/.gitignore index b6e4761..729ff12 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,4 @@ dmypy.json # Pyre type checker .pyre/ +.report From 49f4b1aefe51ad64863264119d37b313a5f6a7f2 Mon Sep 17 00:00:00 2001 From: Bojan Date: Mon, 2 Jun 2025 14:30:50 +0200 Subject: [PATCH 130/146] Update github actions tests --- .github/workflows/checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 2601dd0..9f08d04 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -29,4 +29,4 @@ jobs: - name: Run tests run: | - make run-test + poetry run make run-test From 4f217812a525b61827f7cf5a163b7067ccb62624 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 3 Jun 2025 15:25:40 +0200 Subject: [PATCH 131/146] fixed language and type support for nquads --- dkg/utils/knowledge_collection_tools.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index 14371db..63c5846 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -5,7 +5,7 @@ from dkg.types import JSONLD, NQuads from pyld import jsonld from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM, ESCAPE_MAP -from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral +from rdflib import Graph, BNode, URIRef, Dataset from rdflib.exceptions import ParserError as RDFParserError from uuid import uuid4 from web3 import Web3 @@ -182,16 +182,13 @@ def replace_blank_node(term): def group_nquads_by_subject(nquads_list: list[str], sort: bool = False): grouped = {} - # Process each quad in original order - for nquad in nquads_list: - if not nquad.strip(): # Skip empty lines - continue + all_nquads = "\n".join(nquad for nquad in nquads_list if nquad.strip()) - # Parse single quad - g = Graph() - g.parse(data=nquad, format="nquads") - quad = next(iter(g)) - subject, predicate, obj = quad + d = Dataset() + d.parse(data=all_nquads, format="nquads") + + for quad in d: + subject, predicate, obj, graph = quad # Get subject key subject_key = ( @@ -204,11 +201,8 @@ def group_nquads_by_subject(nquads_list: list[str], sort: bool = False): if subject_key not in grouped: grouped[subject_key] = [] - # Format object - object_value = f'"{obj}"' if isinstance(obj, RDFLiteral) else f"<{obj}>" - # Add quad to group - quad_string = f"{subject_key} <{predicate}> {object_value} ." + quad_string = f"{subject.n3()} {predicate.n3()} {obj.n3()} ." grouped[subject_key].append(quad_string) # Return grouped quads (sorted if requested) From fa32d9509666778c673f32bb4d5627f9b317d658 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 3 Jun 2025 15:26:17 +0200 Subject: [PATCH 132/146] added groupNquadsBySubject tests cases --- test/knowledge_collection_tools_test.py | 131 ++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/test/knowledge_collection_tools_test.py b/test/knowledge_collection_tools_test.py index 16bfb27..0b1c7ce 100644 --- a/test/knowledge_collection_tools_test.py +++ b/test/knowledge_collection_tools_test.py @@ -1,13 +1,144 @@ import dkg.utils.knowledge_collection_tools as kc_tools +import uuid class TestGroupNQuadsBySubject: def test_resource_object_quad(self): + # JSON-LD equivalent of the quads being tested: + # + # { + # "@context": "http://schema.org", + # "@id": "http://example.org/book1", + # "author": { + # "@id": "http://example.org/author1" + # } + # } quads = [ " .", " .", ] grouped = kc_tools.group_nquads_by_subject(quads) assert len(grouped) == 1 + print(grouped[0][0]) + print(quads[0]) assert quads[0] in grouped[0] assert quads[1] in grouped[0] + + def test_literal_object_quad(self): + # JSON-LD equivalent of the quads being tested: + # + # { + # "@context": "http://schema.org", + # "@id": "http://example.org/book1", + # "type": "Book", + # "title": "The Great Book" + # } + quads = [ + ' "The Great Book" .', + " .", + ] + grouped = kc_tools.group_nquads_by_subject(quads) + assert len(grouped) == 1 + assert quads[0] in grouped[0] + assert quads[1] in grouped[0] + + def test_literal_with_escape_character(self): + # JSON-LD equivalent of the quads being tested: + # + # { + # "@context": "http://schema.org", + # "@id": "http://example.org/book1", + # "type": "Book", + # "title": "The Great Book \n" + # } + quads = [ + ' "The Great Book \\n" .', + " .", + ] + grouped = kc_tools.group_nquads_by_subject(quads) + assert len(grouped) == 1 + assert quads[0] in grouped[0] + assert quads[1] in grouped[0] + + def test_literal_with_language_tags(self): + # JSON-LD equivalent of the quads being tested: + # + # { + # "@context": "http://schema.org", + # "@id": "http://example.org/book1", + # "type": "Book", + # "description": [ + # { + # "@value": "A thrilling adventure novel.", + # "@language": "en" + # }, + # { + # "@value": "Napeta pustolovska novela.", + # "@language": "sl" + # } + # ] + # } + quads = [ + ' "A thrilling adventure novel."@en .', + ' "Napeta pustolovska novela."@sl .', + " .", + ] + grouped = kc_tools.group_nquads_by_subject(quads) + assert len(grouped) == 1 + assert quads[0] in grouped[0] + assert quads[1] in grouped[0] + assert quads[2] in grouped[0] + + def test_literal_with_language_and_escape_character(self): + # JSON-LD equivalent of the quads being tested: + # + # { + # "@context": "http://schema.org", + # "@id": "http://example.org/book1", + # "type": "Book", + # "description": [ + # { + # "@value": "A thrilling adventure novel. \n", + # "@language": "en" + # }, + # { + # "@value": "Napeta pustolovska novela. \n", + # "@language": "sl" + # } + # ] + # } + quads = [ + ' "A thrilling adventure novel. \n"@en .', + ' "Napeta pustolovska novela. \n"@sl .', + " .", + ] + grouped = kc_tools.group_nquads_by_subject(quads) + assert len(grouped) == 1 + assert quads[0] in [nquad.encode("unicode_escape") for nquad in grouped[0]] + assert quads[1] in grouped[0] + assert quads[2] in grouped[0] + + def test_literal_with_language_and_blank_node_subject(self): + # JSON-LD equivalent of the quads being tested: + # + # { + # "@context": { + # "predicate": "http://example.org/predicate" + # }, + # "@graph": [ + # { + # "predicate": { + # "@value": "something", + # "@language": "en" + # } + # } + # ] + # } + + subject = f"" + quads = [ + f'{subject} "something"@en .', + ] + grouped = kc_tools.group_nquads_by_subject(quads) + assert len(grouped) == 1 + assert quads[0] in grouped[0] From 7919d9c9cd7199d2afdb164617e35b5ea8f90078 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 3 Jun 2025 16:07:46 +0200 Subject: [PATCH 133/146] emoji test case added --- test/knowledge_collection_tools_test.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/knowledge_collection_tools_test.py b/test/knowledge_collection_tools_test.py index 0b1c7ce..3f90f60 100644 --- a/test/knowledge_collection_tools_test.py +++ b/test/knowledge_collection_tools_test.py @@ -42,6 +42,24 @@ def test_literal_object_quad(self): assert quads[0] in grouped[0] assert quads[1] in grouped[0] + def test_literal_object_quad_with_an_emoticon(self): + # JSON-LD equivalent of the quads being tested: + # + # { + # "@context": "http://schema.org", + # "@id": "http://example.org/book1", + # "type": "Book", + # "title": "The Great Book" + # } + quads = [ + ' "The Great Book 😀" .', + " .", + ] + grouped = kc_tools.group_nquads_by_subject(quads) + assert len(grouped) == 1 + assert quads[0] in grouped[0] + assert quads[1] in grouped[0] + def test_literal_with_escape_character(self): # JSON-LD equivalent of the quads being tested: # From 74ea9f2a7c0296639d59273b337e3a7a680a2b9f Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Thu, 5 Jun 2025 09:32:51 +0200 Subject: [PATCH 134/146] updated groupBySubject and blank node tests --- test/knowledge_collection_tools_test.py | 456 +++++++++++++++++++++--- 1 file changed, 404 insertions(+), 52 deletions(-) diff --git a/test/knowledge_collection_tools_test.py b/test/knowledge_collection_tools_test.py index 3f90f60..9ebe289 100644 --- a/test/knowledge_collection_tools_test.py +++ b/test/knowledge_collection_tools_test.py @@ -1,5 +1,8 @@ import dkg.utils.knowledge_collection_tools as kc_tools +from rdflib import Dataset, URIRef, Literal import uuid +import re +import pytest class TestGroupNQuadsBySubject: @@ -17,7 +20,7 @@ def test_resource_object_quad(self): " .", " .", ] - grouped = kc_tools.group_nquads_by_subject(quads) + grouped = kc_tools.group_nquads_by_subject(quads, sort=True) assert len(grouped) == 1 print(grouped[0][0]) print(quads[0]) @@ -37,7 +40,7 @@ def test_literal_object_quad(self): ' "The Great Book" .', " .", ] - grouped = kc_tools.group_nquads_by_subject(quads) + grouped = kc_tools.group_nquads_by_subject(quads, sort=True) assert len(grouped) == 1 assert quads[0] in grouped[0] assert quads[1] in grouped[0] @@ -55,25 +58,7 @@ def test_literal_object_quad_with_an_emoticon(self): ' "The Great Book 😀" .', " .", ] - grouped = kc_tools.group_nquads_by_subject(quads) - assert len(grouped) == 1 - assert quads[0] in grouped[0] - assert quads[1] in grouped[0] - - def test_literal_with_escape_character(self): - # JSON-LD equivalent of the quads being tested: - # - # { - # "@context": "http://schema.org", - # "@id": "http://example.org/book1", - # "type": "Book", - # "title": "The Great Book \n" - # } - quads = [ - ' "The Great Book \\n" .', - " .", - ] - grouped = kc_tools.group_nquads_by_subject(quads) + grouped = kc_tools.group_nquads_by_subject(quads, sort=True) assert len(grouped) == 1 assert quads[0] in grouped[0] assert quads[1] in grouped[0] @@ -101,41 +86,12 @@ def test_literal_with_language_tags(self): ' "Napeta pustolovska novela."@sl .', " .", ] - grouped = kc_tools.group_nquads_by_subject(quads) + grouped = kc_tools.group_nquads_by_subject(quads, sort=True) assert len(grouped) == 1 assert quads[0] in grouped[0] assert quads[1] in grouped[0] assert quads[2] in grouped[0] - def test_literal_with_language_and_escape_character(self): - # JSON-LD equivalent of the quads being tested: - # - # { - # "@context": "http://schema.org", - # "@id": "http://example.org/book1", - # "type": "Book", - # "description": [ - # { - # "@value": "A thrilling adventure novel. \n", - # "@language": "en" - # }, - # { - # "@value": "Napeta pustolovska novela. \n", - # "@language": "sl" - # } - # ] - # } - quads = [ - ' "A thrilling adventure novel. \n"@en .', - ' "Napeta pustolovska novela. \n"@sl .', - " .", - ] - grouped = kc_tools.group_nquads_by_subject(quads) - assert len(grouped) == 1 - assert quads[0] in [nquad.encode("unicode_escape") for nquad in grouped[0]] - assert quads[1] in grouped[0] - assert quads[2] in grouped[0] - def test_literal_with_language_and_blank_node_subject(self): # JSON-LD equivalent of the quads being tested: # @@ -157,6 +113,402 @@ def test_literal_with_language_and_blank_node_subject(self): quads = [ f'{subject} "something"@en .', ] - grouped = kc_tools.group_nquads_by_subject(quads) + grouped = kc_tools.group_nquads_by_subject(quads, sort=True) assert len(grouped) == 1 assert quads[0] in grouped[0] + + +class TestGenerateMissingIdsForBlankNodes: + def test_blank_node_replacement(self): + # JSON-LD equivalent of the quads being tested: + # + # { + # "@context": { + # "relatedTo": "http://example.org/relatedTo" + # }, + # "@id": "http://example.org/document/1", + # "relatedTo": {} + # } + + nquads_array = [ + " _:c14n0 .", + ] + + updated_quads = kc_tools.generate_missing_ids_for_blank_nodes(nquads_array) + all_nquads = "\n".join(nquad for nquad in updated_quads if nquad.strip()) + + d = Dataset() + d.parse(data=all_nquads, format="nquads") + + quad_count = sum(1 for _ in d.quads()) + assert quad_count == 1 + + o = None + + for s, p, o_val, _ in d.quads( + ( + URIRef("http://example.org/document/1"), + URIRef("http://example.org/relatedTo"), + None, + ) + ): + o = o_val + + uuid_regex = re.compile(r"^uuid:[0-9a-fA-F\-]{36}$") + + assert isinstance(o, URIRef) + assert uuid_regex.match(str(o)) + + def test_shared_blank_node_replacement(self): + # Equivalent JSON-LD structure: + # + # { + # "@context": { "is": "http://example.org/is" }, + # "@graph": [ + # { + # "@id": "http://example.org/subject1", + # "is": { "@id": "_:sharedBlank" } + # }, + # { + # "@id": "http://example.org/subject2", + # "is": { "@id": "_:sharedBlank" } + # } + # ] + # } + + nquads_array = [ + " _:c14n0 .", + " _:c14n0 .", + ] + + updated_quads = kc_tools.generate_missing_ids_for_blank_nodes(nquads_array) + all_nquads = "\n".join(nquad for nquad in updated_quads if nquad.strip()) + + d = Dataset() + d.parse(data=all_nquads, format="nquads") + + quad_count = sum(1 for _ in d.quads()) + assert quad_count == 2 + + o1 = None + o2 = None + + for s, p, o, _ in d.quads( + ( + URIRef("http://example.org/subject1"), + URIRef("http://example.org/is"), + None, + ) + ): + o1 = o + for s, p, o, _ in d.quads( + ( + URIRef("http://example.org/subject2"), + URIRef("http://example.org/is"), + None, + ) + ): + o2 = o + + uuid_regex = re.compile(r"^uuid:[0-9a-fA-F\-]{36}$") + + assert isinstance(o1, URIRef) + assert isinstance(o2, URIRef) + + assert uuid_regex.match(str(o1)) + assert uuid_regex.match(str(o2)) + + assert str(o1) == str(o2) + + def test_subject_blank_node_replacement(self): + # Equivalent JSON-LD structure: + # + # { + # "@context": { "ex": "http://example.org/" }, + # "@graph": [ + # { + # "ex:name": "John Doe" + # } + # ] + # } + + nquads_array = [ + '_:c14n0 "John Doe" .', + ] + + updated_quads = kc_tools.generate_missing_ids_for_blank_nodes(nquads_array) + all_nquads = "\n".join(nquad for nquad in updated_quads if nquad.strip()) + + d = Dataset() + d.parse(data=all_nquads, format="nquads") + + quad_count = sum(1 for _ in d.quads()) + assert quad_count == 1 + + s = None + + for subj, pred, obj_val, _ in d.quads( + (None, URIRef("http://example.org/name"), Literal("John Doe")) + ): + s = subj + + uuid_regex = re.compile(r"^uuid:[0-9a-fA-F\-]{36}$") + + assert isinstance(s, URIRef) + assert uuid_regex.match(str(s)) + + def test_occuring_subject_blank_node_replacement(self): + # Equivalent JSON-LD: + # + # { + # "@context": { "ex": "http://example.org/" }, + # "@graph": [ + # { + # "ex:name": "John Doe", + # "ex:sex": "male" + # } + # ] + # } + + nquads_array = [ + '_:c14n0 "John Doe" .', + '_:c14n0 "male" .', + ] + + updated_quads = kc_tools.generate_missing_ids_for_blank_nodes(nquads_array) + all_nquads = "\n".join(q for q in updated_quads if q.strip()) + + d = Dataset() + d.parse(data=all_nquads, format="nquads") + + quad_count = sum(1 for _ in d.quads()) + assert quad_count == 2 + + s1 = None + s2 = None + + for s, p, o, _ in d.quads( + (None, URIRef("http://example.org/name"), Literal("John Doe")) + ): + s1 = s + + for s, p, o, _ in d.quads( + (None, URIRef("http://example.org/sex"), Literal("male")) + ): + s2 = s + + uuid_regex = re.compile(r"^uuid:[0-9a-fA-F\-]{36}$") + + assert isinstance(s1, URIRef) + assert isinstance(s2, URIRef) + assert uuid_regex.match(str(s1)) + assert uuid_regex.match(str(s2)) + assert s1 == s2 + + def test_different_blank_subjects_have_different_uuids(self): + # Equivalent JSON-LD: + # + # { + # "@context": { "ex": "http://example.org/" }, + # "@graph": [ + # { + # "ex:hasName": "Alice", + # "ex:sex": "male" + # }, + # { + # "ex:hasName": "Bob", + # "ex:sex": "female" + # } + # ] + # } + + nquads_array = [ + '_:c14n0 "male" .', + '_:c14n0 "Bob" .', + '_:c14n1 "female" .', + '_:c14n1 "Alice" .', + ] + + updated_quads = kc_tools.generate_missing_ids_for_blank_nodes(nquads_array) + all_nquads = "\n".join(q for q in updated_quads if q.strip()) + + d = Dataset() + d.parse(data=all_nquads, format="nquads") + + quad_count = sum(1 for _ in d.quads()) + assert quad_count == 4 + + s1 = None + s2 = None + s3 = None + s4 = None + + for s, p, o, _ in d.quads( + (None, URIRef("http://example.org/hasName"), Literal("Bob")) + ): + s1 = s + + for s, p, o, _ in d.quads( + (None, URIRef("http://example.org/sex"), Literal("male")) + ): + s2 = s + + for s, p, o, _ in d.quads( + (None, URIRef("http://example.org/hasName"), Literal("Alice")) + ): + s3 = s + + for s, p, o, _ in d.quads( + (None, URIRef("http://example.org/sex"), Literal("female")) + ): + s4 = s + + uuid_regex = re.compile(r"^uuid:[0-9a-fA-F\-]{36}$") + + assert isinstance(s1, URIRef) + assert isinstance(s2, URIRef) + assert uuid_regex.match(str(s1)) + assert uuid_regex.match(str(s2)) + assert s1 == s2 + + assert isinstance(s3, URIRef) + assert isinstance(s4, URIRef) + assert uuid_regex.match(str(s3)) + assert uuid_regex.match(str(s4)) + assert s3 == s4 + + assert s1 != s3 + + def test_blank_node_used_as_object_and_subject_has_same_uuid(self): + # Equivalent JSON-LD: + # + # { + # "@context": "http://schema.org", + # "review": { + # "reviewBody": "Excellent book!" + # } + # } + + nquads_array = [ + '_:c14n0 "Excellent book!" .', + "_:c14n1 _:c14n0 .", + ] + + updated_quads = kc_tools.generate_missing_ids_for_blank_nodes(nquads_array) + all_nquads = "\n".join(q for q in updated_quads if q.strip()) + + d = Dataset() + d.parse(data=all_nquads, format="nquads") + + quad_count = sum(1 for _ in d.quads()) + assert quad_count == 2 + + s1 = None + s2 = None + o2 = None + + for s, p, o, _ in d.quads( + (None, URIRef("http://schema.org/reviewBody"), Literal("Excellent book!")) + ): + s1 = s + + for s, p, o, _ in d.quads((None, URIRef("http://schema.org/review"), None)): + s2 = s + o2 = o + + uuid_regex = re.compile(r"^uuid:[0-9a-fA-F\-]{36}$") + + assert isinstance(s1, URIRef) + assert uuid_regex.match(str(s1)) + + assert isinstance(s2, URIRef) + assert uuid_regex.match(str(s2)) + + assert isinstance(o2, URIRef) + assert uuid_regex.match(str(o2)) + + assert str(s1) != str(s2) + assert str(o2) == str(s1) + + def test_creating_new_graphs_error(self): + # { + # "@context": { + # "kjdh@base": "https://example.org/", + # "name": "http://schema.org/name", + # "knows": { + # "@id": "http://schema.org/knows", + # "@type": "@id" + # }, + # "Person": "http://schema.org/Person" + # }, + # "@graph": [ + # { + # "@type": "Person", + # "name": "Alice", + # "knows": [ + # { + # "@id": "_:bob" + # }, + # { + # "@id": "_:carol" + # } + # ] + # }, + # { + # "@id": "_:bob", + # "@graph": [ + # { + # "@type": "Person", + # "name": "Bob" + # } + # ] + # }, + # { + # "@id": "_:carol", + # "@graph": [ + # { + # "@type": "Person", + # "name": "Carol" + # } + # ] + # } + # ] + # } + + nquads_array = [ + '_:c14n2 "Carol" _:c14n0 .', + "_:c14n2 _:c14n0 .", + "_:c14n3 _:c14n0 .", + "_:c14n3 _:c14n1 .", + '_:c14n3 "Alice" .', + "_:c14n3 .", + '_:c14n4 "Bob" _:c14n1 .', + "_:c14n4 _:c14n1 .", + ] + with pytest.raises(kc_tools.UnsupportedJSONLD) as exc: + raise kc_tools.UnsupportedJSONLD(nquads_array) + + expected_message = """Unsupported JSON-LD input detected + +After parsing the JSON-LD input, the parser detected creation of new named graphs. +The DKG does not support custom named graphs. + +Problematic Quads: + +1. _:c14n2 "Carol" _:c14n0 . +2. _:c14n2 _:c14n0 . +3. _:c14n4 "Bob" _:c14n1 . +4. _:c14n4 _:c14n1 . + +Full Parsed N-Quads Array: + +_:c14n2 "Carol" _:c14n0 . +_:c14n2 _:c14n0 . +_:c14n3 _:c14n0 . +_:c14n3 _:c14n1 . +_:c14n3 "Alice" . +_:c14n3 . +_:c14n4 "Bob" _:c14n1 . +_:c14n4 _:c14n1 .""" + + assert exc.value.message.strip() == expected_message From b739d5ad24a4069df42c8a04ea70c41a85beb9ad Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Thu, 5 Jun 2025 09:55:10 +0200 Subject: [PATCH 135/146] version bump to 8.0.14 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8c200a7..a6ddf3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.13" +version = "8.0.14" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From 5ba6a0412d802991b2f7b65141d6f6ab611827b4 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 17 Jun 2025 10:59:39 +0200 Subject: [PATCH 136/146] main logic refined --- dkg/modules/asset/asset.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/dkg/modules/asset/asset.py b/dkg/modules/asset/asset.py index 33a79f2..16558ff 100644 --- a/dkg/modules/asset/asset.py +++ b/dkg/modules/asset/asset.py @@ -386,24 +386,16 @@ def create( if token_amount: estimated_publishing_cost = token_amount else: - time_until_next_epoch = self.blockchain_service.time_until_next_epoch() - epoch_length = self.blockchain_service.epoch_length() stake_weighted_average_ask = ( self.blockchain_service.get_stake_weighted_average_ask() ) # Convert to integers and perform calculation estimated_publishing_cost = ( - ( - int(stake_weighted_average_ask) - * ( - int(epochs_num) * int(1e18) - + (int(time_until_next_epoch) * int(1e18)) // int(epoch_length) - ) - * int(dataset_size) - ) + int(stake_weighted_average_ask) + * int(epochs_num) + * int(dataset_size) // 1024 - // int(1e18) ) knowledge_collection_id = None From 32ad8dc6fd3ad00ab17d8149ead83f42f3eaafab Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 17 Jun 2025 11:14:31 +0200 Subject: [PATCH 137/146] main logic refined async --- dkg/modules/asset/async_asset.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/dkg/modules/asset/async_asset.py b/dkg/modules/asset/async_asset.py index 639b52a..655c434 100644 --- a/dkg/modules/asset/async_asset.py +++ b/dkg/modules/asset/async_asset.py @@ -398,26 +398,16 @@ async def create( if token_amount: estimated_publishing_cost = token_amount else: - time_until_next_epoch = ( - await self.blockchain_service.time_until_next_epoch() - ) - epoch_length = await self.blockchain_service.epoch_length() stake_weighted_average_ask = ( await self.blockchain_service.get_stake_weighted_average_ask() ) # Convert to integers and perform calculation estimated_publishing_cost = ( - ( - int(stake_weighted_average_ask) - * ( - int(epochs_num) * int(1e18) - + (int(time_until_next_epoch) * int(1e18)) // int(epoch_length) - ) - * int(dataset_size) - ) + int(stake_weighted_average_ask) + * int(epochs_num) + * int(dataset_size) // 1024 - // int(1e18) ) knowledge_collection_id = None From 6e94a60c07c600129f24b4021bfa5747b0705da8 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 26 Jun 2025 16:46:28 +0200 Subject: [PATCH 138/146] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a6ddf3b..9c87c5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.0.14" +version = "8.1.0" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From 74029f93eaa80fc48e90a88da31c2f626e7bd07a Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Fri, 4 Jul 2025 10:49:56 +0200 Subject: [PATCH 139/146] added calculate merkle root test --- test/knowledge_collection_tools_test.py | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/knowledge_collection_tools_test.py b/test/knowledge_collection_tools_test.py index 9ebe289..b3c30b1 100644 --- a/test/knowledge_collection_tools_test.py +++ b/test/knowledge_collection_tools_test.py @@ -512,3 +512,29 @@ def test_creating_new_graphs_error(self): _:c14n4 _:c14n1 .""" assert exc.value.message.strip() == expected_message + + +class TestCalculateMerkleRoot: + def test_calculate_merkle_root_with_example_data(self): + """Test calculate_merkle_root function with real-world example data.""" + quads = [ + ' "468.9 sq mi" .', + ' "New York" .', + ' "8,336,817" .', + ' "New York" .', + " .", + ' "0xaac2a420672a1eb77506c544ff01beed2be58c0ee3576fe037c846f97481cefd" .', + " .", + " .", + " .", + ] + + merkle_root = kc_tools.calculate_merkle_root(quads) + + # Expected merkle root for this dataset + expected_merkle_root = ( + "0x897442f7db61619b9f272c69d787975f169d0624d7f08c216017c3218c8ea5da" + ) + + # Verify the result matches the expected value + assert merkle_root == expected_merkle_root From a3fe9b8513e8404881d92bee7ef74830483e65ef Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 7 Jul 2025 14:41:37 +0200 Subject: [PATCH 140/146] sorted inner arrays aswell --- dkg/utils/knowledge_collection_tools.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py index 63c5846..0097d43 100644 --- a/dkg/utils/knowledge_collection_tools.py +++ b/dkg/utils/knowledge_collection_tools.py @@ -207,7 +207,10 @@ def group_nquads_by_subject(nquads_list: list[str], sort: bool = False): # Return grouped quads (sorted if requested) grouped_items = sorted(grouped.items()) if sort else grouped.items() - return [quads for _, quads in grouped_items] + if sort: + return [sorted(quads) for _, quads in grouped_items] + else: + return [quads for _, quads in grouped_items] def calculate_number_of_chunks(quads, chunk_size_bytes=CHUNK_BYTE_SIZE): From e949ee66a1dcbe5024ee42532a871d4a1bc8a67b Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 7 Jul 2025 15:43:21 +0200 Subject: [PATCH 141/146] updated abis --- dkg/data/interfaces/KnowledgeCollection.json | 156 +--- dkg/data/interfaces/Paranet.json | 740 ++++++++++++++---- .../ParanetIncentivesPoolFactory.json | 159 ++-- .../ParanetKnowledgeMinersRegistry.json | 233 +++--- dkg/data/interfaces/ParanetsRegistry.json | 576 ++++++++------ 5 files changed, 1164 insertions(+), 700 deletions(-) diff --git a/dkg/data/interfaces/KnowledgeCollection.json b/dkg/data/interfaces/KnowledgeCollection.json index 3eaeebf..0b17b30 100644 --- a/dkg/data/interfaces/KnowledgeCollection.json +++ b/dkg/data/interfaces/KnowledgeCollection.json @@ -10,17 +10,6 @@ "stateMutability": "nonpayable", "type": "constructor" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "CannotUpdateImmutableKnowledgeCollection", - "type": "error" - }, { "inputs": [ { @@ -200,11 +189,6 @@ "name": "ZeroAddressHub", "type": "error" }, - { - "inputs": [], - "name": "ZeroTokenAmount", - "type": "error" - }, { "inputs": [], "name": "askStorage", @@ -382,29 +366,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "address", - "name": "paymaster", - "type": "address" - } - ], - "name": "increaseKnowledgeCollectionTokenAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "initialize", @@ -451,6 +412,45 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "paranetKnowledgeCollectionsRegistry", + "outputs": [ + { + "internalType": "contract ParanetKnowledgeCollectionsRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paranetKnowledgeMinersRegistry", + "outputs": [ + { + "internalType": "contract ParanetKnowledgeMinersRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paranetsRegistry", + "outputs": [ + { + "internalType": "contract ParanetsRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "paymasterManager", @@ -516,84 +516,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "string", - "name": "updateOperationId", - "type": "string" - }, - { - "internalType": "bytes32", - "name": "merkleRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "mintKnowledgeAssetsAmount", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "knowledgeAssetsToBurn", - "type": "uint256[]" - }, - { - "internalType": "uint88", - "name": "byteSize", - "type": "uint88" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "address", - "name": "paymaster", - "type": "address" - }, - { - "internalType": "uint72", - "name": "publisherNodeIdentityId", - "type": "uint72" - }, - { - "internalType": "bytes32", - "name": "publisherNodeR", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "publisherNodeVS", - "type": "bytes32" - }, - { - "internalType": "uint72[]", - "name": "identityIds", - "type": "uint72[]" - }, - { - "internalType": "bytes32[]", - "name": "r", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "vs", - "type": "bytes32[]" - } - ], - "name": "updateKnowledgeCollection", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "version", diff --git a/dkg/data/interfaces/Paranet.json b/dkg/data/interfaces/Paranet.json index 04ce899..9bdce03 100644 --- a/dkg/data/interfaces/Paranet.json +++ b/dkg/data/interfaces/Paranet.json @@ -13,12 +13,12 @@ { "inputs": [ { - "internalType": "enum ParanetLib.MinersAccessPolicy[]", + "internalType": "uint8[]", "name": "expectedAccessPolicies", "type": "uint8[]" }, { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "actualAccessPolicy", "type": "uint8" } @@ -29,12 +29,12 @@ { "inputs": [ { - "internalType": "enum ParanetLib.NodesAccessPolicy[]", + "internalType": "uint8[]", "name": "expectedAccessPolicies", "type": "uint8[]" }, { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "actualAccessPolicy", "type": "uint8" } @@ -42,6 +42,43 @@ "name": "InvalidParanetNodesAccessPolicy", "type": "error" }, + { + "inputs": [ + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "KnowledgeCollectionIsAPartOfOtherParanet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionNotInFirstEpoch", + "type": "error" + }, { "inputs": [ { @@ -55,7 +92,7 @@ "type": "address" } ], - "name": "ParanetCuratedMinerAccessRequestDoesntExist", + "name": "ParanetPermissionedMinerAccessRequestDoesntExist", "type": "error" }, { @@ -76,7 +113,7 @@ "type": "uint8" } ], - "name": "ParanetCuratedMinerAccessRequestInvalidStatus", + "name": "ParanetPermissionedMinerAccessRequestInvalidStatus", "type": "error" }, { @@ -92,7 +129,7 @@ "type": "address" } ], - "name": "ParanetCuratedMinerDoesntExist", + "name": "ParanetPermissionedMinerDoesntExist", "type": "error" }, { @@ -108,7 +145,7 @@ "type": "address" } ], - "name": "ParanetCuratedMinerHasAlreadyBeenAdded", + "name": "ParanetPermissionedMinerHasAlreadyBeenAdded", "type": "error" }, { @@ -124,7 +161,7 @@ "type": "uint72" } ], - "name": "ParanetCuratedNodeDoesntExist", + "name": "ParanetPermissionedNodeDoesntExist", "type": "error" }, { @@ -140,7 +177,7 @@ "type": "uint72" } ], - "name": "ParanetCuratedNodeHasAlreadyBeenAdded", + "name": "ParanetPermissionedNodeHasAlreadyBeenAdded", "type": "error" }, { @@ -156,7 +193,7 @@ "type": "uint72" } ], - "name": "ParanetCuratedNodeJoinRequestDoesntExist", + "name": "ParanetPermissionedNodeJoinRequestDoesntExist", "type": "error" }, { @@ -177,51 +214,24 @@ "type": "uint8" } ], - "name": "ParanetCuratedNodeJoinRequestInvalidStatus", + "name": "ParanetPermissionedNodeJoinRequestInvalidStatus", "type": "error" }, { "inputs": [ { "internalType": "address", - "name": "knowledgeAssetStorageAddress", + "name": "knowledgeCollectionStorageAddress", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" - } - ], - "name": "ParanetDoesntExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "knowledgeAssetStorageAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ParanetHasAlreadyBeenRegistered", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "knowledgeAssetStorageAddress", - "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeAssetTokenId", "type": "uint256" } ], @@ -248,12 +258,17 @@ "inputs": [ { "internalType": "address", - "name": "knowledgeAssetStorageAddress", + "name": "knowledgeCollectionStorageAddress", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetTokenId", "type": "uint256" } ], @@ -293,29 +308,35 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "knowledgeAssetTokenId", + "name": "knowledgeCollectionId", "type": "uint256" } ], - "name": "KnowledgeAssetSubmittedToParanet", + "name": "KnowledgeCollectionSubmittedToParanet", "type": "event" }, { @@ -324,9 +345,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -334,13 +361,30 @@ "type": "uint256" }, { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "storageAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + } + ], "indexed": false, - "internalType": "address", - "name": "minerAddress", - "type": "address" + "internalType": "struct ParanetLib.IncentivesPool", + "name": "incentivesPool", + "type": "tuple" } ], - "name": "ParanetCuratedMinerAccessRequestAccepted", + "name": "ParanetIncetivesPoolDeployed", "type": "event" }, { @@ -349,9 +393,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -360,12 +410,18 @@ }, { "indexed": false, - "internalType": "address", - "name": "minerAddress", - "type": "address" + "internalType": "string", + "name": "newParanetName", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newParanetDescription", + "type": "string" } ], - "name": "ParanetCuratedMinerAccessRequestCreated", + "name": "ParanetMetadataUpdated", "type": "event" }, { @@ -374,9 +430,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -390,7 +452,7 @@ "type": "address" } ], - "name": "ParanetCuratedMinerAccessRequestRejected", + "name": "ParanetPermissionedMinerAccessRequestAccepted", "type": "event" }, { @@ -399,9 +461,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -415,7 +483,7 @@ "type": "address" } ], - "name": "ParanetCuratedMinerAdded", + "name": "ParanetPermissionedMinerAccessRequestCreated", "type": "event" }, { @@ -424,9 +492,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -440,7 +514,7 @@ "type": "address" } ], - "name": "ParanetCuratedMinerRemoved", + "name": "ParanetPermissionedMinerAccessRequestRejected", "type": "event" }, { @@ -449,9 +523,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -460,12 +540,12 @@ }, { "indexed": false, - "internalType": "uint72", - "name": "identityId", - "type": "uint72" + "internalType": "address", + "name": "minerAddress", + "type": "address" } ], - "name": "ParanetCuratedNodeAdded", + "name": "ParanetPermissionedMinerAdded", "type": "event" }, { @@ -474,9 +554,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -485,12 +571,12 @@ }, { "indexed": false, - "internalType": "uint72", - "name": "identityId", - "type": "uint72" + "internalType": "address", + "name": "minerAddress", + "type": "address" } ], - "name": "ParanetCuratedNodeJoinRequestAccepted", + "name": "ParanetPermissionedMinerRemoved", "type": "event" }, { @@ -499,9 +585,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -515,7 +607,7 @@ "type": "uint72" } ], - "name": "ParanetCuratedNodeJoinRequestCreated", + "name": "ParanetPermissionedNodeAdded", "type": "event" }, { @@ -524,9 +616,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -540,7 +638,7 @@ "type": "uint72" } ], - "name": "ParanetCuratedNodeJoinRequestRejected", + "name": "ParanetPermissionedNodeJoinRequestAccepted", "type": "event" }, { @@ -549,9 +647,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -565,7 +669,7 @@ "type": "uint72" } ], - "name": "ParanetCuratedNodeRemoved", + "name": "ParanetPermissionedNodeJoinRequestCreated", "type": "event" }, { @@ -574,9 +678,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -584,25 +694,13 @@ "type": "uint256" }, { - "components": [ - { - "internalType": "string", - "name": "poolType", - "type": "string" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], "indexed": false, - "internalType": "struct ParanetLib.IncentivesPool", - "name": "incentivesPool", - "type": "tuple" + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "ParanetIncetivesPoolDeployed", + "name": "ParanetPermissionedNodeJoinRequestRejected", "type": "event" }, { @@ -611,29 +709,29 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { - "indexed": false, - "internalType": "string", - "name": "newParanetName", - "type": "string" + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" }, { "indexed": false, - "internalType": "string", - "name": "newParanetDescription", - "type": "string" + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "ParanetMetadataUpdated", + "name": "ParanetPermissionedNodeRemoved", "type": "event" }, { @@ -642,13 +740,19 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "parnetKATokenId", "type": "uint256" }, { @@ -665,20 +769,20 @@ }, { "indexed": false, - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "nodesAccessPolicy", "type": "uint8" }, { "indexed": false, - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "minersAccessPolicy", "type": "uint8" }, { "indexed": false, - "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", - "name": "knowledgeAssetsAccessPolicy", + "internalType": "uint8", + "name": "knowledgeCollectionsSubmissionPolicy", "type": "uint8" } ], @@ -691,21 +795,33 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "paranetServiceKCTokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -722,9 +838,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetServiceKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -759,9 +881,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetServiceKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -794,9 +922,42 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeAssetTokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "curator", + "type": "address" + } + ], + "name": "addCurator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -808,7 +969,7 @@ "type": "address[]" } ], - "name": "addParanetCuratedMiners", + "name": "addParanetPermissionedMiners", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -817,9 +978,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -831,7 +997,7 @@ "type": "uint72[]" } ], - "name": "addParanetCuratedNodes", + "name": "addParanetPermissionedNodes", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -840,9 +1006,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -852,12 +1023,17 @@ "components": [ { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetTokenId", "type": "uint256" } ], @@ -875,9 +1051,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -889,7 +1070,7 @@ "type": "address" } ], - "name": "approveCuratedMiner", + "name": "approvePermissionedMiner", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -898,9 +1079,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -912,11 +1098,65 @@ "type": "uint72" } ], - "name": "approveCuratedNode", + "name": "approvePermissionedNode", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "chronos", + "outputs": [ + { + "internalType": "contract Chronos", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "getKnowledgeCollectionLocatorsWithPagination", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + } + ], + "internalType": "struct ParanetLib.UniversalAssetCollectionLocator[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "hub", @@ -965,10 +1205,10 @@ }, { "inputs": [], - "name": "paranetKnowledgeAssetsRegistry", + "name": "paranetKnowledgeCollectionsRegistry", "outputs": [ { - "internalType": "contract ParanetKnowledgeAssetsRegistry", + "internalType": "contract ParanetKnowledgeCollectionsRegistry", "name": "", "type": "address" } @@ -1002,6 +1242,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "paranetStagingRegistry", + "outputs": [ + { + "internalType": "contract ParanetStagingRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "paranetsRegistry", @@ -1032,9 +1285,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -1051,14 +1309,19 @@ "type": "string" }, { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "minersAccessPolicy", "type": "uint8" + }, + { + "internalType": "uint8", + "name": "knowledgeCollectionsSubmissionPolicy", + "type": "uint8" } ], "name": "registerParanet", @@ -1076,9 +1339,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetServiceKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetServiceKATokenId", @@ -1115,9 +1383,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -1129,7 +1402,7 @@ "type": "address" } ], - "name": "rejectCuratedMiner", + "name": "rejectPermissionedMiner", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1138,9 +1411,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -1152,7 +1430,35 @@ "type": "uint72" } ], - "name": "rejectCuratedNode", + "name": "rejectPermissionedNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeAssetTokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "curator", + "type": "address" + } + ], + "name": "removeCurator", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1161,9 +1467,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -1175,7 +1486,7 @@ "type": "address[]" } ], - "name": "removeParanetCuratedMiners", + "name": "removeParanetPermissionedMiners", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1184,9 +1495,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -1198,7 +1514,7 @@ "type": "uint72[]" } ], - "name": "removeParanetCuratedNodes", + "name": "removeParanetPermissionedNodes", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1207,16 +1523,21 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", "type": "uint256" } ], - "name": "requestParanetCuratedMinerAccess", + "name": "requestParanetPermissionedMinerAccess", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1225,16 +1546,59 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", "type": "uint256" } ], - "name": "requestParanetCuratedNodeAccess", + "name": "requestParanetPermissionedNodeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeAssetTokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "accepted", + "type": "bool" + } + ], + "name": "reviewKnowledgeCollection", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1252,6 +1616,39 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeAssetTokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + } + ], + "name": "stageKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "status", @@ -1269,9 +1666,47 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeAssetTokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + } + ], + "name": "submitKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -1297,9 +1732,14 @@ "inputs": [ { "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetServiceKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetServiceKATokenId", diff --git a/dkg/data/interfaces/ParanetIncentivesPoolFactory.json b/dkg/data/interfaces/ParanetIncentivesPoolFactory.json index 774b229..87a2d9c 100644 --- a/dkg/data/interfaces/ParanetIncentivesPoolFactory.json +++ b/dkg/data/interfaces/ParanetIncentivesPoolFactory.json @@ -13,44 +13,61 @@ { "inputs": [ { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, "internalType": "address", - "name": "knowledgeAssetStorageAddress", + "name": "paranetKCStorageContract", "type": "address" }, { + "indexed": true, "internalType": "uint256", - "name": "tokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { - "internalType": "string", - "name": "poolType", - "type": "string" + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" }, { + "indexed": false, + "internalType": "address", + "name": "storageAddress", + "type": "address" + }, + { + "indexed": false, "internalType": "address", "name": "poolAddress", "type": "address" - } - ], - "name": "ParanetIncentivesPoolAlreadyExists", - "type": "error" - }, - { - "inputs": [ + }, { - "internalType": "string", - "name": "msg", - "type": "string" + "indexed": false, + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" } ], - "name": "UnauthorizedAccess", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressHub", - "type": "error" + "name": "ParanetIncentivesPoolDeployed", + "type": "event" }, { "anonymous": false, @@ -58,9 +75,15 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -68,34 +91,33 @@ "type": "uint256" }, { - "components": [ - { - "internalType": "string", - "name": "poolType", - "type": "string" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], "indexed": false, - "internalType": "struct ParanetLib.IncentivesPool", - "name": "incentivesPool", - "type": "tuple" + "internalType": "address", + "name": "storageAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPoolAddress", + "type": "address" } ], - "name": "ParanetIncetivesPoolDeployed", + "name": "ParanetIncentivesPoolRedeployed", "type": "event" }, { "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -103,7 +125,7 @@ }, { "internalType": "uint256", - "name": "tracToNeuroEmissionMultiplier", + "name": "tracToTokenEmissionMultiplier", "type": "uint256" }, { @@ -115,16 +137,20 @@ "internalType": "uint16", "name": "paranetIncentivizationProposalVotersRewardPercentage", "type": "uint16" - } - ], - "name": "deployNeuroIncentivesPool", - "outputs": [ + }, + { + "internalType": "string", + "name": "incentivesPoolName", + "type": "string" + }, { "internalType": "address", - "name": "", + "name": "rewardTokenAddress", "type": "address" } ], + "name": "deployIncentivesPool", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -161,6 +187,19 @@ "stateMutability": "pure", "type": "function" }, + { + "inputs": [], + "name": "paranetIncentivesPoolFactoryHelper", + "outputs": [ + { + "internalType": "contract ParanetIncentivesPoolFactoryHelper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "paranetsRegistry", @@ -174,6 +213,34 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "storageAddress", + "type": "address" + } + ], + "name": "redeployIncentivesPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json b/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json index f78c7e5..5aa6397 100644 --- a/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json +++ b/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json @@ -26,29 +26,6 @@ "name": "ZeroAddressHub", "type": "error" }, - { - "inputs": [ - { - "internalType": "address", - "name": "miner", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "addedCumulativeAwardedNeuro", - "type": "uint256" - } - ], - "name": "addCumulativeAwardedNeuro", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -86,11 +63,11 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "addSubmittedKnowledgeAsset", + "name": "addSubmittedKnowledgeCollection", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -150,17 +127,17 @@ }, { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionId", "type": "uint256" }, { "internalType": "bytes32", - "name": "assertionId", + "name": "merkleRoot", "type": "bytes32" }, { @@ -169,7 +146,7 @@ "type": "uint96" } ], - "name": "addUpdatingKnowledgeAssetState", + "name": "addUpdatingKnowledgeCollectionState", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -188,7 +165,7 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetStateId", + "name": "knowledgeCollectionStateId", "type": "bytes32" }, { @@ -197,7 +174,7 @@ "type": "uint96" } ], - "name": "addUpdatingKnowledgeAssetUpdateTokenAmount", + "name": "addUpdatingKnowledgeCollectionUpdateTokenAmount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -208,9 +185,19 @@ "internalType": "address", "name": "miner", "type": "address" + }, + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "addedcumulativeAwardedToken", + "type": "uint256" } ], - "name": "decrementTotalSubmittedKnowledgeAssetsCount", + "name": "addcumulativeAwardedToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -223,7 +210,7 @@ "type": "address" } ], - "name": "deleteKnowledgeMiner", + "name": "decrementTotalSubmittedKnowledgeCollectionsCount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -234,22 +221,11 @@ "internalType": "address", "name": "miner", "type": "address" - }, - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" } ], - "name": "getCumulativeAwardedNeuro", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", + "name": "deleteKnowledgeMiner", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { @@ -300,7 +276,7 @@ }, { "internalType": "uint256", - "name": "totalSubmittedKnowledgeAssetsCount", + "name": "totalSubmittedKnowledgeCollectionsCount", "type": "uint256" } ], @@ -325,7 +301,7 @@ "type": "bytes32" } ], - "name": "getSubmittedKnowledgeAssets", + "name": "getSubmittedKnowledgeCollections", "outputs": [ { "internalType": "bytes32[]", @@ -359,7 +335,7 @@ "type": "uint256" } ], - "name": "getSubmittedKnowledgeAssets", + "name": "getSubmittedKnowledgeCollections", "outputs": [ { "internalType": "bytes32[]", @@ -378,7 +354,7 @@ "type": "address" } ], - "name": "getTotalSubmittedKnowledgeAssetsCount", + "name": "getTotalSubmittedKnowledgeCollectionsCount", "outputs": [ { "internalType": "uint256", @@ -443,35 +419,25 @@ "internalType": "bytes32", "name": "paranetId", "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "start", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "end", - "type": "uint256" } ], - "name": "getUpdatingKnowledgeAssetStates", + "name": "getUpdatingKnowledgeCollectionStates", "outputs": [ { "components": [ { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionId", "type": "uint256" }, { "internalType": "bytes32", - "name": "assertionId", + "name": "merkleRoot", "type": "bytes32" }, { @@ -480,7 +446,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetLib.UpdatingKnowledgeAssetState[]", + "internalType": "struct ParanetLib.UpdatingKnowledgeCollectionState[]", "name": "", "type": "tuple[]" } @@ -499,25 +465,35 @@ "internalType": "bytes32", "name": "paranetId", "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" } ], - "name": "getUpdatingKnowledgeAssetStates", + "name": "getUpdatingKnowledgeCollectionStates", "outputs": [ { "components": [ { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionId", "type": "uint256" }, { "internalType": "bytes32", - "name": "assertionId", + "name": "merkleRoot", "type": "bytes32" }, { @@ -526,7 +502,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetLib.UpdatingKnowledgeAssetState[]", + "internalType": "struct ParanetLib.UpdatingKnowledgeCollectionState[]", "name": "", "type": "tuple[]" } @@ -534,6 +510,30 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getcumulativeAwardedToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "hub", @@ -555,7 +555,7 @@ "type": "address" } ], - "name": "incrementTotalSubmittedKnowledgeAssetsCount", + "name": "incrementTotalSubmittedKnowledgeCollectionsCount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -639,57 +639,11 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", - "type": "bytes32" - } - ], - "name": "removeSubmittedKnowledgeAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "miner", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "knowledgeAssetStateId", - "type": "bytes32" - } - ], - "name": "removeUpdatingKnowledgeAssetState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "miner", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "paranetId", + "name": "knowledgeCollectionId", "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "cumulativeAwardedNeuro", - "type": "uint256" } ], - "name": "setCumulativeAwardedNeuro", + "name": "removeSubmittedKnowledgeCollection", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -726,11 +680,11 @@ }, { "internalType": "uint256", - "name": "totalSubmittedKnowledgeAssetsCount", + "name": "totalSubmittedKnowledgeCollectionsCount", "type": "uint256" } ], - "name": "setTotalSubmittedKnowledgeAssetsCount", + "name": "setTotalSubmittedKnowledgeCollectionsCount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -790,7 +744,7 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetStateId", + "name": "knowledgeCollectionStateId", "type": "bytes32" }, { @@ -799,7 +753,7 @@ "type": "uint96" } ], - "name": "setUpdatingKnowledgeAssetUpdateTokenAmount", + "name": "setUpdatingKnowledgeCollectionUpdateTokenAmount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -818,11 +772,11 @@ }, { "internalType": "uint256", - "name": "subtractedCumulativeAwardedNeuro", + "name": "cumulativeAwardedToken", "type": "uint256" } ], - "name": "subCumulativeAwardedNeuro", + "name": "setcumulativeAwardedToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -905,7 +859,7 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetStateId", + "name": "knowledgeCollectionStateId", "type": "bytes32" }, { @@ -914,7 +868,30 @@ "type": "uint96" } ], - "name": "subUpdatingKnowledgeAssetUpdateTokenAmount", + "name": "subUpdatingKnowledgeCollectionUpdateTokenAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subtractedcumulativeAwardedToken", + "type": "uint256" + } + ], + "name": "subcumulativeAwardedToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" diff --git a/dkg/data/interfaces/ParanetsRegistry.json b/dkg/data/interfaces/ParanetsRegistry.json index 438a9fb..b3abdb9 100644 --- a/dkg/data/interfaces/ParanetsRegistry.json +++ b/dkg/data/interfaces/ParanetsRegistry.json @@ -10,55 +10,6 @@ "stateMutability": "nonpayable", "type": "constructor" }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "AddressAlreadyInSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "AddressDoesNotExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "name": "ContractAlreadyExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "name": "ContractDoesNotExist", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyName", - "type": "error" - }, { "inputs": [ { @@ -70,11 +21,6 @@ "name": "UnauthorizedAccess", "type": "error" }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, { "inputs": [], "name": "ZeroAddressHub", @@ -106,17 +52,22 @@ "type": "bytes32" }, { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" + "internalType": "string", + "name": "incentivesPoolName", + "type": "string" }, { - "internalType": "bytes", - "name": "nodeId", - "type": "bytes" + "internalType": "address", + "name": "storageAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" } ], - "name": "addCuratedNode", + "name": "addIncentivesPool", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -130,11 +81,11 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "addKnowledgeAsset", + "name": "addKnowledgeCollecton", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -203,6 +154,29 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes", + "name": "nodeId", + "type": "bytes" + } + ], + "name": "addPermissionedNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -253,11 +227,16 @@ }, { "internalType": "address", - "name": "addr", + "name": "storageAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", "type": "address" } ], - "internalType": "struct UnorderedNamedContractDynamicSet.Contract[]", + "internalType": "struct ParanetLib.IncentivesPool[]", "name": "", "type": "tuple[]" } @@ -266,50 +245,13 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - } - ], - "name": "getCumulativeKnowledgeValue", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - } - ], - "name": "getCuratedNodes", + "inputs": [], + "name": "getAllParanetIds", "outputs": [ { - "components": [ - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "bytes", - "name": "nodeId", - "type": "bytes" - } - ], - "internalType": "struct ParanetLib.Node[]", + "internalType": "bytes32[]", "name": "", - "type": "tuple[]" + "type": "bytes32[]" } ], "stateMutability": "view", @@ -323,12 +265,12 @@ "type": "bytes32" } ], - "name": "getCuratedNodesCount", + "name": "getCumulativeKnowledgeValue", "outputs": [ { - "internalType": "uint256", + "internalType": "uint96", "name": "", - "type": "uint256" + "type": "uint96" } ], "stateMutability": "view", @@ -362,16 +304,33 @@ }, { "internalType": "string", - "name": "incentivesPoolType", + "name": "poolName", "type": "string" } ], - "name": "getIncentivesPoolAddress", + "name": "getIncentivesPoolByPoolName", "outputs": [ { - "internalType": "address", + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "storageAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + } + ], + "internalType": "struct ParanetLib.IncentivesPool", "name": "", - "type": "address" + "type": "tuple" } ], "stateMutability": "view", @@ -383,14 +342,36 @@ "internalType": "bytes32", "name": "paranetId", "type": "bytes32" + }, + { + "internalType": "address", + "name": "storageAddr", + "type": "address" } ], - "name": "getKnowledgeAssets", + "name": "getIncentivesPoolByStorageAddress", "outputs": [ { - "internalType": "bytes32[]", + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "storageAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + } + ], + "internalType": "struct ParanetLib.IncentivesPool", "name": "", - "type": "bytes32[]" + "type": "tuple" } ], "stateMutability": "view", @@ -404,12 +385,12 @@ "type": "bytes32" } ], - "name": "getKnowledgeAssetsAccessPolicy", + "name": "getKnowledgeCollections", "outputs": [ { - "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", + "internalType": "bytes32[]", "name": "", - "type": "uint8" + "type": "bytes32[]" } ], "stateMutability": "view", @@ -423,7 +404,7 @@ "type": "bytes32" } ], - "name": "getKnowledgeAssetsCount", + "name": "getKnowledgeCollectionsCount", "outputs": [ { "internalType": "uint256", @@ -443,7 +424,7 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" }, { @@ -452,7 +433,7 @@ "type": "uint256" } ], - "name": "getKnowledgeAssetsStartingFromKnowledgeAssetId", + "name": "getKnowledgeCollectionsStartingFromKnowlCollectionId", "outputs": [ { "internalType": "bytes32[]", @@ -463,6 +444,25 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getKnowledgeCollectionsSubmissionPolicy", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -481,7 +481,7 @@ "type": "uint256" } ], - "name": "getKnowledgeAssetsWithPagination", + "name": "getKnowledgeCollectionsWithPagination", "outputs": [ { "internalType": "bytes32[]", @@ -754,7 +754,7 @@ "name": "getMinersAccessPolicy", "outputs": [ { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "", "type": "uint8" } @@ -913,7 +913,7 @@ "name": "getNodesAccessPolicy", "outputs": [ { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "", "type": "uint8" } @@ -921,6 +921,68 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getParanetIdAtIndex", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "getParanetIds", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getParanetIdsMapping", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -936,6 +998,11 @@ "name": "", "type": "address" }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, { "internalType": "uint256", "name": "", @@ -959,9 +1026,14 @@ "components": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "paranetKATokenId", @@ -978,18 +1050,18 @@ "type": "string" }, { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "minersAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", - "name": "knowledgeAssetsAccessPolicy", + "internalType": "uint8", + "name": "knowledgeCollectionsSubmissionPolicy", "type": "uint8" }, { @@ -1006,6 +1078,69 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getParanetsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getPermissionedNodes", + "outputs": [ + { + "components": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes", + "name": "nodeId", + "type": "bytes" + } + ], + "internalType": "struct ParanetLib.Node[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getPermissionedNodesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1052,12 +1187,12 @@ "type": "bytes32" }, { - "internalType": "address", - "name": "incentivesPoolAddress", - "type": "address" + "internalType": "string", + "name": "poolName", + "type": "string" } ], - "name": "hasIncentivesPoolByAddress", + "name": "hasIncentivesPoolByName", "outputs": [ { "internalType": "bool", @@ -1076,12 +1211,12 @@ "type": "bytes32" }, { - "internalType": "string", - "name": "incentivesPoolType", - "type": "string" + "internalType": "address", + "name": "storageAddr", + "type": "address" } ], - "name": "hasIncentivesPoolByType", + "name": "hasIncentivesPoolByStorageAddress", "outputs": [ { "internalType": "bool", @@ -1113,12 +1248,12 @@ "type": "bytes32" }, { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" } ], - "name": "isCuratedNode", + "name": "isKnowledgeCollectionRegistered", "outputs": [ { "internalType": "bool", @@ -1137,12 +1272,12 @@ "type": "bytes32" }, { - "internalType": "bytes32", - "name": "knowledgeAssetId", - "type": "bytes32" + "internalType": "address", + "name": "knowledgeMinerAddress", + "type": "address" } ], - "name": "isKnowledgeAssetRegistered", + "name": "isKnowledgeMinerRegistered", "outputs": [ { "internalType": "bool", @@ -1161,12 +1296,12 @@ "type": "bytes32" }, { - "internalType": "address", - "name": "knowledgeMinerAddress", - "type": "address" + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "isKnowledgeMinerRegistered", + "name": "isPermissionedNode", "outputs": [ { "internalType": "bool", @@ -1237,12 +1372,17 @@ "inputs": [ { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetTokenId", "type": "uint256" }, { @@ -1256,18 +1396,18 @@ "type": "string" }, { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "minersAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", - "name": "knowledgeAssetsAccessPolicy", + "internalType": "uint8", + "name": "knowledgeCollectionsSubmissionPolicy", "type": "uint8" } ], @@ -1282,60 +1422,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "removeCuratedNode", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "incentivesPoolAddress", - "type": "address" - } - ], - "name": "removeIncentivesPool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "incentivesPoolType", - "type": "string" - } - ], - "name": "removeIncentivesPool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1345,11 +1431,11 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "removeKnowledgeAsset", + "name": "removeKnowledgeCollection", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1426,12 +1512,12 @@ "type": "bytes32" }, { - "internalType": "bytes32", - "name": "serviceId", - "type": "bytes32" + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "removeService", + "name": "removePermissionedNode", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1444,12 +1530,12 @@ "type": "bytes32" }, { - "internalType": "uint96", - "name": "cumulativeKnowledgeValue", - "type": "uint96" + "internalType": "bytes32", + "name": "serviceId", + "type": "bytes32" } ], - "name": "setCumulativeKnowledgeValue", + "name": "removeService", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1462,12 +1548,12 @@ "type": "bytes32" }, { - "internalType": "string", - "name": "description", - "type": "string" + "internalType": "uint96", + "name": "cumulativeKnowledgeValue", + "type": "uint96" } ], - "name": "setDescription", + "name": "setCumulativeKnowledgeValue", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1481,16 +1567,11 @@ }, { "internalType": "string", - "name": "incentivesPoolType", + "name": "description", "type": "string" - }, - { - "internalType": "address", - "name": "incentivesPoolAddress", - "type": "address" } ], - "name": "setIncentivesPoolAddress", + "name": "setDescription", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1503,12 +1584,12 @@ "type": "bytes32" }, { - "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", - "name": "knowledgeAssetsAccessPolicy", + "internalType": "uint8", + "name": "knowledgeCollectionsSubmissionPolicy", "type": "uint8" } ], - "name": "setKnowledgeAssetsAccessPolicy", + "name": "setKnowledgeCollectionsSubmissionPolicy", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1521,7 +1602,7 @@ "type": "bytes32" }, { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "minersAccessPolicy", "type": "uint8" } @@ -1557,7 +1638,7 @@ "type": "bytes32" }, { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "nodesAccessPolicy", "type": "uint8" } @@ -1585,29 +1666,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "incentivesPoolType", - "type": "string" - }, - { - "internalType": "address", - "name": "incentivesPoolAddress", - "type": "address" - } - ], - "name": "updateIncentivesPoolAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { From 6e15c99a08a0fe1ebb59eb800dad4ed57f43baf3 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 7 Jul 2025 15:50:00 +0200 Subject: [PATCH 142/146] version bump to 8.1.0rc1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9c87c5b..08e3740 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.1.0" +version = "8.1.0rc1" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From 12648bc2220aea59889a4c7b911f5e4051c5116b Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Mon, 7 Jul 2025 15:55:36 +0200 Subject: [PATCH 143/146] version bump to 8.1.1rc1* --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 08e3740..45b1f31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.1.0rc1" +version = "8.1.1rc1" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0" From 288bf0a4137f60d7042915e30d94b3e1061046bc Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 8 Jul 2025 12:04:15 +0200 Subject: [PATCH 144/146] fixed metadata not being fetched --- dkg/modules/asset/asset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dkg/modules/asset/asset.py b/dkg/modules/asset/asset.py index 16558ff..edc2085 100644 --- a/dkg/modules/asset/asset.py +++ b/dkg/modules/asset/asset.py @@ -595,7 +595,7 @@ def get(self, ual: UAL, options: dict = {}) -> dict: ), }, } - metadata = get_public_operation_result.get("data") + metadata = get_public_operation_result.get("data", {}).get("metadata", None) assertion = get_public_operation_result.get("data", {}).get("assertion", None) if not assertion: From ee17c982b9a388d8e160de84fcca3a6739a9f6b9 Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Tue, 8 Jul 2025 12:05:18 +0200 Subject: [PATCH 145/146] fixed async metadata not being fetched --- dkg/modules/asset/async_asset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dkg/modules/asset/async_asset.py b/dkg/modules/asset/async_asset.py index 655c434..547bb4a 100644 --- a/dkg/modules/asset/async_asset.py +++ b/dkg/modules/asset/async_asset.py @@ -607,7 +607,7 @@ async def get(self, ual: UAL, options: dict = None) -> dict: ), }, } - metadata = get_public_operation_result.get("data") + metadata = get_public_operation_result.get("data", {}).get("metadata", None) assertion = get_public_operation_result.get("data", {}).get("assertion", None) if not assertion: From 1d187edfdb304cafcbffb50329c87728e25d491e Mon Sep 17 00:00:00 2001 From: Marko Kostic Date: Thu, 10 Jul 2025 10:09:29 +0200 Subject: [PATCH 146/146] version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 45b1f31..8f3779c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dkg" -version = "8.1.1rc1" +version = "8.1.1rc2" description = "Python library for interacting with the OriginTrail Decentralized Knowledge Graph" authors = ["Uladzislau Hubar , Zvonimir Sculac "] license = "Apache-2.0"