diff --git a/dkg/asset.py b/dkg/asset.py index c2ddc87..9ceed03 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -360,6 +360,256 @@ 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) 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()