def build_and_send_ddo_with_compute_service(client, alg_diff=False, asset_type=None): pub_wallet = get_publisher_wallet() cons_wallet = get_consumer_wallet() # publish an algorithm asset (asset with metadata of type `algorithm`) alg_ddo = (get_algorithm_ddo_different_provider(client, cons_wallet) if alg_diff else get_algorithm_ddo(client, cons_wallet)) alg_data_token = alg_ddo.as_dictionary()["dataToken"] alg_dt_contract = DataToken(alg_data_token) mint_tokens_and_wait(alg_dt_contract, cons_wallet, cons_wallet) # publish a dataset asset if asset_type == "allow_all_published": dataset_ddo_w_compute_service = comp_ds_allow_all_published( client, pub_wallet) elif asset_type == "specific_algo_dids": algos = [] for _ in itertools.repeat(None, 2): alg_ddo = get_algorithm_ddo(client, cons_wallet) alg_data_token = alg_ddo.as_dictionary()["dataToken"] alg_dt_contract = DataToken(alg_data_token) mint_tokens_and_wait(alg_dt_contract, cons_wallet, cons_wallet) algos.append(alg_ddo) dataset_ddo_w_compute_service = comp_ds_specific_algo_dids( client, pub_wallet, algos) else: dataset_ddo_w_compute_service = comp_ds(client, pub_wallet) did = dataset_ddo_w_compute_service.did ddo = dataset_ddo_w_compute_service data_token = dataset_ddo_w_compute_service.data_token_address dt_contract = DataToken(data_token) mint_tokens_and_wait(dt_contract, cons_wallet, pub_wallet) sa = ServiceAgreement.from_ddo(ServiceTypes.CLOUD_COMPUTE, dataset_ddo_w_compute_service) tx_id = send_order(client, ddo, dt_contract, sa, cons_wallet) alg_service = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, alg_ddo) alg_tx_id = send_order(client, alg_ddo, alg_dt_contract, alg_service, cons_wallet) return ( dataset_ddo_w_compute_service, did, tx_id, sa, data_token, alg_ddo, alg_data_token, alg_dt_contract, alg_tx_id, )
def test_compute_specific_algo_dids(client): pub_wallet = get_publisher_wallet() cons_wallet = get_consumer_wallet() # publish a dataset asset dataset_ddo_w_compute_service = get_dataset_ddo_with_compute_service_specific_algo_dids(client, pub_wallet) did = dataset_ddo_w_compute_service.did ddo = dataset_ddo_w_compute_service data_token = dataset_ddo_w_compute_service.as_dictionary()['dataToken'] dt_contract = DataToken(data_token) mint_tokens_and_wait(dt_contract, cons_wallet, pub_wallet) # publish an algorithm asset (asset with metadata of type `algorithm`) alg_ddo = get_algorithm_ddo(client, cons_wallet) alg_data_token = alg_ddo.as_dictionary()['dataToken'] alg_dt_contract = DataToken(alg_data_token) mint_tokens_and_wait(alg_dt_contract, pub_wallet, cons_wallet) # CHECKPOINT 1 sa = ServiceAgreement.from_ddo(ServiceTypes.CLOUD_COMPUTE, dataset_ddo_w_compute_service) tx_id = send_order(client, ddo, dt_contract, sa, cons_wallet) nonce = get_nonce(client, cons_wallet.address) # prepare consumer signature on did msg = f'{cons_wallet.address}{did}{nonce}' _hash = add_ethereum_prefix_and_hash_msg(msg) signature = Web3Helper.sign_hash(_hash, cons_wallet) # Start the compute job payload = dict({ 'signature': signature, 'documentId': did, 'serviceId': sa.index, 'serviceType': sa.type, 'consumerAddress': cons_wallet.address, 'transferTxId': tx_id, 'dataToken': data_token, 'output': build_stage_output_dict(dict(), dataset_ddo_w_compute_service, cons_wallet.address, pub_wallet), 'algorithmDid': alg_ddo.did, 'algorithmMeta': {}, 'algorithmDataToken': alg_data_token }) compute_endpoint = BaseURLs.ASSETS_URL + '/compute' response = client.post( compute_endpoint, data=json.dumps(payload), content_type='application/json' ) assert response.status == '400 BAD REQUEST', f'start compute job failed: {response.status} , { response.data}'
def publish_asset(metadata, publisher_wallet): ocean = Ocean(config=Config(options_dict=get_config_dict())) # create compute service compute_descriptor = build_compute_descriptor(ocean, publisher_wallet.address) # create asset DDO and datatoken try: asset = ocean.assets.create(metadata, publisher_wallet, [compute_descriptor], dt_name='Compute with data6', dt_symbol='DT-Testx7') print(f'Dataset asset created successfully: did={asset.did}, datatoken={asset.data_token_address}') #Dataset asset created successfully: did=did:op:2cbDb0Aaa1F546829E31267d1a7F74d926Bb5B1B, datatoken=0x2cbDb0Aaa1F546829E31267d1a7F74d926Bb5B1B except Exception as e: print(f'Publishing asset failed: {e}') return None, None dt = DataToken(asset.data_token_address) txid = dt.mint_tokens(publisher_wallet.address, 100, publisher_wallet) receipt = dt.get_tx_receipt(txid) assert receipt and receipt.status == 1, f'datatoken mint failed: tx={txid}, txReceipt={receipt}' # Create datatoken liquidity pool for the new asset pool = ocean.pool.create(asset.data_token_address, 50, 5, publisher_wallet, 5) #50 datatokens - 5 ocean in pool print(f'datatoken liquidity pool was created at address {pool.address}') #datatoken liquidity pool was created at address 0xeaD638506951B4a4c3575bbC0c7D1491c17B7A08 # Now the asset can be discovered and consumed dt_cost = ocean.pool.calcInGivenOut(pool.address, ocean.OCEAN_address, asset.data_token_address, 1.0) print(f'Asset {asset.did} can now be purchased from pool @{pool.address} ' f'at the price of {dt_cost} OCEAN tokens.') return asset, pool
def is_dispensable(self, dt_address: str, amount: int, to_wallet: Wallet) -> bool: """ :return: bool """ if not amount: return False token = DataToken(self.web3, dt_address) if not self.is_active(dt_address): return False user_balance = token.balanceOf(to_wallet.address) max_balance = self.max_balance(dt_address) if user_balance >= max_balance: return False max_tokens = self.max_balance(dt_address) if amount > max_tokens: return False is_true_minter = self.is_true_minter(dt_address) if is_true_minter: return True contract_balance = self.balance(dt_address) if contract_balance >= amount: return True return False
def cancel_minter(self, dt_address: str, from_wallet: Wallet) -> str: """ :return: hex str transaction hash """ self.send_transaction("removeMinter", (dt_address, ), from_wallet) token = DataToken(self.web3, dt_address) return token.approveMinter(from_wallet)
def get_user_orders( self, address: str, datatoken: Optional[str] = None, service_id: Optional[int] = None, ) -> List[Order]: """ :return: List of orders `[Order]` """ dt = DataToken(self.web3, datatoken) _orders = [] for log in dt.get_start_order_logs( address, from_all_tokens=not bool(datatoken) ): a = dict(log.args.items()) a["amount"] = int(log.args.amount) a["marketFee"] = int(log.args.marketFee) a = AttributeDict(a.items()) # 'datatoken', 'amount', 'timestamp', 'transactionId', 'did', 'payer', 'consumer', 'serviceId', 'serviceType' order = Order( log.address, a.amount, a.timestamp, log.transactionHash, f"did:op:{remove_0x_prefix(log.address)}", a.payer, a.consumer, a.serviceId, None, ) if service_id is None or order.serviceId == service_id: _orders.append(order) return _orders
def process_order(ocean_instance, publisher_wallet, consumer_wallet, ddo, service_type): """Helper function to process a compute order.""" # Give the consumer some datatokens so they can order the service try: dt = DataToken(ddo.data_token_address) tx_id = dt.transfer_tokens(consumer_wallet.address, 10, publisher_wallet) dt.verify_transfer_tx(tx_id, publisher_wallet.address, consumer_wallet.address) except (AssertionError, Exception) as e: print(e) raise # Order compute service from the dataset asset order_requirements = ocean_instance.assets.order(ddo.did, consumer_wallet.address, service_type=service_type) # Start the order on-chain using the `order` requirements from previous step service = ddo.get_service(service_type) consumer = consumer_wallet.address if service_type == ServiceTypes.ASSET_ACCESS and order_requirements.computeAddress: consumer = order_requirements.computeAddress _order_tx_id = ocean_instance.assets.pay_for_service( order_requirements.amount, order_requirements.data_token_address, ddo.did, service.index, ZERO_ADDRESS, consumer_wallet, consumer, ) return _order_tx_id, order_requirements, service
def buy_data_tokens( self, pool_address: str, amount: int, max_OCEAN_amount: int, from_wallet: Wallet ) -> str: """ Buy data tokens from this pool, paying `max_OCEAN_amount` of OCEAN tokens. If total spent <= max_OCEAN_amount. - Caller is spending OCEAN tokens, and receiving `amount` DataTokens - OCEAN tokens are going into pool, DataTokens are going out of pool The transaction fails if total spent exceeds `max_OCEAN_amount`. :param pool_address: str address of pool contract :param amount: int number of data tokens to add to this pool in *base* :param max_OCEAN_amount: :param from_wallet: :return: str transaction id/hash """ ocean_tok = DataToken(self.web3, self.ocean_address) if ocean_tok.balanceOf(from_wallet.address) < max_OCEAN_amount: raise InsufficientBalance("Insufficient funds for buying DataTokens!") if ocean_tok.allowance(from_wallet.address, pool_address) < max_OCEAN_amount: ocean_tok.approve(pool_address, max_OCEAN_amount, from_wallet) dtoken_address = self.get_token_address(pool_address) pool = BPool(self.web3, pool_address) return pool.swapExactAmountOut( tokenIn_address=self.ocean_address, # entering pool maxAmountIn=max_OCEAN_amount, # "" tokenOut_address=dtoken_address, # leaving pool tokenAmountOut=amount, # "" maxPrice=2 ** 255, # here we limit by max_num_OCEAN, not price from_wallet=from_wallet, )
def buy_at_fixed_rate( self, amount: float, wallet: Wallet, max_OCEAN_amount: float, exchange_id: str = "", data_token: str = "", exchange_owner: str = "", ) -> bool: exchange, exchange_id = self.get_exchange_id_fallback_dt_and_owner( exchange_id, exchange_owner, data_token) amount_base = to_base_18(amount) max_OCEAN_amount_base = to_base_18(max_OCEAN_amount) # Figure out the amount of ocean tokens to approve before triggering the exchange function to do the swap ocean_amount_base = exchange.get_base_token_quote( exchange_id, amount_base) if ocean_amount_base > max_OCEAN_amount_base: raise ValidationError( f"Buying {amount} datatokens requires {from_base_18(ocean_amount_base)} OCEAN " f"tokens which exceeds the max_OCEAN_amount {max_OCEAN_amount}." ) ocean_token = DataToken(self.ocean_address) ocean_token.get_tx_receipt( ocean_token.approve(self._exchange_address, ocean_amount_base, wallet)) tx_id = exchange.buy_data_token(exchange_id, data_token_amount=amount_base, from_wallet=wallet) return bool(exchange.get_tx_receipt(tx_id).status)
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 buy_data_tokens(self, pool_address: str, amount: float, max_OCEAN_amount: float, from_wallet: Wallet) -> str: """ Buy data tokens from this pool, paying `max_OCEAN_amount_base` of OCEAN tokens. If total spent <= max_OCEAN_amount_base. - Caller is spending OCEAN tokens, and receiving `amount_base` DataTokens - OCEAN tokens are going into pool, DataTokens are going out of pool The transaction fails if total spent exceeds `max_OCEAN_amount_base`. :param pool_address: str address of pool contract :param amount: int number of data tokens to add to this pool in *base* :param max_OCEAN_amount: :param from_wallet: :return: str transaction id/hash """ ocean_tok = DataToken(self.ocean_address) ocean_tok.approve_tokens(pool_address, max_OCEAN_amount, from_wallet, wait=True) dtoken_address = self.get_token_address(pool_address) pool = BPool(pool_address) return pool.swapExactAmountOut( tokenIn_address=self.ocean_address, # entering pool maxAmountIn_base=to_base_18(max_OCEAN_amount), # "" tokenOut_address=dtoken_address, # leaving pool tokenAmountOut_base=to_base_18(amount), # "" maxPrice_base=2**255, # here we limit by max_num_OCEAN, not price from_wallet=from_wallet, )
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 get_data_token(self, token_address: str) -> DataToken: """ :param token_address: Token contract address, str :return: `Datatoken` instance """ return DataToken(self.web3, token_address)
def buy_at_fixed_rate(self, amount: float, wallet: Wallet, max_OCEAN_amount: float, exchange_id: str = '', data_token: str = '', exchange_owner: str = '') -> bool: exchange = self._exchange_contract() if not exchange_id: assert exchange_owner and data_token, f'exchange_owner and data_token are required when exchange_id is not given.' exchange_id = exchange.generateExchangeId(self.ocean_address, data_token, exchange_owner) amount_base = to_base_18(amount) max_OCEAN_amount_base = to_base_18(max_OCEAN_amount) # Figure out the amount of ocean tokens to approve before triggering the exchange function to do the swap ocean_amount_base = exchange.get_base_token_quote( exchange_id, amount_base) if ocean_amount_base > max_OCEAN_amount_base: raise AssertionError( f'Buying {amount} datatokens requires {from_base_18(ocean_amount_base)} OCEAN ' f'tokens which exceeds the max_OCEAN_amount {max_OCEAN_amount}.' ) ocean_token = DataToken(self.ocean_address) ocean_token.get_tx_receipt( ocean_token.approve(self._exchange_address, ocean_amount_base, wallet)) tx_id = exchange.buy_data_token(exchange_id, data_token_amount=amount_base, from_wallet=wallet) return bool(exchange.get_tx_receipt(tx_id).status)
def _deployAndMintToken(symbol: str, to_address: str) -> btoken.BToken: wallet = get_factory_deployer_wallet(_NETWORK) dt_address = DataToken.deploy( wallet.web3, wallet, None, "Template Contract", "TEMPLATE", wallet.address, to_base_18(1000), DTFactory.FIRST_BLOB, to_address, ) dt_factory = DTFactory( DTFactory.deploy(wallet.web3, wallet, None, dt_address, to_address) ) token_address = dt_factory.get_token_address( dt_factory.createToken( symbol, symbol, symbol, DataToken.DEFAULT_CAP_BASE, wallet ) ) token = DataToken(token_address) token.mint(to_address, to_base_18(1000), wallet) return btoken.BToken(token.address)
def publish_asset(metadata, publisher_wallet): ocean = Ocean(config=Config(options_dict=get_config_dict())) # create compute service compute_descriptor = build_compute_descriptor(ocean, publisher_wallet.address) # create asset DDO and datatoken try: asset = ocean.assets.create(metadata, publisher_wallet, [compute_descriptor], dt_name='Dataset with Compute', dt_symbol='DT-Compute') print(f'Dataset asset created successfully: did={asset.did}, datatoken={asset.data_token_address}') except Exception as e: print(f'Publishing asset failed: {e}') return None, None dt = DataToken(asset.data_token_address) txid = dt.mint_tokens(publisher_wallet.address, 100, publisher_wallet) receipt = dt.get_tx_receipt(txid) assert receipt and receipt.status == 1, f'datatoken mint failed: tx={txid}, txReceipt={receipt}' # Create datatoken liquidity pool for the new asset pool = ocean.pool.create(asset.data_token_address, 50, 50, publisher_wallet, 5) print(f'datatoken liquidity pool was created at address {pool.address}') # Now the asset can be discovered and consumed dt_cost = ocean.pool.calcInGivenOut(pool.address, ocean.OCEAN_address, asset.data_token_address, 1.0) print(f'Asset {asset.did} can now be purchased from pool @{pool.address} ' f'at the price of {dt_cost} OCEAN tokens.') return asset, pool
def get_user_orders(self, address, datatoken=None, service_id=None): dt = DataToken(datatoken) _orders = [] for log in dt.get_start_order_logs( self._web3, address, from_all_tokens=not bool(datatoken)): a = dict(log.args.items()) a["amount"] = from_base_18(int(log.args.amount)) a["marketFee"] = from_base_18(int(log.args.marketFee)) a = AttributeDict(a.items()) # 'datatoken', 'amount', 'timestamp', 'transactionId', 'did', 'payer', 'consumer', 'serviceId', 'serviceType' order = Order( log.address, a.amount, a.timestamp, log.transactionHash, f"did:op:{remove_0x_prefix(log.address)}", a.payer, a.consumer, a.serviceId, None, ) if service_id is None or order.serviceId == service_id: _orders.append(order) return _orders
def get_datatoken_minter(asset, datatoken_address): publisher = Web3Provider.get_web3().toChecksumAddress(asset.publisher) dt = DataToken(datatoken_address) if not dt.contract_concise.isMinter(publisher): raise AssertionError(f'ddo publisher {publisher} is not the current ' f'minter for the DataToken contract at {datatoken_address}.') return publisher
def pay_for_service( amount: float, token_address: str, did: str, service_id: int, fee_receiver: str, from_wallet: Wallet, consumer: str, ) -> str: """ Submits the payment for chosen service in DataTokens. :param amount: :param token_address: :param did: :param service_id: :param fee_receiver: :param from_wallet: Wallet instance :param consumer: str the address of consumer of the service, defaults to the payer (the `from_wallet` address) :return: hex str id of transfer transaction """ amount_base = to_base_18(amount) dt = DataToken(token_address) balance = dt.balanceOf(from_wallet.address) if balance < amount_base: raise AssertionError( f"Your token balance {balance} is not sufficient " f"to execute the requested service. This service " f"requires {amount_base} number of tokens.") if did.startswith("did:"): did = add_0x_prefix(did_to_id(did)) if fee_receiver is None: fee_receiver = ZERO_ADDRESS if consumer is None: consumer = from_wallet.address tx_hash = dt.startOrder(consumer, amount_base, service_id, fee_receiver, from_wallet) try: dt.verify_order_tx( Web3Provider.get_web3(), tx_hash, did, service_id, amount_base, from_wallet.address, ) return tx_hash except (AssertionError, Exception) as e: msg = ( f"Downloading asset files failed. The problem is related to " f"the transfer of the data tokens required for the download " f"service: {e}") logger.error(msg) raise AssertionError(msg)
def make_minter(self, dt_address: str, from_wallet: Wallet) -> str: """ :return: hex str transaction hash """ token = DataToken(self.web3, dt_address) token.proposeMinter(self.address, from_wallet=from_wallet) return self.send_transaction("acceptMinter", (dt_address, ), from_wallet)
def test_order(web3, alice_ocean, alice_wallet): asset = get_registered_ddo(alice_ocean, get_metadata(), alice_wallet) dt = DataToken(web3, asset.data_token_address) service = asset.get_service(service_type=ServiceTypes.ASSET_ACCESS) sa = Service.from_json(service.as_dictionary()) order_requirements = alice_ocean.assets.order( asset.did, alice_wallet.address, sa.index ) assert order_requirements, "Order was unsuccessful." _order_tx_id = alice_ocean.assets.pay_for_service( web3, order_requirements.amount, order_requirements.data_token_address, asset.did, service.index, alice_wallet.address, alice_wallet, sa.get_c2d_address(), ) asset_folder = alice_ocean.assets.download( asset.did, sa.index, alice_wallet, _order_tx_id, alice_ocean.config.downloads_path, ) assert len(os.listdir(asset_folder)) >= 1, "The asset folder is empty." for order_log in dt.get_start_order_logs(): order_log_dict = dict(order_log.args.items()) order_log_dict["amount"] = int(order_log.args.amount) order_log_dict["marketFee"] = int(order_log.args.marketFee) order_args = [ order_log.address, order_log_dict["amount"], order_log_dict["timestamp"], order_log.transactionHash, f"did:op:{remove_0x_prefix(order_log.address)}", order_log_dict["payer"], order_log_dict["consumer"], order_log_dict["serviceId"], None, ] order = Order(*order_args) assert order, "The order does not exist." assert isinstance(order, tuple), "Order is not a tuple." assert ( order[0] == asset.data_token_address ), "The order data token address is different." assert order[5] == alice_wallet.address, "The payer is not the supposed one." assert order[6] == sa.get_c2d_address(), "The consumer is not the supposed one." assert len(order) == 9, "Different number of args."
def test_compute_norawalgo_allowed(client): pub_wallet = get_publisher_wallet() cons_wallet = get_consumer_wallet() # publish a dataset asset dataset_ddo_w_compute_service = get_dataset_ddo_with_compute_service_no_rawalgo(client, pub_wallet) did = dataset_ddo_w_compute_service.did ddo = dataset_ddo_w_compute_service data_token = dataset_ddo_w_compute_service.data_token_address dt_contract = DataToken(data_token) mint_tokens_and_wait(dt_contract, cons_wallet, pub_wallet) # CHECKPOINT 1 algorithm_meta = { "rawcode": "console.log('Hello world'!)", "format": 'docker-image', "version": '0.1', "container": { "entrypoint": 'node $ALGO', "image": 'node', "tag": '10' } } # prepare parameter values for the compute endpoint # signature, documentId, consumerAddress, and algorithmDid or algorithmMeta sa = ServiceAgreement.from_ddo(ServiceTypes.CLOUD_COMPUTE, dataset_ddo_w_compute_service) tx_id = send_order(client, ddo, dt_contract, sa, cons_wallet) nonce = get_nonce(client, cons_wallet.address) # prepare consumer signature on did msg = f'{cons_wallet.address}{did}{nonce}' _hash = add_ethereum_prefix_and_hash_msg(msg) signature = Web3Helper.sign_hash(_hash, cons_wallet) # Start the compute job payload = dict({ 'signature': signature, 'documentId': did, 'serviceId': sa.index, 'serviceType': sa.type, 'consumerAddress': cons_wallet.address, 'transferTxId': tx_id, 'dataToken': data_token, 'output': build_stage_output_dict(dict(), dataset_ddo_w_compute_service, cons_wallet.address, pub_wallet), 'algorithmDid': '', 'algorithmMeta': algorithm_meta, 'algorithmDataToken': '' }) compute_endpoint = BaseURLs.ASSETS_URL + '/compute' response = client.post( compute_endpoint, data=json.dumps(payload), content_type='application/json' ) assert response.status == '400 BAD REQUEST', f'start compute job failed: {response.status} , { response.data}'
def _get_num_assets(_minter): dids = [ add_0x_prefix(did_to_id(a)) for a in ocn.assets.owner_assets(_minter) ] dids = [a for a in dids if len(a) == 42] return len([ a for a in dids if DataToken(a).contract_concise.isMinter(_minter) ])
def run_compute(did, consumer_wallet, algorithm_file, pool_address, order_id=None): ocean = Ocean(config=Config(options_dict=get_config_dict())) # Get asset DDO/metadata and service asset = ocean.assets.resolve(did) service = asset.get_service(ServiceTypes.CLOUD_COMPUTE) # check the price in ocean tokens num_ocean = ocean.pool.calcInGivenOut(pool_address, ocean.OCEAN_address, asset.data_token_address, 1.0) # buy datatoken to be able to run the compute service dt = DataToken(asset.asset_id) dt_balance = dt.token_balance(consumer_wallet.address) if dt_balance < 1.0: pool = BPool(pool_address) txid = ocean.pool.buy_data_tokens(pool_address, 1.0, num_ocean+0.1, consumer_wallet) receipt = pool.get_tx_receipt(txid) if not receipt or receipt.status != 1: print(f'buying data token failed: txId={txid}, txReceipt={receipt}') return None, None tx_id = order_id if not tx_id: tx_id = ocean.assets.pay_for_service(1.0, asset.data_token_address, did, service.index, fee_receiver=asset.publisher, from_wallet=consumer_wallet) # load python algorithm to run in the compute job with open(algorithm_file) as f: algorithm_text = f.read() # whether to publish the algorithm results as an Ocean assets output_dict = { 'publishOutput': False, 'publishAlgorithmLog': False, } # start the compute job (submit the compute service request) algorithm_meta = AlgorithmMetadata( { 'language': 'python', 'rawcode': algorithm_text, 'container': { 'tag': 'latest', 'image': 'amancevice/pandas', 'entrypoint': 'python $ALGO' } } ) job_id = ocean.compute.start(did, consumer_wallet, tx_id, algorithm_meta=algorithm_meta, output=output_dict) # check the status of the compute job status = ocean.compute.status(did, job_id, consumer_wallet) print(f'status of compute job {job_id}: {status}') # get the result of the compute run result = ocean.compute.result(did, job_id, consumer_wallet) print(f'got result of compute job {job_id}: {result}') return job_id, status
def test_download_service(client): aqua = Aquarius("http://localhost:5000") try: for did in aqua.list_assets(): aqua.retire_asset_ddo(did) except (ValueError, Exception): pass pub_wallet = get_publisher_wallet() cons_wallet = get_consumer_wallet() ddo = get_dataset_ddo_with_access_service(client, pub_wallet) dt_address = ddo.as_dictionary()["dataToken"] dt_token = DataToken(dt_address) mint_tokens_and_wait(dt_token, cons_wallet, pub_wallet) sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo) tx_id = send_order(client, ddo, dt_token, sa, cons_wallet) index = 0 download_endpoint = BaseURLs.ASSETS_URL + "/download" # Consume using url index and auth token # (let the provider do the decryption) payload = dict({ "documentId": ddo.did, "serviceId": sa.index, "serviceType": sa.type, "dataToken": dt_address, "consumerAddress": cons_wallet.address, }) payload["signature"] = generate_auth_token(cons_wallet) payload["transferTxId"] = tx_id payload["fileIndex"] = index request_url = (download_endpoint + "?" + "&".join([f"{k}={v}" for k, v in payload.items()])) response = client.get(request_url) assert response.status_code == 200, f"{response.data}" # Consume using url index and signature (withOUT nonce), should fail _hash = add_ethereum_prefix_and_hash_msg(ddo.did) payload["signature"] = Web3Helper.sign_hash(_hash, cons_wallet) request_url = (download_endpoint + "?" + "&".join([f"{k}={v}" for k, v in payload.items()])) print( ">>>> Expecting InvalidSignatureError from the download endpoint <<<<" ) # noqa response = client.get(request_url) assert response.status_code == 400, f"{response.data}" # Consume using url index and signature (with nonce) nonce = get_nonce(client, cons_wallet.address) _hash = add_ethereum_prefix_and_hash_msg(f"{ddo.did}{nonce}") payload["signature"] = Web3Helper.sign_hash(_hash, cons_wallet) request_url = (download_endpoint + "?" + "&".join([f"{k}={v}" for k, v in payload.items()])) response = client.get(request_url) assert response.status_code == 200, f"{response.data}"
def test_initialize_on_ipfs_url(client): pub_wallet = get_publisher_wallet() cons_wallet = get_consumer_wallet() ddo = get_dataset_with_ipfs_url_ddo(client, pub_wallet) data_token = ddo.data_token_address dt_contract = DataToken(data_token) sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo) send_order(client, ddo, dt_contract, sa, cons_wallet)
def get_token_minter(self, token_address): """Retrieves token minter. This function will be deprecated in the next major release. It's only kept for backwards compatibility.""" from ocean_lib.models.data_token import DataToken # isort:skip dt = DataToken(address=token_address) return dt.contract_concise.minter()
def test_get_token_minter(web3, alice_wallet, dtfactory_address, alice_address): """Tests proper retrieval of token minter from DTFactory.""" dtfactory = DTFactory(web3, dtfactory_address) dt_address = dtfactory.createToken( "foo_blob", "DT1", "DT1", to_wei(1000), from_wallet=alice_wallet ) dt = DataToken(web3, dtfactory.get_token_address(dt_address)) dt.mint(alice_address, to_wei(10), from_wallet=alice_wallet) assert dtfactory.get_token_minter(dt.address) == alice_address
def validate_order(sender, token_address, num_tokens, tx_id, did, service_id): dt_contract = DataToken(token_address) try: amount = to_base_18(num_tokens) tx, order_event, transfer_event = dt_contract.verify_order_tx( Web3Provider.get_web3(), tx_id, did, service_id, amount, sender) return tx, order_event, transfer_event except AssertionError: raise
def test_download_service(client): aqua = Aquarius('http://localhost:5000') try: for did in aqua.list_assets(): aqua.retire_asset_ddo(did) except (ValueError, Exception): pass pub_wallet = get_publisher_wallet() cons_wallet = get_consumer_wallet() ddo = get_dataset_ddo_with_access_service(client, pub_wallet) dt_address = ddo.as_dictionary()['dataToken'] dt_token = DataToken(dt_address) mint_tokens_and_wait(dt_token, cons_wallet, pub_wallet) sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo) tx_id = send_order(client, ddo, dt_token, sa, cons_wallet) index = 0 download_endpoint = BaseURLs.ASSETS_URL + '/download' # Consume using url index and auth token (let the provider do the decryption) payload = dict({ 'documentId': ddo.did, 'serviceId': sa.index, 'serviceType': sa.type, 'dataToken': dt_address, 'consumerAddress': cons_wallet.address }) payload['signature'] = generate_auth_token(cons_wallet) payload['transferTxId'] = tx_id payload['fileIndex'] = index request_url = download_endpoint + '?' + '&'.join( [f'{k}={v}' for k, v in payload.items()]) response = client.get(request_url) assert response.status_code == 200, f'{response.data}' # Consume using url index and signature (withOUT nonce), should fail _hash = add_ethereum_prefix_and_hash_msg(ddo.did) payload['signature'] = Web3Helper.sign_hash(_hash, cons_wallet) request_url = download_endpoint + '?' + '&'.join( [f'{k}={v}' for k, v in payload.items()]) print( '>>>> Expecting InvalidSignatureError from the download endpoint <<<<') response = client.get(request_url) assert response.status_code == 401, f'{response.data}' # Consume using url index and signature (with nonce) nonce = get_nonce(client, cons_wallet.address) _hash = add_ethereum_prefix_and_hash_msg(f'{ddo.did}{nonce}') payload['signature'] = Web3Helper.sign_hash(_hash, cons_wallet) request_url = download_endpoint + '?' + '&'.join( [f'{k}={v}' for k, v in payload.items()]) response = client.get(request_url) assert response.status_code == 200, f'{response.data}'