def access(service_agreement_id, service_index, ddo, consumer_account, destination, gateway, secret_store, config, index=None): """ Download asset data files or result files from a compute job. :param service_agreement_id: Service agreement id, str :param service_index: identifier of the service inside the asset DDO, str :param ddo: DDO :param consumer_account: Account instance of the consumer :param destination: Path, str :param gateway: Gateway instance :param secret_store: SecretStore instance :param config: Sdk configuration instance :param index: Index of the document that is going to be downloaded, int :return: Asset folder path, str """ did = ddo.did sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo) consume_url = sa.service_endpoint if not consume_url: logger.error( 'Consume asset failed, service definition is missing the "serviceEndpoint".' ) raise AssertionError( 'Consume asset failed, service definition is missing the "serviceEndpoint".' ) if ddo.get_service(ServiceTypes.AUTHORIZATION): secret_store_service = ddo.get_service( service_type=ServiceTypes.AUTHORIZATION) secret_store_url = secret_store_service.service_endpoint secret_store.set_secret_store_url(secret_store_url) asset_folder = create_asset_folder(did, service_index, destination) 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(ddo.metadata['main']['files']), logger.error( 'index can not be bigger than the number of files') if index is not None: gateway.access_service(did, service_agreement_id, consume_url, consumer_account, asset_folder, config, index) else: for i, _file in enumerate(ddo.metadata['main']['files']): gateway.access_service(did, service_agreement_id, consume_url, consumer_account, asset_folder, config, i) return asset_folder
def test_consume(client, provider_account, consumer_account): endpoint = BaseURLs.ASSETS_URL + '/consume' for method in constants.ConfigSections.DECRYPTION_METHODS: print('Testing Consume with Authorization Method: ' + method) ddo = get_registered_ddo(provider_account, providers=[provider_account.address], auth_service=method) # initialize an agreement agreement_id = place_order(provider_account, ddo, consumer_account, ServiceTypes.ASSET_ACCESS) payload = dict({ 'serviceAgreementId': agreement_id, 'consumerAddress': consumer_account.address }) print('Provider: ' + provider_account.address) print('Consumer: ' + consumer_account.address) keeper = keeper_instance() agr_id_hash = add_ethereum_prefix_and_hash_msg(agreement_id) signature = keeper.sign_hash(agr_id_hash, consumer_account) index = 0 event = keeper.access_template.subscribe_agreement_created( agreement_id, 15, None, (), wait=True, from_block=0) assert event, "Agreement event is not found, check the keeper node's logs" consumer_balance = keeper.token.get_token_balance( consumer_account.address) if consumer_balance < 50: keeper.dispenser.request_tokens(50 - consumer_balance, consumer_account) sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo) lock_payment(agreement_id, ddo.asset_id, sa, amounts, receivers, consumer_account) event = keeper.lock_payment_condition.subscribe_condition_fulfilled( agreement_id, 15, None, (), wait=True, from_block=0) assert event, "Lock reward condition fulfilled event is not found, check the keeper " \ "node's logs" grant_access(agreement_id, ddo, consumer_account, provider_account) event = keeper.access_condition.subscribe_condition_fulfilled( agreement_id, 15, None, (), wait=True, from_block=0) assert event or keeper.access_condition.check_permissions( ddo.asset_id, consumer_account.address ), f'Failed to get access permission: agreement_id={agreement_id}, ' \ f'did={ddo.did}, consumer={consumer_account.address}' # Consume using url index and signature (let the gateway do the decryption) payload['signature'] = signature payload['index'] = index request_url = endpoint + '?' + '&'.join( [f'{k}={v}' for k, v in payload.items()]) response = client.get(request_url) assert response.status == '200 OK'
def test_nft_access(client, provider_account, consumer_account): keeper = keeper_instance() ddo = get_nft_ddo(provider_account, providers=[provider_account.address]) asset_id = ddo.asset_id nft_amounts = 1 keeper.nft_upgradeable.transfer_nft(asset_id, consumer_account.address, nft_amounts, provider_account) assert keeper.nft_upgradeable.balance(consumer_account.address, asset_id) >= nft_amounts nft_access_service_agreement = ServiceAgreement.from_ddo( ServiceTypes.NFT_ACCESS, ddo) agreement_id = ServiceAgreement.create_new_agreement_id() (nft_access_cond_id, nft_holder_cond_id ) = nft_access_service_agreement.generate_agreement_condition_ids( agreement_id, asset_id, consumer_account.address, keeper) print('NFT_ACCESS_DID: ' + asset_id) keeper.nft_access_template.create_agreement( agreement_id, asset_id, [nft_holder_cond_id, nft_access_cond_id], nft_access_service_agreement.conditions_timelocks, nft_access_service_agreement.conditions_timeouts, consumer_account.address, consumer_account) event = keeper.nft_access_template.subscribe_agreement_created( agreement_id, 15, None, (), wait=True, from_block=0) assert event, "Agreement event is not found, check the keeper node's logs" # generate the grant token grant_token = generate_access_grant_token(consumer_account, agreement_id, ddo.did, uri="/nft-access") # request access token response = client.post("/api/v1/gateway/services/oauth/token", data={ "grant_type": NeverminedJWTBearerGrant.GRANT_TYPE, "assertion": grant_token }) access_token = response.get_json()["access_token"] index = 0 endpoint = BaseURLs.ASSETS_URL + '/nft-access/%s/%d' % (agreement_id, index) response = client.get(endpoint, headers={"Authorization": f"Bearer {access_token}"}) assert response.status == '200 OK' assert len( keeper.did_registry.get_provenance_method_events( 'USED', did_bytes=did_to_id_bytes(ddo.did))) >= 1
def setup_nft_sales_agreements_environment(): consumer_acc = get_consumer_account() publisher_acc = get_publisher_account() keeper = Keeper.get_instance() ddo = get_ddo_nft_sample() did_seed = generate_prefixed_id() asset_id = keeper.did_registry.hash_did(did_seed, publisher_acc.address) ddo._did = DID.did(asset_id) keeper.did_registry.register_mintable_did( did_seed, checksum=Web3Provider.get_web3().toBytes(hexstr=ddo.asset_id), url='http://172.17.0.1:5000', cap=10, royalties=10, account=publisher_acc, providers=None) keeper.did_registry.mint(ddo.asset_id, 10, account=publisher_acc) service_agreement = ServiceAgreement.from_ddo(ServiceTypes.NFT_SALES, ddo) agreement_id = ServiceAgreement.create_new_agreement_id() price = service_agreement.get_price() (access_cond_id, lock_cond_id, escrow_cond_id) = service_agreement.generate_agreement_condition_ids( agreement_id, asset_id, consumer_acc.address, keeper) nft_access_service_agreement = ServiceAgreement.from_ddo( ServiceTypes.NFT_ACCESS, ddo) nft_access_agreement_id = ServiceAgreement.create_new_agreement_id() (nft_access_cond_id, nft_holder_cond_id ) = nft_access_service_agreement.generate_agreement_condition_ids( nft_access_agreement_id, asset_id, consumer_acc.address, keeper) return (keeper, ddo, publisher_acc, consumer_acc, agreement_id, nft_access_agreement_id, asset_id, price, service_agreement, nft_access_service_agreement, (lock_cond_id, access_cond_id, escrow_cond_id), (nft_access_cond_id, nft_holder_cond_id))
def validate_nft_access(self, agreement_id, did, consumer_address): keeper = keeper_instance() asset = DIDResolver(keeper.did_registry).resolve(did) # check which nft access service type is on the ddo service_type = ServiceTypes.NFT_ACCESS if asset.get_service(ServiceTypes.NFT721_ACCESS) is not None: service_type = ServiceTypes.NFT721_ACCESS sa = ServiceAgreement.from_ddo(service_type, asset) return self._validate_nft_access(agreement_id, did, consumer_address, sa, service_type)
def _validate_nft_access(self, agreement_id, did, consumer_address, service_agreement, service_type): keeper = keeper_instance() asset = DIDResolver(keeper.did_registry).resolve(did) asset_id = asset.asset_id sa_name = service_agreement.main['name'] erc721_address = service_agreement.get_param_value_by_name('_contractAddress') access_granted = False if agreement_id is None or agreement_id == '0x': if sa_name == 'nftAccessAgreement': access_granted = is_nft_holder(keeper, asset_id, service_agreement.get_number_nfts(), consumer_address) elif sa_name == 'nft721AccessAgreement': access_granted = is_nft721_holder(keeper, asset_id, consumer_address, erc721_address) else: agreement = keeper.agreement_manager.get_agreement(agreement_id) cond_ids = agreement.condition_ids access_cond_id = cond_ids[1] ddo = DIDResolver(keeper.did_registry).resolve(did) nft_access_service_agreement = ServiceAgreement.from_ddo(service_type, ddo) (nft_access_cond_id, nft_holder_cond_id) = nft_access_service_agreement.generate_agreement_condition_ids(agreement_id, asset_id, consumer_address, keeper) if [nft_holder_cond_id, nft_access_cond_id] != cond_ids: raise InvalidClientError(f"ServiceAgreement {agreement_id} doesn't match ddo") if not is_nft_access_condition_fulfilled( agreement_id, access_cond_id, consumer_address, keeper): # If not granted, verification of agreement and conditions and fulfill # access_granted = is_nft_holder(keeper, asset_id, sa.get_number_nfts(), consumer_address) access_granted = fulfill_nft_holder_and_access_condition( keeper, agreement_id, cond_ids, asset_id, service_agreement.get_number_nfts(), consumer_address, self.provider_account ) if not access_granted: msg = ('Checking access permissions failed. Either consumer address does not have ' 'permission to consume this NFT or consumer address and/or service ' 'agreement ' 'id is invalid.') logger.warning(msg) raise InvalidClientError(msg)
def test_access_endpoint_bad_signature(client, provider_account, consumer_account): # The provider_account will place the order and consumer_account # will try to request access to it # order access keeper = keeper_instance() ddo = get_registered_ddo(provider_account, providers=[provider_account.address]) agreement_id = place_order(provider_account, ddo, provider_account) event = keeper.access_template.subscribe_agreement_created(agreement_id, 15, None, (), wait=True, from_block=0) assert event, "Agreement event is not found, check the keeper node's logs" consumer_balance = keeper.token.get_token_balance(consumer_account.address) if consumer_balance < 50: keeper.dispenser.request_tokens(50 - consumer_balance, consumer_account) sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo) lock_payment(agreement_id, ddo.asset_id, sa, amounts, receivers, consumer_account) event = keeper.lock_payment_condition.subscribe_condition_fulfilled( agreement_id, 15, None, (), wait=True, from_block=0) assert event, "Lock reward condition fulfilled event is not found, check the keeper node's logs" # create jwt bearer grant jwk = account_to_jwk(consumer_account) assertion = NeverminedJWTBearerGrant.sign(jwk, issuer=consumer_account.address, audience=BaseURLs.ASSETS_URL + '/access', subject=agreement_id, claims={"did": ddo.did}, header={"alg": "ES256K"}) response = client.post("/api/v1/gateway/services/oauth/token", data={ "grant_type": NeverminedJWTBearerGrant.GRANT_TYPE, "assertion": assertion }) assert response.status_code == 400 assert response.get_json()["error"] == "invalid_client"
def test_execute_endpoint(client, provider_account, consumer_account): ddo_compute = get_registered_compute_ddo( provider_account, providers=[provider_account.address]) ddo_algorithm = get_registered_algorithm_ddo( consumer_account, providers=[provider_account.address]) ddo_workflow = get_registered_workflow_ddo( consumer_account, ddo_compute.did, ddo_algorithm.did, providers=[provider_account.address]) # initialize agreement agreement_id = place_order(provider_account, ddo_compute, consumer_account, service_type=ServiceTypes.CLOUD_COMPUTE) sa = ServiceAgreement.from_ddo(ServiceTypes.CLOUD_COMPUTE, ddo_compute) lock_payment(agreement_id, ddo_compute.asset_id, sa, amounts, receivers, consumer_account) keeper = keeper_instance() event = keeper.lock_payment_condition.subscribe_condition_fulfilled( agreement_id, 60, None, (), wait=True) assert event is not None, "Reward condition is not found" # create jwt bearer grant jwk = account_to_jwk(consumer_account) assertion = NeverminedJWTBearerGrant.sign(jwk, issuer=consumer_account.address, subject=agreement_id, audience=BaseURLs.ASSETS_URL + '/execute', claims={"did": ddo_workflow.did}, header={"alg": "ES256K"}) response = client.post("/api/v1/gateway/services/oauth/token", data={ "grant_type": NeverminedJWTBearerGrant.GRANT_TYPE, "assertion": assertion }) assert response.status_code == 200 # use jwt access token to execute the compute access_token = response.get_json()["access_token"] response = client.post(f"/api/v1/gateway/services/execute/{agreement_id}", headers={"Authorization": f"Bearer {access_token}"}) assert response.status_code == 200
def execute(agreement_id, compute_ddo, workflow_ddo, consumer_account, gateway, index, config): """ :param agreement_id: :param workflow_ddo: :param consumer_account: :param index: :return: the id of the compute job """ service_endpoint = ServiceAgreement.from_ddo( ServiceTypes.CLOUD_COMPUTE, compute_ddo).service_endpoint response = gateway.execute_compute_service(agreement_id, service_endpoint, consumer_account, workflow_ddo, config) return response.json()["workflowId"]
def place_order(provider_account, ddo, consumer_account, service_type=ServiceTypes.ASSET_ACCESS): keeper = keeper_instance() agreement_id = ServiceAgreement.create_new_agreement_id() if service_type == ServiceTypes.ASSET_ACCESS: agreement_template = keeper.access_template elif service_type == ServiceTypes.ASSET_ACCESS_PROOF: agreement_template = keeper.access_proof_template elif service_type == ServiceTypes.NFT_SALES: agreement_template = keeper.nft_sales_template elif service_type == ServiceTypes.CLOUD_COMPUTE: agreement_template = keeper.escrow_compute_execution_template else: raise NotImplementedError( "The agreement template could not be created.") publisher_address = provider_account.address service_agreement = ServiceAgreement.from_ddo(service_type, ddo) if service_type == ServiceTypes.ASSET_ACCESS_PROOF: consumer_pub = get_buyer_public_key() condition_ids = service_agreement.generate_agreement_condition_ids( agreement_id, ddo.asset_id, consumer_pub, keeper) else: condition_ids = service_agreement.generate_agreement_condition_ids( agreement_id, ddo.asset_id, consumer_account.address, keeper) time_locks = service_agreement.conditions_timelocks time_outs = service_agreement.conditions_timeouts agreement_template.create_agreement(agreement_id, ddo.asset_id, condition_ids, time_locks, time_outs, consumer_account.address, consumer_account) return agreement_id
def setup_agreements_environment(ddo_sample): consumer_acc = get_consumer_account() publisher_acc = get_publisher_account() keeper = Keeper.get_instance() ddo = ddo_sample ddo._did = DID.did({"0": generate_prefixed_id()}) keeper.did_registry.register( ddo.asset_id, checksum=Web3Provider.get_web3().toBytes(hexstr=ddo.asset_id), url='localhost:5000', account=publisher_acc, providers=None ) registered_ddo = ddo asset_id = registered_ddo.asset_id service_agreement = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo) agreement_id = ServiceAgreement.create_new_agreement_id() price = service_agreement.get_price() access_cond_id, lock_cond_id, escrow_cond_id = \ service_agreement.generate_agreement_condition_ids( agreement_id, asset_id, consumer_acc.address, publisher_acc.address, keeper ) return ( keeper, publisher_acc, consumer_acc, agreement_id, asset_id, price, service_agreement, (lock_cond_id, access_cond_id, escrow_cond_id), )
def setup_did_sales_agreements_environment(): consumer_acc = get_consumer_account() publisher_acc = get_publisher_account() keeper = Keeper.get_instance() ddo = get_ddo_did_sales_sample() did_seed = generate_prefixed_id() asset_id = keeper.did_registry.hash_did(did_seed, publisher_acc.address) ddo._did = DID.did(asset_id) keeper.did_registry.register( did_seed, checksum=Web3Provider.get_web3().toBytes(hexstr=ddo.asset_id), url='metadata:5000', account=publisher_acc, providers=None) service_agreement = ServiceAgreement.from_ddo(ServiceTypes.DID_SALES, ddo) agreement_id = ServiceAgreement.create_new_agreement_id() price = service_agreement.get_price() (access_cond_id, lock_cond_id, escrow_cond_id) = service_agreement.generate_agreement_condition_ids( agreement_id, asset_id, consumer_acc.address, keeper) return ( keeper, ddo, publisher_acc, consumer_acc, agreement_id, asset_id, price, service_agreement, (lock_cond_id, access_cond_id, escrow_cond_id), )
def test_access_proof(client, provider_account, consumer_account): for method in constants.ConfigSections.DECRYPTION_METHODS: ddo = get_proof_ddo(provider_account, providers=[provider_account.address], auth_service=method) # initialize an agreement agreement_id = place_order(provider_account, ddo, consumer_account, ServiceTypes.ASSET_ACCESS_PROOF) print(ddo.did) keeper = keeper_instance() index = 0 event = keeper.access_proof_template.subscribe_agreement_created( agreement_id, 15, None, (), wait=True, from_block=0) assert event, "Agreement event is not found, check the keeper node's logs" consumer_balance = keeper.token.get_token_balance( consumer_account.address) if consumer_balance < 50: keeper.dispenser.request_tokens(50 - consumer_balance, consumer_account) sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS_PROOF, ddo) lock_payment(agreement_id, ddo.asset_id, sa, amounts, receivers, consumer_account) event = keeper.lock_payment_condition.subscribe_condition_fulfilled( agreement_id, 15, None, (), wait=True, from_block=0) assert event, "Lock reward condition fulfilled event is not found, check the keeper node's logs" # Consume using url index # generate the grant token grant_token = generate_access_proof_grant_token( consumer_account, agreement_id, ddo.did, get_buyer_secret_key(), "/access-proof") # request access token response = client.post("/api/v1/gateway/services/oauth/token", data={ "grant_type": NeverminedJWTBearerGrant.GRANT_TYPE, "assertion": grant_token }) access_token = response.get_json()["access_token"] agreement = keeper.agreement_manager.get_agreement(agreement_id) cond_ids = agreement.condition_ids assert keeper.condition_manager.get_condition_state( cond_ids[0]) == ConditionState.Fulfilled.value assert keeper.condition_manager.get_condition_state( cond_ids[1]) == ConditionState.Fulfilled.value assert keeper.condition_manager.get_condition_state( cond_ids[2]) == ConditionState.Fulfilled.value endpoint = BaseURLs.ASSETS_URL + '/access-proof/%s/%d' % (agreement_id, index) response = client.get( endpoint, headers={"Authorization": f"Bearer {access_token}"}) assert response.status == '200 OK' assert len( keeper.did_registry.get_provenance_method_events( 'USED', did_bytes=did_to_id_bytes(ddo.did))) == 1
def test_sign_agreement(publisher_instance, consumer_instance, registered_ddo): # point consumer_instance's Gateway mock to the publisher's nevermined instance Gateway.set_http_client( GatewayMock(publisher_instance, publisher_instance.main_account)) consumer_acc = consumer_instance.main_account keeper = Keeper.get_instance() publisher_acc = publisher_instance.main_account did = registered_ddo.did asset_id = registered_ddo.asset_id ddo = consumer_instance.assets.resolve(did) service_agreement = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo) price = service_agreement.get_price() # Give consumer some tokens keeper.dispenser.request_vodkas(price * 2, consumer_acc) agreement_id, signature = consumer_instance.agreements.prepare( did, consumer_acc, ServiceTypesIndices.DEFAULT_ACCESS_INDEX) success = publisher_instance.agreements.create( did, ServiceTypesIndices.DEFAULT_ACCESS_INDEX, agreement_id, consumer_acc.address, publisher_acc) assert success, 'createAgreement failed.' # Verify condition types (condition contracts) agreement_values = keeper.agreement_manager.get_agreement(agreement_id) assert agreement_values.did == asset_id, '' cond_types = keeper.access_template.get_condition_types() for i, cond_id in enumerate(agreement_values.condition_ids): cond = keeper.condition_manager.get_condition(cond_id) assert cond.type_ref == cond_types[i] access_cond_id, lock_cond_id, escrow_cond_id = agreement_values.condition_ids # Fulfill lock_payment_condition is done automatically when create agreement is done correctly assert 2 == keeper.condition_manager.get_condition_state(lock_cond_id), '' assert 1 == keeper.condition_manager.get_condition_state( access_cond_id), '' assert 1 == keeper.condition_manager.get_condition_state( escrow_cond_id), '' # Fulfill access_condition tx_hash = keeper.access_condition.fulfill(agreement_id, asset_id, consumer_acc.address, publisher_acc) keeper.access_condition.get_tx_receipt(tx_hash) assert 2 == keeper.condition_manager.get_condition_state( access_cond_id), '' event = keeper.access_condition.subscribe_condition_fulfilled( agreement_id, 10, log_event(keeper.access_condition.FULFILLED_EVENT), (), wait=True) assert event, 'no event for AccessSecretStoreCondition.Fulfilled' # Fulfill escrow_payment_condition amounts = service_agreement.get_amounts_int() receivers = service_agreement.get_receivers() tx_hash = keeper.escrow_payment_condition.fulfill( agreement_id, asset_id, amounts, receivers, keeper.escrow_payment_condition.address, lock_cond_id, access_cond_id, publisher_acc) keeper.escrow_payment_condition.get_tx_receipt(tx_hash) assert 2 == keeper.condition_manager.get_condition_state( escrow_cond_id), '' event = keeper.escrow_payment_condition.subscribe_condition_fulfilled( agreement_id, 10, log_event(keeper.escrow_payment_condition.FULFILLED_EVENT), (), wait=True) assert event, 'no event for EscrowReward.Fulfilled' publisher_instance.assets.retire(did)
def nft_transfer(): """Allows the provider transfer and release the rewards. swagger_from_file: docs/nft_transfer.yml """ required_attributes = [ 'agreementId', 'nftHolder', 'nftReceiver', 'nftAmount' ] data = request.json msg, status = check_required_attributes(required_attributes, data, 'nft-transfer') if msg: return msg, status agreement_id = data.get('agreementId') nft_holder_address = data.get('nftHolder') nft_receiver_address = data.get('nftReceiver') nft_amount = data.get('nftAmount') keeper = keeper_instance() agreement = keeper.agreement_manager.get_agreement(agreement_id) did = id_to_did(agreement.did) ddo = DIDResolver(keeper.did_registry).resolve(did) try: ServiceAgreement.from_ddo(ServiceTypes.NFT_SALES, ddo) except ValueError as e: logger.error('nft-sales service not found on ddo for %s', did) return str(e), 400 (lock_payment_condition_id, nft_transfer_condition_id, escrow_payment_condition_id) = agreement.condition_ids if not is_nft_holder(keeper, agreement.did, nft_amount, nft_holder_address): msg = f'Holder {nft_holder_address} does not have enough NFTs to transfer' logger.warning(msg) return msg, 406 if not is_lock_payment_condition_fulfilled(lock_payment_condition_id, keeper): msg = f'lockPayment condition for agreement_id={agreement_id} is not fulfilled' logger.warning(msg) return msg, 402 if not is_nft_transfer_approved(nft_holder_address, get_provider_account().address, keeper): msg = f'Gateway ({get_provider_account().address}) is not approved to transfer nfts from {nft_holder_address}' logger.warning(msg) return msg, 405 # fulfill transferNFT condition if not is_nft_transfer_condition_fulfilled(nft_transfer_condition_id, keeper): logger.debug('NFTTransfer condition not fulfilled') result = fulfill_for_delegate_nft_transfer_condition( agreement_id, agreement.did, Web3.toChecksumAddress(nft_holder_address), Web3.toChecksumAddress(nft_receiver_address), nft_amount, lock_payment_condition_id, keeper) if result is False: msg = f'There was an error fulfilling the NFTTransfer condition for agreement_id={agreement_id}' logger.error(msg) return msg, 500 # fulfill escrowPayment condition if not is_escrow_payment_condition_fulfilled(escrow_payment_condition_id, keeper): logger.debug('EscrowPayment condition not fulfilled') result = fulfill_escrow_payment_condition( keeper, agreement_id, [ nft_transfer_condition_id, lock_payment_condition_id, escrow_payment_condition_id ], ddo, get_provider_account(), service_type=ServiceTypes.NFT_SALES) if result is False: msg = f'There was an error fulfilling the EscrowPayment condition for agreement_id={agreement_id}' logger.error(msg) return msg, 500 return 'success', 200
def test_nfts_flow(publisher_instance_no_init, consumer_instance_no_init): config = ExampleConfig.get_config() ConfigProvider.set_config(config) keeper = Keeper.get_instance() pub_acc = get_publisher_account() # Register ddo ddo = get_registered_ddo_nft(publisher_instance_no_init, pub_acc) asset_id = ddo.asset_id nft_amounts = 1 assert isinstance(ddo, DDO) consumer_account = get_consumer_account() consumer_instance_no_init.accounts.request_tokens(consumer_account, 100) service_sales = ddo.get_service(service_type=ServiceTypes.NFT_SALES) sa_sales = ServiceAgreement.from_service_dict( service_sales.as_dictionary()) amounts = sa_sales.get_amounts_int() receivers = sa_sales.get_receivers() number_nfts = sa_sales.get_number_nfts() token_address = keeper.token.address sales_agreement_id = consumer_instance_no_init.assets.order( ddo.did, sa_sales.index, consumer_account, consumer_account) sales_agreement = keeper.agreement_manager.get_agreement( sales_agreement_id) assert sales_agreement.did == asset_id, '' lock_cond_id = sales_agreement.condition_ids[0] access_cond_id = sales_agreement.condition_ids[1] escrow_cond_id = sales_agreement.condition_ids[2] # transfer the nft keeper.transfer_nft_condition.fulfill(sales_agreement_id, asset_id, consumer_account.address, nft_amounts, lock_cond_id, pub_acc) # escrow payment keeper.escrow_payment_condition.fulfill( sales_agreement_id, asset_id, amounts, receivers, keeper.escrow_payment_condition.address, token_address, lock_cond_id, access_cond_id, pub_acc) assert keeper.condition_manager.get_condition_state(lock_cond_id) == 2, '' assert keeper.condition_manager.get_condition_state( access_cond_id) == 2, '' assert keeper.condition_manager.get_condition_state( escrow_cond_id) == 2, '' assert keeper.did_registry.balance(consumer_account.address, asset_id) >= number_nfts # CHECK ACCESS CREATING THE AGREEMENT nft_access_service_agreement = ServiceAgreement.from_ddo( ServiceTypes.NFT_ACCESS, ddo) sa_access = ddo.get_service(service_type=ServiceTypes.NFT_ACCESS) nft_access_agreement_id = consumer_instance_no_init.assets.order( ddo.did, sa_access.index, consumer_account, consumer_account) event = keeper.nft_access_template.subscribe_agreement_created( nft_access_agreement_id, 10, log_event(keeper.nft_access_template.AGREEMENT_CREATED_EVENT), (), wait=True) assert event, 'no event for AgreementCreated ' time.sleep(3) keeper.nft_holder_condition.fulfill(nft_access_agreement_id, asset_id, consumer_account.address, number_nfts, consumer_account) time.sleep(3) keeper.nft_access_condition.fulfill(nft_access_agreement_id, asset_id, consumer_account.address, pub_acc) time.sleep(3) access_agreement = keeper.agreement_manager.get_agreement( nft_access_agreement_id) assert access_agreement.did == asset_id, '' nft_holder_cond_id = access_agreement.condition_ids[0] nft_access_cond_id = access_agreement.condition_ids[1] assert keeper.condition_manager.get_condition_state( nft_access_cond_id) == 2, '' assert keeper.condition_manager.get_condition_state( nft_holder_cond_id) == 2, '' # AND HERE TESTING WITHOUT CREATING THE AGREEMENT service_access = ddo.get_service(service_type=ServiceTypes.NFT_ACCESS) no_agreement_id = '0x' assert consumer_instance_no_init.assets.access( no_agreement_id, ddo.did, service_access.index, consumer_account, config.downloads_path, service_type=ServiceTypes.NFT_ACCESS) # AND HERE CHECKING CREATING AN AGREEMENT FIRST nft_access_service_agreement = ServiceAgreement.from_ddo( ServiceTypes.NFT_ACCESS, ddo) nft_access_agreement_id = ServiceAgreement.create_new_agreement_id() (nft_access_cond_id, nft_holder_cond_id ) = nft_access_service_agreement.generate_agreement_condition_ids( nft_access_agreement_id, asset_id, consumer_account.address, keeper) keeper.nft_access_template.create_agreement( nft_access_agreement_id, asset_id, [nft_holder_cond_id, nft_access_cond_id], nft_access_service_agreement.conditions_timelocks, nft_access_service_agreement.conditions_timeouts, consumer_account.address, pub_acc) event = keeper.nft_access_template.subscribe_agreement_created( nft_access_agreement_id, 10, log_event(keeper.nft_access_template.AGREEMENT_CREATED_EVENT), (), wait=True) assert event, 'no event for AgreementCreated ' # This is because in this test the gateway is executed using the same account than the consumer keeper.did_registry.add_provider(asset_id, consumer_account.address, pub_acc) time.sleep(3) assert consumer_instance_no_init.assets.access( nft_access_agreement_id, ddo.did, service_access.index, consumer_account, config.downloads_path, index=0, service_type=ServiceTypes.NFT_ACCESS)
def test_process_pending_agreements(keeper, web3, storage_path, provider_account): start_time = 0 ddo = get_registered_ddo(provider_account, providers=[provider_account.address]) did = ddo.did consumer = get_consumer_account() block_number = web3.eth.blockNumber block_number = block_number - 10 if block_number > 10 else block_number metadata = ddo.metadata encrypted_files = metadata['encryptedFiles'] sa = ServiceAgreement.from_ddo('access', ddo) agr_1 = place_order(provider_account, ddo, consumer) agr_2 = place_order(provider_account, ddo, consumer) agr_3 = place_order(provider_account, ddo, consumer) pending_agreements = { agr_1: [ did, 3, sa.get_price(), encrypted_files, start_time, consumer.address, block_number, 'access' ], agr_2: [ did, 3, sa.get_price(), encrypted_files, start_time + 3000, consumer.address, block_number, 'access' ], agr_3: [ did, 3, sa.get_price(), encrypted_files, start_time + 10000, consumer.address, block_number, 'access' ] } conditions = { agr_1: { 'accessSecretStore': 1, 'lockReward': 2, 'escrowReward': 1 }, agr_2: { 'accessSecretStore': 1, 'lockReward': 1, 'escrowReward': 1 }, agr_3: { 'accessSecretStore': 2, 'lockReward': 2, 'escrowReward': 1 } } balance = keeper.token.get_token_balance(consumer.address) / (2**18) if balance < 20: keeper.dispenser.request_tokens(100, consumer) lock_reward(agr_1, sa, consumer) lock_reward(agr_3, sa, consumer) grant_access(agr_3, ddo, consumer, provider_account) event = keeper.access_secret_store_condition.subscribe_condition_fulfilled( agr_3, 35, None, (), wait=True) if not event: # check status cond_to_status = get_conditions_status(agr_3) print(f'agr_3 condition status: {cond_to_status}') if cond_to_status['accessSecretStore'] != 2: raise AssertionError(f'grant access failed for agreement {agr_3}') events_monitor = ProviderEventsMonitor(keeper, web3, storage_path, provider_account) events_monitor.process_pending_agreements(pending_agreements, conditions) keeper.access_secret_store_condition.subscribe_condition_fulfilled( agr_1, 15, None, (), wait=True) keeper.escrow_reward_condition.subscribe_condition_fulfilled(agr_1, 15, None, (), wait=True) keeper.escrow_reward_condition.subscribe_condition_fulfilled(agr_3, 15, None, (), wait=True) # check status of all agreements for agr_id in (agr_1, agr_3): cond_to_status = get_conditions_status(agr_1) assert [2, 2, 2] == list(cond_to_status.values()), \ f'agr_id {agr_id}: some conditions were not fulfilled or ' \ f'do not match the expected status. Conditions status are: {cond_to_status}' events_monitor.start_agreement_events_monitor() lock_reward(agr_2, sa, consumer) keeper.access_secret_store_condition.subscribe_condition_fulfilled( agr_2, 15, None, (), wait=True) keeper.escrow_reward_condition.subscribe_condition_fulfilled(agr_2, 15, None, (), wait=True) cond_to_status = get_conditions_status(agr_2) assert [2, 2, 2] == list(cond_to_status.values()), \ f'agr_id {agr_id}: some conditions were not fulfilled or ' \ f'do not match the expected status. Conditions status are: {cond_to_status}' events_monitor.stop_monitor() time.sleep(2)
def test_nft_transfer(client, provider_account, consumer_account, publisher_account): print('PROVIDER_ACCOUNT= ' + provider_account.address) print('PUBLISHER_ACCOUNT= ' + publisher_account.address) print('CONSUMER_ACCOUNT= ' + consumer_account.address) keeper = keeper_instance() ddo = get_nft_ddo(publisher_account, providers=[provider_account.address]) asset_id = ddo.asset_id nft_amounts = 1 agreement_id = ServiceAgreement.create_new_agreement_id() print('NFT_SALES_DID: ' + asset_id) nft_sales_service_agreement = ServiceAgreement.from_ddo( ServiceTypes.NFT_SALES, ddo) (transfer_nft_condition_id, lock_payment_condition_id, escrow_payment_condition_id ) = nft_sales_service_agreement.generate_agreement_condition_ids( agreement_id, asset_id, consumer_account.address, keeper) keeper.nft_sales_template.create_agreement( agreement_id, asset_id, [ lock_payment_condition_id, transfer_nft_condition_id, escrow_payment_condition_id ], nft_sales_service_agreement.conditions_timelocks, nft_sales_service_agreement.conditions_timeouts, consumer_account.address, consumer_account) event = keeper.nft_sales_template.subscribe_agreement_created(agreement_id, 15, None, (), wait=True, from_block=0) assert event, "Agreement event is not found, check the keeper node's logs" agreement = keeper.agreement_manager.get_agreement(agreement_id) cond_ids = agreement.condition_ids keeper.token.token_approve(keeper.lock_payment_condition.address, nft_sales_service_agreement.get_price(), consumer_account) keeper.dispenser.request_tokens(50, consumer_account) lock_payment(agreement_id, ddo.asset_id, nft_sales_service_agreement, nft_sales_service_agreement.get_amounts_int(), nft_sales_service_agreement.get_receivers(), consumer_account) event = keeper.lock_payment_condition.subscribe_condition_fulfilled( agreement_id, 15, None, (), wait=True, from_block=0) assert event, "Lock reward condition fulfilled event is not found, check the keeper " \ "node's logs" keeper.nft_upgradeable.set_approval_for_all(get_provider_account().address, True, publisher_account) time.sleep(10) is_approved = keeper.nft_upgradeable.is_approved_for_all( publisher_account.address, provider_account.address) assert is_approved is True response = client.post(BaseURLs.ASSETS_URL + '/nft-transfer', json={ 'agreementId': agreement_id, 'nftHolder': publisher_account.address, 'nftReceiver': consumer_account.address, 'nftAmount': nft_amounts }) assert response.status_code == 200 assert keeper.condition_manager.get_condition_state( cond_ids[0]) == ConditionState.Fulfilled.value assert keeper.condition_manager.get_condition_state( cond_ids[1]) == ConditionState.Fulfilled.value assert keeper.condition_manager.get_condition_state( cond_ids[2]) == ConditionState.Fulfilled.value