def test_ddo_address_utilities(): sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample_with_credentials.json") assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path) ddo = V3Asset(json_filename=sample_ddo_path) assert ddo.allowed_addresses == ["0x123", "0x456a"] ddo.add_address_to_allow_list("0xAbc12") assert ddo.allowed_addresses == ["0x123", "0x456a", "0xabc12"] ddo.remove_address_from_allow_list("0xAbc12") assert ddo.allowed_addresses == ["0x123", "0x456a"] ddo.remove_address_from_allow_list("0x123") assert ddo.allowed_addresses == ["0x456a"] ddo.remove_address_from_allow_list("0x456a") assert ddo.allowed_addresses == [] assert ddo.denied_addresses == ["0x2222", "0x333"] # does not exist ddo.remove_address_from_deny_list("0xasfaweg") assert ddo.denied_addresses == ["0x2222", "0x333"] ddo.add_address_to_deny_list("0xasfaweg") assert ddo.denied_addresses == ["0x2222", "0x333", "0xasfaweg"] ddo = V3Asset() assert ddo.allowed_addresses == [] ddo.add_address_to_allow_list("0xAbc12") assert ddo.allowed_addresses == ["0xabc12"] # double adding ddo.add_address_to_allow_list("0xAbc12") assert ddo.allowed_addresses == ["0xabc12"]
def test_pay_for_service_insufficient_balance(publisher_ocean_instance): """Tests if balance is lower than the purchased amount.""" ocn = publisher_ocean_instance alice = get_publisher_wallet() sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json") asset = V3Asset(json_filename=sample_ddo_path) asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4()) token = ocn.create_data_token("DataToken1", "DT1", from_wallet=alice, blob="foo_blob") with pytest.raises(InsufficientBalance): ocn.assets.pay_for_service( ocn.web3, 10000000000000, token.address, asset.did, 0, ZERO_ADDRESS, alice, alice.address, )
def resolve_asset( did: str, metadata_cache_uri: Optional[str] = None, web3: Optional[Web3] = None, token_address: Optional[str] = None, ) -> V3Asset: """Resolve a DID to an URL/DDO or later an internal/external DID. :param did: the asset id to resolve, this is part of the ocean DID did:op:<32 byte value> :param metadata_cache_uri: str the url of the metadata store :param web3: Web3 instance :param token_address: str the address of the DataToken smart contract :return Asset: the resolved DID """ assert metadata_cache_uri or ( web3 and token_address ), "Either metadata_cache_uri or (web3 and token_address) is required." if not metadata_cache_uri: metadata_cache_uri = DataToken(web3, token_address).get_metadata_url() logger.debug(f"found did {did} -> url={metadata_cache_uri}") ddo = AquariusProvider.get_aquarius(metadata_cache_uri).get_asset_ddo(did) if ddo: return V3Asset(dictionary=ddo.as_dictionary())
def test_ddo_connection(config): ddo = V3Asset("did:op:testdid") provider_uri = config.provider_url assert ( ddo.is_consumable(with_connectivity_check=True, provider_uri=provider_uri) == ConsumableCodes.CONNECTIVITY_FAIL )
def create_asset(ocean, publisher, encrypt=False): """Helper function for asset creation based on ddo_sa_sample.json.""" sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json") assert sample_ddo_path.exists(), "{} does not exist!".format( sample_ddo_path) asset = V3Asset(json_filename=sample_ddo_path) asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4()) return ocean.assets.create(asset.metadata, publisher, [], encrypt=encrypt)
def test_create_asset_with_owner_address(publisher_ocean_instance): """Tests that an asset can be created with owner address.""" ocn = publisher_ocean_instance alice = get_publisher_wallet() sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json") asset = V3Asset(json_filename=sample_ddo_path) asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4()) assert ocn.assets.create( asset.metadata, alice, [], owner_address=alice.address ), "Asset creation failed with the specified owner address."
def test_create_asset_without_dt_address(publisher_ocean_instance): """Tests creation of the asset which has not the data token address.""" ocn = publisher_ocean_instance alice = get_publisher_wallet() sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json") asset = V3Asset(json_filename=sample_ddo_path) asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4()) assert ocn.assets.create( asset.metadata, alice, [], data_token_address=None ), "Asset creation failed with the specified datatoken address."
def test_ddo_unlisting(): sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json") assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path) ddo = V3Asset(json_filename=sample_ddo_path) assert ddo.is_listed ddo.unlist() assert not ddo.is_listed ddo.list() assert ddo.is_listed
def test_ddo_retiring(): sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json") assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path) ddo = V3Asset(json_filename=sample_ddo_path) assert not ddo.is_retired ddo.retire() assert ddo.is_retired assert ddo.is_consumable() == ConsumableCodes.ASSET_DISABLED ddo.unretire() assert not ddo.is_retired
def get_asset_ddo(self, did: str) -> Optional[V3Asset]: """ Retrieve asset ddo for a given did. :param did: Asset DID string :return: V3Asset instance """ response = self.requests_session.get(f"{self.base_url}/ddo/{did}") if response.status_code == 200: return V3Asset(dictionary=response.json()) return None
def test_ddo_credentials_disabled(): sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample_disabled.json") assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path) ddo = V3Asset(json_filename=sample_ddo_path) assert ddo.is_disabled assert not ddo.is_enabled ddo.enable() assert not ddo.is_disabled assert ddo.is_enabled ddo.disable() assert ddo.is_consumable() == ConsumableCodes.ASSET_DISABLED
def query(self, query: dict, metadata_cache_uri: Optional[str] = None) -> list: """ Search an asset in oceanDB using search query. :param query: dict with query parameters (e.g.) https://github.com/oceanprotocol/aquarius/blob/develop/docs/for_api_users/API.md :param metadata_cache_uri: Url of the aquarius where you want to search. If there is not provided take the default :return: List of assets that match with the query. """ logger.info(f"Searching asset query: {query}") aquarius = self._get_aquarius(metadata_cache_uri) return [ V3Asset(dictionary=ddo_dict) for ddo_dict in aquarius.query_search(query) ]
def search(self, text: str, metadata_cache_uri: Optional[str] = None) -> list: """ Search an asset in oceanDB using aquarius. :param text: String with the value that you are searching :param metadata_cache_uri: Url of the aquarius where you want to search. If there is not provided take the default :return: List of assets that match with the query """ logger.info(f"Searching asset containing: {text}") return [ V3Asset(dictionary=ddo_dict) for ddo_dict in self._get_aquarius(metadata_cache_uri).query_search( {"query": {"query_string": {"query": text}}} ) ]
def get_ddo_sample(datatoken_address): """Helper function to get a sample ddo for testing.""" did = f"did:op:{remove_0x_prefix(datatoken_address)}" sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json") assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path) asset = V3Asset(json_filename=sample_ddo_path) asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4()) checksum_dict = dict() for service in asset.services: checksum_dict[str(service.index)] = checksum(service.main) asset.add_proof(checksum_dict, get_publisher_wallet()) asset.did = did return asset
def test_ddo_credentials_addresses_both(): """Tests DDO credentials when both deny and allow lists exist on the asset.""" sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample_with_credentials.json") assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path) ddo = V3Asset(json_filename=sample_ddo_path) address_credential = AddressCredential(ddo) assert address_credential.get_addresses_of_class("allow") == ["0x123", "0x456a"] assert address_credential.get_addresses_of_class("deny") == ["0x2222", "0x333"] assert ( address_credential.validate_access({"type": "address", "value": "0x111"}) == ConsumableCodes.CREDENTIAL_NOT_IN_ALLOW_LIST ) assert ( address_credential.validate_access({"type": "address", "value": "0x456A"}) == ConsumableCodes.OK )
def test_create_asset_with_address(publisher_ocean_instance): """Tests that an asset can be created with specific DT address.""" ocn = publisher_ocean_instance alice = get_publisher_wallet() sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json") asset = V3Asset(json_filename=sample_ddo_path) asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4()) token = ocn.create_data_token("DataToken1", "DT1", from_wallet=alice, blob="foo_blob") assert ocn.assets.create( asset.metadata, alice, [], data_token_address=token.address ), "Asset creation failed with the specified datatoken address."
def test_ddo_dict(): """Tests DDO creation from dictionary.""" sample_ddo_path = get_resource_path("ddo", "ddo_sample_algorithm.json") assert sample_ddo_path.exists(), f"{sample_ddo_path} does not exist!" ddo1 = V3Asset(json_filename=sample_ddo_path) assert ddo1.did == "did:op:8d1b4d73e7af4634958f071ab8dfe7ab0df14019" ddo1.add_proof({"checksum": "test"}, get_publisher_wallet()) ddo_dict = ddo1.as_dictionary() assert ddo_dict["publicKey"][0]["id"] == ddo1.did assert ddo_dict["publicKey"][0]["owner"] == get_publisher_wallet().address assert ddo_dict["publicKey"][0]["type"] == "EthereumECDSAKey" assert ddo_dict["authentication"][0] == { "type": "RsaSignatureAuthentication2018", "publicKey": ddo1.did, }
def test_creating_asset_from_scratch(): """Tests creating an Asset from scratch.""" # create an empty ddo ddo = V3Asset() assert ddo.did is None assert ddo.asset_id is None assert ddo.created is not None, "DDO has not been created." did = DID.did({"0": "0x99999999999999999"}) ddo.did = did assert ddo.did == did ddo.add_service(TEST_SERVICE_TYPE, TEST_SERVICE_URL) pub_acc = get_publisher_wallet() ddo.add_proof({"checksum": "test"}, pub_acc) ddo_text_proof = ddo.as_text() assert ddo_text_proof
def test_ddo_credentials_addresses_no_access_list(): """Tests DDO credentials when neither deny, nor allow lists exist on the asset.""" sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample_with_credentials.json") assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path) # if "allow" OR "deny" exist, we need a credential, # so remove both to test the behaviour of no credential supplied ddo = V3Asset(json_filename=sample_ddo_path) address_credential = AddressCredential(ddo) ddo.credentials.pop("allow") ddo.credentials.pop("deny") assert address_credential.validate_access() == ConsumableCodes.OK # test that we can use another credential if address is not required assert ( ddo.is_consumable( {"type": "somethingelse", "value": "test"}, with_connectivity_check=False ) == ConsumableCodes.OK )
def test_verify_order_tx(alice_address, bob_address, alice_ocean, alice_wallet): """Tests verify_order_tx function.""" token = alice_ocean.create_data_token("DataToken1", "DT1", from_wallet=alice_wallet, blob="foo_blob") token.mint(alice_address, to_wei(100), from_wallet=alice_wallet) token.approve(bob_address, to_wei(1), from_wallet=alice_wallet) transfer_tx_id = token.transfer(bob_address, to_wei(5), from_wallet=alice_wallet) with pytest.raises(TimeExhausted): with patch("ocean_lib.models.data_token.DataToken.get_tx_receipt" ) as mock: # dummy tx id which is not found in the chain # catches TimeExhausted exception from web3 mock.side_effect = TimeExhausted() token.verify_order_tx("0x0", "some_did", "some_index", "some_amount", alice_address) transfer_tx_id = token.transfer(bob_address, to_wei(5), from_wallet=alice_wallet) with pytest.raises(AssertionError): # tx id is from transfer, not order token.verify_order_tx(transfer_tx_id, "some_did", "some_index", "some_amount", alice_address) sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json") asset = V3Asset(json_filename=sample_ddo_path) order_tx_id = token.startOrder(alice_address, to_wei(1), 1, ZERO_ADDRESS, alice_wallet) with pytest.raises(AssertionError): # the wrong asset did, this is a sample token.verify_order_tx(order_tx_id, asset.did, "some_index", "some_amount", alice_address)
def test_InsufficientBalance(publisher_ocean_instance): alice = get_publisher_wallet() sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json") asset = V3Asset(json_filename=sample_ddo_path) asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4()) token = publisher_ocean_instance.create_data_token("DataToken1", "DT1", from_wallet=alice, blob="foo_blob") with pytest.raises(InsufficientBalance): publisher_ocean_instance.assets.pay_for_service( publisher_ocean_instance.web3, to_wei("12345678999999.9"), token.address, asset.did, 0, ZERO_ADDRESS, alice, alice.address, )
def test_ddo_credentials_addresses_only_deny(): """Tests DDO credentials when only the deny list exists on the asset.""" sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample_with_credentials.json") assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path) # remove allow to test the behaviour of deny ddo = V3Asset(json_filename=sample_ddo_path) ddo.credentials.pop("allow") address_credential = AddressCredential(ddo) assert address_credential.get_addresses_of_class("allow") == [] assert address_credential.get_addresses_of_class("deny") == ["0x2222", "0x333"] assert ( address_credential.validate_access({"type": "address", "value": "0x111"}) == ConsumableCodes.OK ) assert ( address_credential.validate_access({"type": "address", "value": "0x333"}) == ConsumableCodes.CREDENTIAL_IN_DENY_LIST ) credential = {"type": "address", "value": ""} with pytest.raises(MalformedCredential): address_credential.validate_access(credential)
def create( self, metadata: dict, publisher_wallet: Wallet, services: Optional[list] = None, owner_address: Optional[str] = None, data_token_address: Optional[str] = None, provider_uri: Optional[str] = None, dt_name: Optional[str] = None, dt_symbol: Optional[str] = None, dt_blob: Optional[str] = None, dt_cap: Optional[int] = None, encrypt: Optional[bool] = False, ) -> Optional[V3Asset]: """Register an asset on-chain. Creating/deploying a DataToken contract and in the Metadata store (Aquarius). :param metadata: dict conforming to the Metadata accepted by Ocean Protocol. :param publisher_wallet: Wallet of the publisher registering this asset :param services: list of Service objects. :param owner_address: hex str the ethereum address to assign asset ownership to. After registering the asset on-chain, the ownership is transferred to this address :param data_token_address: hex str the address of the data token smart contract. The new asset will be associated with this data token address. :param provider_uri: str URL of service provider. This will be used as base to construct the serviceEndpoint for the `access` (download) service :param dt_name: str name of DataToken if creating a new one :param dt_symbol: str symbol of DataToken if creating a new one :param dt_blob: str blob of DataToken if creating a new one. A `blob` is any text to be stored with the ERC20 DataToken contract for any purpose. :param dt_cap: int amount of DataTokens to mint, denoted in wei :return: DDO instance """ assert isinstance( metadata, dict ), f"Expected metadata of type dict, got {type(metadata)}" # copy metadata so we don't change the original metadata_copy = copy.deepcopy(metadata) asset_type = metadata_copy["main"]["type"] assert asset_type in ( "dataset", "algorithm", ), f"Invalid/unsupported asset type {asset_type}" validation_result, validation_errors = self.validate(metadata) if not validation_result: msg = f"Metadata has validation errors: {validation_errors}" logger.error(msg) raise ValueError(msg) urls = [item["url"] for item in metadata["main"]["files"]] if not provider_uri: provider_uri = DataServiceProvider.get_url(self._config) for url in urls: if not DataServiceProvider.check_single_file_info(url, provider_uri): msg = f"The URL of this service can not be accessed: {url}." logger.error(msg) raise ValueError(msg) services = services or [] services = self._add_defaults( services, metadata_copy, provider_uri, publisher_wallet ) checksum_dict = dict() for service in services: checksum_dict[str(service.index)] = checksum(service.main) # Create a DDO object asset = V3Asset() # Adding proof to the ddo. asset.add_proof(checksum_dict, publisher_wallet) ################# # DataToken address = DTFactory.configured_address( get_network_name(web3=self._web3), self._config.address_file ) dtfactory = DTFactory(self._web3, address) if not data_token_address: blob = dt_blob or "" name = dt_name or metadata["main"]["name"] symbol = dt_symbol or name # register on-chain _cap = dt_cap if dt_cap else DataToken.DEFAULT_CAP tx_id = dtfactory.createToken( blob, name, symbol, _cap, from_wallet=publisher_wallet ) data_token = DataToken(self._web3, dtfactory.get_token_address(tx_id)) if not data_token: logger.warning("Creating new data token failed.") return None data_token_address = data_token.address logger.info( f"Successfully created data token with address " f"{data_token.address} for new dataset asset." ) # owner_address is set as minter only if creating new data token. So if # `data_token_address` is set `owner_address` has no effect. if owner_address: data_token.proposeMinter(owner_address, from_wallet=publisher_wallet) else: if not dtfactory.verify_data_token(data_token_address): raise ContractNotFound( f"datatoken address {data_token_address} is not found in the DTFactory events." ) # verify data_token_address dt = DataToken(self._web3, data_token_address) minter = dt.contract.caller.minter() if not minter: raise AssertionError( f"datatoken address {data_token_address} does not seem to be a valid DataToken contract." ) elif minter.lower() != publisher_wallet.address.lower(): raise AssertionError( f"Minter of datatoken {data_token_address} is not the same as the publisher." ) assert ( data_token_address ), "data_token_address is required for publishing a dataset asset." # Generating the did and adding to the ddo. did = f"did:op:{remove_0x_prefix(data_token_address)}" asset.did = did logger.debug(f"Using datatoken address as did: {did}") # Check if it's already registered first! if self._get_aquarius().ddo_exists(did): raise AquariusError( f"Asset id {did} is already registered to another asset." ) for service in services: if service.type == ServiceTypes.METADATA: ddo_service_endpoint = service.service_endpoint if "{did}" in ddo_service_endpoint: ddo_service_endpoint = ddo_service_endpoint.replace("{did}", did) service.service_endpoint = ddo_service_endpoint asset.add_service(service) asset.proof["signatureValue"] = sign_hash( encode_defunct(text=asset.asset_id), publisher_wallet ) # Setup metadata service # First compute files_encrypted assert metadata_copy["main"][ "files" ], "files is required in the metadata main attributes." logger.debug("Encrypting content urls in the metadata.") publisher_signature = self._data_provider.sign_message( publisher_wallet, asset.asset_id, provider_uri=provider_uri ) _, encrypt_endpoint = self._data_provider.build_encrypt_endpoint(provider_uri) files_encrypted = self._data_provider.encrypt_files_dict( metadata_copy["main"]["files"], encrypt_endpoint, asset.asset_id, publisher_wallet.address, publisher_signature, ) # only assign if the encryption worked if files_encrypted: logger.debug(f"Content urls encrypted successfully {files_encrypted}") index = 0 for file in metadata_copy["main"]["files"]: file["index"] = index index = index + 1 del file["url"] metadata_copy["encryptedFiles"] = files_encrypted else: raise AssertionError("Encrypting the files failed.") logger.debug( f"Generated asset and services, DID is {asset.did}," f" metadata service @{ddo_service_endpoint}." ) # Set datatoken address in the asset asset.data_token_address = data_token_address flags, asset_contents = self._build_asset_contents(asset, encrypt) try: # publish the new ddo in ocean-db/Aquarius ddo_registry = self.ddo_registry() tx_id = ddo_registry.create( asset.asset_id, flags, asset_contents, publisher_wallet ) if not ddo_registry.verify_tx(tx_id): raise VerifyTxFailed( f"create DDO on-chain failed, transaction status is 0. Transaction hash is {tx_id}" ) logger.info("Asset/ddo published on-chain successfully.") except ValueError as ve: raise ValueError(f"Invalid value to publish in the metadata: {str(ve)}") except Exception as e: logger.error(f"Publish asset on-chain failed: {str(e)}") raise return asset
def test_ddo_on_chain(config, web3): """Tests chain operations on a DDO.""" ddo_address = get_contracts_addresses(config.address_file, "ganache")[ MetadataContract.CONTRACT_NAME ] dtfactory_address = get_contracts_addresses(config.address_file, "ganache")[ DTFactory.CONTRACT_NAME ] ddo_registry = MetadataContract(web3, ddo_address) wallet = get_publisher_wallet() dtfactory = DTFactory(web3, dtfactory_address) tx_id = dtfactory.createToken("", "dt1", "dt1", 1000, wallet) dt = DataToken(web3, dtfactory.get_token_address(tx_id)) # test create ddo asset = get_ddo_sample(dt.address) old_name = asset.metadata["main"]["name"] txid = ddo_registry.create( asset.asset_id, b"", lzma.compress(Web3.toBytes(text=asset.as_text())), wallet ) assert ddo_registry.verify_tx(txid), f"create ddo failed: txid={txid}" logs = ddo_registry.event_MetadataCreated.processReceipt( ddo_registry.get_tx_receipt(web3, txid), errors=DISCARD ) assert logs, f"no logs found for create ddo tx {txid}" log = logs[0] assert add_0x_prefix(log.args.dataToken) == asset.asset_id # read back the asset ddo from the event log ddo_text = Web3.toText(lzma.decompress(log.args.data)) assert ddo_text == asset.as_text(), "ddo text does not match original." _asset = V3Asset(json_text=ddo_text) assert _asset.did == asset.did, "did does not match." name = _asset.metadata["main"]["name"] assert name == old_name, f"name does not match: {name} != {old_name}" # test_update ddo asset.metadata["main"]["name"] = "updated name for test" txid = ddo_registry.update( asset.asset_id, b"", lzma.compress(Web3.toBytes(text=asset.as_text())), wallet ) assert ddo_registry.verify_tx(txid), f"update ddo failed: txid={txid}" logs = ddo_registry.event_MetadataUpdated.processReceipt( ddo_registry.get_tx_receipt(web3, txid), errors=DISCARD ) assert logs, f"no logs found for update ddo tx {txid}" log = logs[0] assert add_0x_prefix(log.args.dataToken) == asset.asset_id # read back the asset ddo from the event log ddo_text = Web3.toText(lzma.decompress(log.args.data)) assert ddo_text == asset.as_text(), "ddo text does not match original." _asset = V3Asset(json_text=ddo_text) assert ( _asset.metadata["main"]["name"] == "updated name for test" ), "name does not seem to be updated." assert DataToken(web3, asset.asset_id).contract.caller.isMinter(wallet.address) # test update fails from wallet other than the original publisher bob = get_consumer_wallet() try: txid = ddo_registry.update( asset.asset_id, b"", lzma.compress(Web3.toBytes(text=asset.as_text())), bob ) assert ddo_registry.verify_tx(txid) is False, f"update ddo failed: txid={txid}" logs = ddo_registry.event_MetadataUpdated.processReceipt( ddo_registry.get_tx_receipt(web3, txid), errors=DISCARD ) assert ( not logs ), f"should be no logs for MetadataUpdated, but seems there are some logs: tx {txid}, logs {logs}" except ValueError: print("as expected, only owner can update a published ddo.") # test ddoOwner assert DataToken(web3, asset.asset_id).contract.caller.isMinter(wallet.address), ( f"ddo owner does not match the expected publisher address {wallet.address}, " f"owner is {DataToken(web3, asset.asset_id).contract.caller.minter(wallet.address)}" )
def download_asset_files( service_index: int, asset: V3Asset, consumer_wallet: Wallet, destination: str, token_address: str, order_tx_id: str, data_provider: Type[DataServiceProvider], index: Optional[int] = None, userdata: Optional[dict] = None, ) -> str: """Download asset data files or result files from a compute job. :param service_index: identifier of the service inside the asset DDO, str :param asset: V3Asset instance :param consumer_wallet: Wallet instance of the consumer :param destination: Path, str :param token_address: hex str the address of the DataToken smart contract :param order_tx_id: hex str the transaction hash of the startOrder tx :param data_provider: DataServiceProvider class object :param index: Index of the document that is going to be downloaded, int :return: asset folder path, str """ _files = asset.metadata["main"]["files"] sa = asset.get_service(ServiceTypes.ASSET_ACCESS) service_endpoint = sa.service_endpoint if not service_endpoint: logger.error( 'Consume asset failed, service definition is missing the "serviceEndpoint".' ) raise AssertionError( 'Consume asset failed, service definition is missing the "serviceEndpoint".' ) _, service_endpoint = data_provider.build_download_endpoint(service_endpoint) if not os.path.isabs(destination): destination = os.path.abspath(destination) if not os.path.exists(destination): os.mkdir(destination) asset_folder = os.path.join( destination, f"datafile.{asset.asset_id}.{service_index}" ) if not os.path.exists(asset_folder): os.mkdir(asset_folder) if index is not None: assert isinstance(index, int), logger.error("index has to be an integer.") assert index >= 0, logger.error("index has to be 0 or a positive integer.") assert index < len(_files), logger.error( "index can not be bigger than the number of files" ) indexes = [index] else: indexes = range(len(_files)) for i in indexes: data_provider.download_service( asset.did, service_endpoint, consumer_wallet, _files, asset_folder, service_index, token_address, order_tx_id, i, userdata, ) return asset_folder
def get_algorithm_meta(): algorithm_ddo_path = get_resource_path("ddo", "ddo_algorithm.json") algo_main = V3Asset(json_filename=algorithm_ddo_path).metadata["main"] algo_meta_dict = algo_main["algorithm"].copy() algo_meta_dict["url"] = algo_main["files"][0]["url"] return AlgorithmMetadata(algo_meta_dict)
def get_sample_algorithm_ddo() -> V3Asset: return V3Asset(json_filename=get_resource_path("ddo", "ddo_algorithm.json"))
def get_sample_ddo_with_compute_service() -> V3Asset: return V3Asset( json_filename=get_resource_path("ddo", "ddo_with_compute_service.json") )
def get_sample_ddo(file_name="ddo_sa_sample.json") -> V3Asset: return V3Asset(json_filename=get_resource_path("ddo", file_name))
def _build_asset_contents(self, asset: V3Asset, encrypt: bool = False): if not encrypt: return bytes([1]), lzma.compress(Web3.toBytes(text=asset.as_text())) return bytes([2]), self._get_aquarius().encrypt(asset.as_text())