def setup_all(): config = ExampleConfig.get_config() ConfigProvider.set_config(config) Web3Provider.init_web3( provider=get_web3_connection_provider(config.network_url)) ContractHandler.set_artifacts_path(config.artifacts_path) network = Web3Helper.get_network_name() wallet = get_ganache_wallet() if network in ["ganache", "development"] and wallet: print( f"sender: {wallet.key}, {wallet.address}, {wallet.password}, {wallet.keysStr()}" ) print( f"sender balance: {Web3Helper.from_wei(Web3Helper.get_ether_balance(wallet.address))}" ) assert Web3Helper.from_wei(Web3Helper.get_ether_balance( wallet.address)) > 10 from ocean_lib.models.data_token import DataToken OCEAN_token = DataToken(get_ocean_token_address(network)) amt_distribute = 1000 amt_distribute_base = to_base_18(float(amt_distribute)) for w in (get_publisher_wallet(), get_consumer_wallet()): if Web3Helper.from_wei(Web3Helper.get_ether_balance( w.address)) < 2: Web3Helper.send_ether(wallet, w.address, 4) if OCEAN_token.token_balance(w.address) < 100: OCEAN_token.transfer(w.address, amt_distribute_base, from_wallet=wallet)
def get_network_name(): try: network_name = os.getenv('NETWORK_NAME') if not network_name: network_name = Web3Helper.get_network_name().lower() except Exception: network = os.getenv('EVENTS_RPC') if network.startswith('wss://'): network_name = network[len('wss://'):].split('.')[0] elif not network.startswith('http'): network_name = network else: network_name = os.getenv('NETWORK_NAME') if not network_name: raise AssertionError(f'Cannot figure out the network name.') return network_name
def __init__(self, config=None, data_provider=None): """Initialize Ocean class. >> # Make a new Ocean instance >> ocean = Ocean({...}) This class provides the main top-level functions in ocean protocol: * Publish assets metadata and associated services * Each asset is assigned a unique DID and a DID Document (DDO) * The DDO contains the asset's services including the metadata * The DID is registered on-chain with a URL of the metadata store to retrieve the DDO from >> asset = ocean.assets.create(metadata, publisher_wallet) * Discover/Search assets via the current configured metadata store (Aquarius) >> assets_list = ocean.assets.search('search text') An instance of Ocean is parameterized by a `Config` instance. :param config: Config instance :param data_provider: DataServiceProvider instance """ # Configuration information for the market is stored in the Config class # config = Config(filename=config_file, options_dict=config_dict) if not config: try: config = ConfigProvider.get_config() except AssertionError: config = Config(os.getenv(ENV_CONFIG_FILE)) ConfigProvider.set_config(config) if isinstance(config, dict): # fallback to metadataStoreUri cache_key = ("metadataCacheUri" if ("metadataCacheUri" in config) else "metadataStoreUri") aqua_url = config.get( cache_key, config.get("aquarius.url", "http://localhost:5000")) config_dict = { "eth-network": { "network": config.get("network", "") }, "resources": { "aquarius.url": aqua_url, "provider.url": config.get("providerUri", "http://localhost:8030"), }, } config = Config(options_dict=config_dict) ConfigProvider.set_config(config) self._config = config ContractHandler.set_artifacts_path(self._config.artifacts_path) Web3Provider.init_web3( provider=get_web3_connection_provider(self._config.network_url)) self._web3 = Web3Provider.get_web3() if not data_provider: data_provider = DataServiceProvider network = Web3Helper.get_network_name() addresses = get_contracts_addresses(network, self._config) self.assets = OceanAssets( self._config, data_provider, addresses.get(MetadataContract.CONTRACT_NAME)) self.services = OceanServices() self.auth = OceanAuth(self._config.storage_path) self.compute = OceanCompute(self.auth, self._config, data_provider) ocean_address = get_ocean_token_address(network) self.pool = OceanPool(ocean_address, get_bfactory_address(network)) self.exchange = OceanExchange( ocean_address, FixedRateExchange.configured_address( network or Web3Helper.get_network_name(), ConfigProvider.get_config().address_file, ), self.config, ) logger.debug("Ocean instance initialized: ")
def get_dtfactory(self, dtfactory_address: str = "") -> DTFactory: dtf_address = dtfactory_address or DTFactory.configured_address( Web3Helper.get_network_name(), self._config.address_file) return DTFactory(dtf_address)
def OCEAN_address(self): return get_ocean_token_address(Web3Helper.get_network_name())
def create( self, metadata: dict, publisher_wallet: Wallet, service_descriptors: list = None, owner_address: str = None, data_token_address: str = None, provider_uri=None, dt_name: str = None, dt_symbol: str = None, dt_blob: str = None, dt_cap: float = None, ) -> (Asset, None): """ Register an asset on-chain by 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 service_descriptors: list of ServiceDescriptor tuples of length 2. The first item must be one of ServiceTypes and the second item is a dict of parameters and values required by the service :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: float :return: DDO instance """ assert isinstance( metadata, dict), f"Expected metadata of type dict, got {type(metadata)}" assert service_descriptors is None or isinstance( service_descriptors, list ), f"bad type of `service_descriptors` {type(service_descriptors)}" # 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}" if not plecos.is_valid_dict_local(metadata_copy): errors = plecos.list_errors_dict_local(metadata_copy) msg = f"Metadata has validation errors: {errors}" logger.error(msg) raise ValueError(msg) service_descriptors = service_descriptors or [] services = self._process_service_descriptors(service_descriptors, metadata_copy, provider_uri, publisher_wallet) stype_to_service = {s.type: s for s in services} checksum_dict = dict() for service in services: checksum_dict[str(service.index)] = checksum(service.main) # Create a DDO object asset = Asset() # Adding proof to the ddo. asset.add_proof(checksum_dict, publisher_wallet) ################# # DataToken address = DTFactory.configured_address(Web3Helper.get_network_name(), self._config.address_file) dtfactory = DTFactory(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, to_base_18(_cap), from_wallet=publisher_wallet) data_token = DataToken(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: # verify data_token_address dt = DataToken(data_token_address) minter = dt.contract_concise.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." ) elif not dtfactory.verify_data_token(data_token_address): raise AssertionError( f"datatoken address {data_token_address} is not found in the DTFactory events." ) assert ( data_token_address ), "data_token_address is required for publishing a dataset asset." # Generating the did and adding to the ddo. did = asset.assign_did( f"did:op:{remove_0x_prefix(data_token_address)}") logger.debug(f"Using datatoken address as did: {did}") # Check if it's already registered first! if did in self._get_aquarius().list_assets(): raise OceanDIDAlreadyExist( f"Asset id {did} is already registered to another asset.") md_service = stype_to_service[ServiceTypes.METADATA] ddo_service_endpoint = md_service.service_endpoint if "{did}" in ddo_service_endpoint: ddo_service_endpoint = ddo_service_endpoint.replace("{did}", did) md_service.set_service_endpoint(ddo_service_endpoint) # Populate the ddo services asset.add_service(md_service) access_service = stype_to_service.get(ServiceTypes.ASSET_ACCESS, None) compute_service = stype_to_service.get(ServiceTypes.CLOUD_COMPUTE, None) if access_service: asset.add_service(access_service) if compute_service: asset.add_service(compute_service) asset.proof["signatureValue"] = Web3Helper.sign_hash( add_ethereum_prefix_and_hash_msg(asset.asset_id), publisher_wallet) # Add public key and authentication asset.add_public_key(did, publisher_wallet.address) asset.add_authentication(did, PUBLIC_KEY_TYPE_RSA) # 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, self._config) _, 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 try: # publish the new ddo in ocean-db/Aquarius ddo_registry = self.ddo_registry() web3 = Web3Provider.get_web3() tx_id = ddo_registry.create( asset.asset_id, bytes([1]), lzma.compress(web3.toBytes(text=asset.as_text())), publisher_wallet, ) if not ddo_registry.verify_tx(tx_id): raise AssertionError( 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 get_ocean_token_address(network=None): addresses = get_contracts_addresses( network or Web3Helper.get_network_name(), ConfigProvider.get_config()) return addresses.get("Ocean") if addresses else None
def get_bfactory_address(network=None): return BFactory.configured_address( network or Web3Helper.get_network_name(), ConfigProvider.get_config().address_file, )
def test_get_OCEAN_address(publisher_ocean_instance): """Tests OCEAN address retrieval.""" network = Web3Helper.get_network_name() assert publisher_ocean_instance.pool.get_OCEAN_address( ) == get_ocean_token_address(network)