From f0404f3204b44fd6042edd26c2ca87a0cae083c8 Mon Sep 17 00:00:00 2001 From: Bogdan Fazakas Date: Thu, 3 Jun 2021 12:43:15 +0300 Subject: [PATCH 1/7] added ddo object param to function that expect did and asset resolve is called --- src/datatokens/Datatokens.ts | 5 +- src/ocean/Assets.ts | 14 ++- src/ocean/Compute.ts | 93 +++++++++++++----- src/provider/Provider.ts | 15 ++- src/utils/ConfigHelper.ts | 20 +++- src/utils/SubscribablePromise.ts | 4 +- test/integration/ComputeFlow.test.ts | 138 +++++++++++++++++++-------- 7 files changed, 206 insertions(+), 83 deletions(-) diff --git a/src/datatokens/Datatokens.ts b/src/datatokens/Datatokens.ts index bd625424..1fd3ac39 100644 --- a/src/datatokens/Datatokens.ts +++ b/src/datatokens/Datatokens.ts @@ -47,7 +47,10 @@ export class DataTokens { * Generate new datatoken name & symbol from a word list * @return {<{ name: String; symbol: String }>} datatoken name & symbol. Produces e.g. "Endemic Jellyfish Token" & "ENDJEL-45" */ - public generateDtName(wordList?: { nouns: string[]; adjectives: string[] }): { + public generateDtName(wordList?: { + nouns: string[] + adjectives: string[] + }): { name: string symbol: string } { diff --git a/src/ocean/Assets.ts b/src/ocean/Assets.ts index a2fc55f8..a4e8f209 100644 --- a/src/ocean/Assets.ts +++ b/src/ocean/Assets.ts @@ -452,11 +452,18 @@ export class Assets extends Instantiable { serviceType: string, consumerAddress: string, serviceIndex = -1, - serviceEndpoint: string + serviceEndpoint: string, + ddo?: DDO ): Promise { const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) - const res = await provider.initialize(did, serviceIndex, serviceType, consumerAddress) + const res = await provider.initialize( + did, + serviceIndex, + serviceType, + consumerAddress, + ddo + ) if (res === null) return null const providerData = JSON.parse(res) return providerData @@ -501,7 +508,8 @@ export class Assets extends Instantiable { serviceType, payerAddress, serviceIndex, - service.serviceEndpoint + service.serviceEndpoint, + ddo ) if (!providerData) throw new Error( diff --git a/src/ocean/Compute.ts b/src/ocean/Compute.ts index 4c7c4f9d..6870a68e 100644 --- a/src/ocean/Compute.ts +++ b/src/ocean/Compute.ts @@ -105,6 +105,7 @@ export class Compute extends Instantiable { * @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset. * @param {MetaData} algorithmMeta Metadata about the algorithm being run if `algorithm` is being used. This is ignored when `algorithmDid` is specified. * @param {Output} output Define algorithm output publishing. Publishing the result of a compute job is turned off by default. + * @param {DDO} ddo If undefined then the ddo will be fetched by did * @return {Promise} Returns compute job ID under status.jobId */ public async start( @@ -116,10 +117,14 @@ export class Compute extends Instantiable { output?: ComputeOutput, serviceIndex?: string, serviceType?: string, - additionalInputs?: ComputeInput[] + additionalInputs?: ComputeInput[], + ddo?: DDO ): Promise { output = this.checkOutput(consumerAccount, output) - const ddo = await this.ocean.assets.resolve(did) + if (!ddo) { + ddo = await this.ocean.assets.resolve(did) + if (!ddo) throw new Error(`Couldn't resolve the did ${did}`) + } const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service if (did && txId) { @@ -147,14 +152,19 @@ export class Compute extends Instantiable { * @param {Account} consumerAccount The account of the consumer ordering the service. * @param {string} did Decentralized identifier. * @param {string} jobId The ID of the compute job to be stopped + * @param {DDO} ddo If undefined then the ddo will be fetched by did * @return {Promise} Returns the new status of a job */ public async stop( consumerAccount: Account, did: string, - jobId: string + jobId: string, + ddo?: DDO ): Promise { - const ddo = await this.ocean.assets.resolve(did) + if (!ddo) { + ddo = await this.ocean.assets.resolve(did) + if (!ddo) throw new Error(`Couldn't resolve the did ${did}`) + } const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) @@ -169,14 +179,19 @@ export class Compute extends Instantiable { * @param {Account} consumerAccount The account of the consumer ordering the service. * @param {string} did Decentralized identifier. * @param {string} jobId The ID of the compute job to be stopped + * @param {DDO} ddo If undefined then the ddo will be fetched by did * @return {Promise} Returns the new status of a job */ public async delete( consumerAccount: Account, did: string, - jobId: string + jobId: string, + ddo?: DDO ): Promise { - const ddo = await this.ocean.assets.resolve(did) + if (!ddo) { + ddo = await this.ocean.assets.resolve(did) + if (!ddo) throw new Error(`Couldn't resolve the did ${did}`) + } const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) @@ -243,14 +258,19 @@ export class Compute extends Instantiable { * @param {Account} consumerAccount The account of the consumer ordering the service. * @param {string} did Decentralized identifier. * @param {string} jobId The ID of the compute job to be stopped. + * @param {DDO} ddo If undefined then the ddo will be fetched by did * @return {Promise} Returns the DDO of the result asset. */ public async result( consumerAccount: Account, did: string, - jobId: string + jobId: string, + ddo?: DDO ): Promise { - const ddo = await this.ocean.assets.resolve(did) + if (!ddo) { + ddo = await this.ocean.assets.resolve(did) + if (!ddo) throw new Error(`Couldn't resolve the did ${did}`) + } const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) @@ -401,6 +421,8 @@ export class Compute extends Instantiable { * @param {string} serviceIndex The Service index * @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset. * @param {MetaData} algorithmMeta Metadata about the algorithm being run if `algorithm` is being used. This is ignored when `algorithmDid` is specified. + * @param {DDO} datasetDdo Dataset DDO object. If undefined then the ddo will be fetched by did + * @param {DDO} algorithmDDO Algorithm DDO object. If undefined then the ddo will be fetched by did * @return {Promise} True is you can order this * * Note: algorithmDid and algorithmMeta are optional, but if they are not passed, @@ -410,10 +432,15 @@ export class Compute extends Instantiable { public async isOrderable( datasetDid: string, serviceIndex: number, - algorithm: ComputeAlgorithm + algorithm: ComputeAlgorithm, + datasetDdo?: DDO, + algorithmDDO?: DDO ): Promise { - const ddo: DDO = await this.ocean.assets.resolve(datasetDid) - const service: Service = ddo.findServiceById(serviceIndex) + if (!datasetDdo) { + datasetDdo = await this.ocean.assets.resolve(datasetDid) + if (!datasetDdo) throw new Error(`Couldn't resolve the did ${datasetDid}`) + } + const service: Service = datasetDdo.findServiceById(serviceIndex) if (!service) return false if (service.type === 'compute') { if (algorithm.meta) { @@ -426,8 +453,14 @@ export class Compute extends Instantiable { if (algorithm.did) { // check if both have compute services and then if they are served by the same provider if (algorithm.serviceIndex) { - const algoDDO: DDO = await this.ocean.assets.resolve(algorithm.did) - const algoService: Service = algoDDO.findServiceById(algorithm.serviceIndex) + if (!algorithmDDO) { + algorithmDDO = await this.ocean.assets.resolve(algorithm.did) + if (!algorithmDDO) + throw new Error(`Couldn't resolve the did ${algorithm.did}`) + } + const algoService: Service = algorithmDDO.findServiceById( + algorithm.serviceIndex + ) if (algoService && algoService.type === 'compute') { // since both dataset & algo services are compute, we need to check if they are served by the same provider const algoProvider = await Provider.getInstance(this.instanceConfig) @@ -511,18 +544,28 @@ export class Compute extends Instantiable { algorithm: ComputeAlgorithm, mpAddress?: string, computeAddress?: string, + datasetDdo?: DDO, searchPreviousOrders = true ): SubscribablePromise { return new SubscribablePromise(async (observer) => { // first check if we can order this - const allowed = await this.isOrderable(datasetDid, serviceIndex, algorithm) + const allowed = await this.isOrderable( + datasetDid, + serviceIndex, + algorithm, + datasetDdo + ) if (!allowed) throw new Error( `Dataset order failed, dataset is not orderable with the specified algorithm` ) - const ddo: DDO = await this.ocean.assets.resolve(datasetDid) + + if (!datasetDdo) { + datasetDdo = await this.ocean.assets.resolve(datasetDid) + if (!datasetDdo) throw new Error(`Couldn't resolve the did ${datasetDid}`) + } // const service: Service = ddo.findServiceByType('compute') - const service: Service = ddo.findServiceById(serviceIndex) + const service: Service = datasetDdo.findServiceById(serviceIndex) if (!service) throw new Error(`Dataset order failed, Could not find service for the DDO`) try { @@ -631,8 +674,9 @@ export class Compute extends Instantiable { } if (typeof ddo.service[serviceIndex] === 'undefined') return null if (ddo.service[serviceIndex].type !== 'compute') return null - ddo.service[serviceIndex].attributes.main.privacy.allowAllPublishedAlgorithms = - newState + ddo.service[ + serviceIndex + ].attributes.main.privacy.allowAllPublishedAlgorithms = newState return ddo } @@ -747,12 +791,13 @@ export class Compute extends Instantiable { if (ddo.service[serviceIndex].type !== 'compute') return ddo if (!ddo.service[serviceIndex].attributes.main.privacy.publisherTrustedAlgorithms) return ddo - ddo.service[serviceIndex].attributes.main.privacy.publisherTrustedAlgorithms = - ddo.service[serviceIndex].attributes.main.privacy.publisherTrustedAlgorithms.filter( - function (el) { - return el.did !== algoDid - } - ) + ddo.service[ + serviceIndex + ].attributes.main.privacy.publisherTrustedAlgorithms = ddo.service[ + serviceIndex + ].attributes.main.privacy.publisherTrustedAlgorithms.filter(function (el) { + return el.did !== algoDid + }) return ddo } } diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index 00f26ca1..959f9358 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -189,15 +189,12 @@ export class Provider extends Instantiable { did: string, serviceIndex: number, serviceType: string, - consumerAddress: string + consumerAddress: string, + ddo?: DDO ): Promise { - let DDO: DDO - - try { - DDO = await this.ocean.assets.resolve(did) - } catch (e) { - this.logger.error(e) - throw new Error('Failed to resolve DID') + if (!ddo) { + ddo = await this.ocean.assets.resolve(did) + if (!ddo) throw new Error(`Couldn't resolve the did ${did}`) } let initializeUrl = this.getInitializeEndpoint() ? this.getInitializeEndpoint().urlPath @@ -206,7 +203,7 @@ export class Provider extends Instantiable { initializeUrl += `?documentId=${did}` initializeUrl += `&serviceId=${serviceIndex}` initializeUrl += `&serviceType=${serviceType}` - initializeUrl += `&dataToken=${DDO.dataToken}` + initializeUrl += `&dataToken=${ddo.dataToken}` initializeUrl += `&consumerAddress=${consumerAddress}` try { const response = await this.ocean.utils.fetch.get(initializeUrl) diff --git a/src/utils/ConfigHelper.ts b/src/utils/ConfigHelper.ts index c9193c51..05db7929 100644 --- a/src/utils/ConfigHelper.ts +++ b/src/utils/ConfigHelper.ts @@ -150,8 +150,14 @@ export class ConfigHelper { // use the defaults first let configAddresses: Partial if (DefaultContractsAddresses[network]) { - const { DTFactory, BFactory, FixedRateExchange, Dispenser, Metadata, Ocean } = - DefaultContractsAddresses[network] + const { + DTFactory, + BFactory, + FixedRateExchange, + Dispenser, + Metadata, + Ocean + } = DefaultContractsAddresses[network] configAddresses = { factoryAddress: DTFactory, poolFactoryAddress: BFactory, @@ -172,8 +178,14 @@ export class ConfigHelper { 'utf8' ) ) - const { DTFactory, BFactory, FixedRateExchange, Dispenser, Metadata, Ocean } = - data[network] + const { + DTFactory, + BFactory, + FixedRateExchange, + Dispenser, + Metadata, + Ocean + } = data[network] configAddresses = { factoryAddress: DTFactory, poolFactoryAddress: BFactory, diff --git a/src/utils/SubscribablePromise.ts b/src/utils/SubscribablePromise.ts index 5a72e618..3e0c8fe0 100644 --- a/src/utils/SubscribablePromise.ts +++ b/src/utils/SubscribablePromise.ts @@ -17,7 +17,9 @@ export class SubscribablePromise { setTimeout(() => this.init(executor), 1) } - public subscribe(onNext: (next: T) => void): { + public subscribe( + onNext: (next: T) => void + ): { unsubscribe: () => boolean } { return this.observer.subscribe(onNext) diff --git a/test/integration/ComputeFlow.test.ts b/test/integration/ComputeFlow.test.ts index fbdb7589..2db1eef5 100644 --- a/test/integration/ComputeFlow.test.ts +++ b/test/integration/ComputeFlow.test.ts @@ -104,7 +104,8 @@ describe('Compute flow', () => { language: 'js', format: 'docker-image', version: '0.1', - url: 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + url: + 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', container: { entrypoint: 'node $ALGO', image: 'node', @@ -249,7 +250,8 @@ describe('Compute flow', () => { license: 'CC-BY', files: [ { - url: 'https://raw.githubusercontent.com/tbertinmahieux/MSongsDB/master/Tasks_Demos/CoverSongs/shs_dataset_test.txt', + url: + 'https://raw.githubusercontent.com/tbertinmahieux/MSongsDB/master/Tasks_Demos/CoverSongs/shs_dataset_test.txt', checksum: 'efb2c764274b745f5fc37f97c6b0e764', contentLength: '4535431', contentType: 'text/csv', @@ -485,7 +487,8 @@ describe('Compute flow', () => { license: 'CC-BY', files: [ { - url: 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + url: + 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', contentType: 'text/js', encoding: 'UTF-8' } @@ -537,7 +540,8 @@ describe('Compute flow', () => { license: 'CC-BY', files: [ { - url: 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + url: + 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', contentType: 'text/js', encoding: 'UTF-8' } @@ -598,7 +602,8 @@ describe('Compute flow', () => { license: 'CC-BY', files: [ { - url: 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + url: + 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', contentType: 'text/js', encoding: 'UTF-8' } @@ -662,7 +667,8 @@ describe('Compute flow', () => { license: 'CC-BY', files: [ { - url: 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + url: + 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', contentType: 'text/js', encoding: 'UTF-8' } @@ -840,7 +846,8 @@ describe('Compute flow', () => { const allowed = await ocean.compute.isOrderable( ddo.id, computeService.index, - algoDefinition + algoDefinition, + ddo ) assert(allowed === true) computeOrderId = await ocean.compute.orderAsset( @@ -849,7 +856,8 @@ describe('Compute flow', () => { computeService.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + ddo ) assert(computeOrderId != null, 'computeOrderId === null') const response = await ocean.compute.start( @@ -860,7 +868,9 @@ describe('Compute flow', () => { algoDefinition, output, `${computeService.index}`, - computeService.type + computeService.type, + undefined, + ddo ) assert(response, 'Compute error') jobId = response.jobId @@ -918,7 +928,7 @@ describe('Compute flow', () => { }) it('Bob should stop compute job', async () => { assert(jobId != null, 'Jobid is null') - await ocean.compute.stop(bob, ddo.id, jobId) + await ocean.compute.stop(bob, ddo.id, jobId, ddo) const response = await ocean.compute.status(bob, ddo.id, undefined, undefined, jobId) // TODO: typings say that `stopreq` does not exist assert((response[0] as any).stopreq === 1, 'Response.stopreq is invalid') @@ -941,7 +951,8 @@ describe('Compute flow', () => { service1.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + datasetNoRawAlgo ) assert(order === null, 'Order should be null') } catch (error) { @@ -964,7 +975,8 @@ describe('Compute flow', () => { const allowed = await ocean.compute.isOrderable( datasetWithTrustedAlgo.id, service1.index, - algoDefinition + algoDefinition, + datasetWithTrustedAlgo ) assert(allowed === false) @@ -976,7 +988,8 @@ describe('Compute flow', () => { service1.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + datasetWithTrustedAlgo ) assert(order === null, 'Order should be null') } catch (error) { @@ -995,7 +1008,9 @@ describe('Compute flow', () => { const allowed = await ocean.compute.isOrderable( ddo.id, computeService.index, - algoDefinition + algoDefinition, + ddo, + algorithmAsset ) assert(allowed === false) @@ -1006,7 +1021,8 @@ describe('Compute flow', () => { computeService.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + ddo ) assert(order === null, 'Order should be null') } catch (error) { @@ -1081,8 +1097,9 @@ describe('Compute flow', () => { algorithmAssetRemoteProviderWithCompute != null, 'algorithmAsset should not be null' ) - const serviceAlgo = - algorithmAssetRemoteProviderWithCompute.findServiceByType('compute') + const serviceAlgo = algorithmAssetRemoteProviderWithCompute.findServiceByType( + 'compute' + ) assert(serviceAlgo != null, 'serviceAlgo should not be null') // get the compute address first computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) @@ -1094,7 +1111,9 @@ describe('Compute flow', () => { const allowed = await ocean.compute.isOrderable( ddo.id, computeService.index, - algoDefinition + algoDefinition, + ddo, + algorithmAssetRemoteProviderWithCompute ) assert(allowed === false) try { @@ -1104,7 +1123,8 @@ describe('Compute flow', () => { computeService.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + ddo ) assert(order === null, 'Order should be null') } catch (error) { @@ -1127,7 +1147,9 @@ describe('Compute flow', () => { const allowed = await ocean.compute.isOrderable( ddo.id, computeService.index, - algoDefinition + algoDefinition, + ddo, + algorithmAssetwithCompute ) assert(allowed === true) const order = await ocean.compute.orderAsset( @@ -1136,7 +1158,8 @@ describe('Compute flow', () => { computeService.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + ddo ) assert(order != null, 'Order should not be null') // order the algorithm @@ -1159,7 +1182,9 @@ describe('Compute flow', () => { algoDefinition, output, `${computeService.index}`, - computeService.type + computeService.type, + undefined, + ddo ) assert(response, 'Compute error') jobId = response.jobId @@ -1183,7 +1208,9 @@ describe('Compute flow', () => { const allowed = await ocean.compute.isOrderable( ddo.id, computeService.index, - algoDefinition + algoDefinition, + ddo, + algorithmAsset ) assert(allowed === true) const order = await ocean.compute.orderAsset( @@ -1192,7 +1219,8 @@ describe('Compute flow', () => { computeService.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + ddo ) assert(order != null, 'Order should not be null') // order the algorithm @@ -1215,7 +1243,9 @@ describe('Compute flow', () => { algoDefinition, output, `${computeService.index}`, - computeService.type + computeService.type, + undefined, + ddo ) assert(response, 'Compute error') jobId = response.jobId @@ -1242,7 +1272,9 @@ describe('Compute flow', () => { const allowed = await ocean.compute.isOrderable( ddo.id, computeService.index, - algoDefinition + algoDefinition, + ddo, + algorithmAssetRemoteProvider ) assert(allowed === true) const order = await ocean.compute.orderAsset( @@ -1251,7 +1283,8 @@ describe('Compute flow', () => { computeService.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + ddo ) assert(order != null, 'Order should not be null') const orderalgo = await ocean.compute.orderAlgorithm( @@ -1273,7 +1306,9 @@ describe('Compute flow', () => { algoDefinition, output, `${computeService.index}`, - computeService.type + computeService.type, + undefined, + ddo ) assert(response, 'Compute error') assert(response.status >= 1, 'Invalid response status') @@ -1296,7 +1331,9 @@ describe('Compute flow', () => { allowed = await ocean.compute.isOrderable( ddo.id, computeService.index, - algoDefinition + algoDefinition, + ddo, + algorithmAsset ) assert(allowed === true) const order = await ocean.compute.orderAsset( @@ -1305,7 +1342,8 @@ describe('Compute flow', () => { computeService.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + ddo ) assert(order != null, 'Order should not be null') // order the algo @@ -1324,7 +1362,8 @@ describe('Compute flow', () => { allowed = await ocean.compute.isOrderable( ddoAdditional1.id, inputOrder1Service.index, - algoDefinition + algoDefinition, + ddoAdditional1 ) assert(allowed === true) const inputOrder1 = await ocean.compute.orderAsset( @@ -1333,7 +1372,8 @@ describe('Compute flow', () => { inputOrder1Service.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + ddoAdditional1 ) assert(inputOrder1 != null, 'inputOrder1 should not be null') assert(ddoAdditional1 != null, 'ddoAdditional1 should not be null') @@ -1342,7 +1382,8 @@ describe('Compute flow', () => { allowed = await ocean.compute.isOrderable( ddoAdditional2.id, inputOrder2Service.index, - algoDefinition + algoDefinition, + ddoAdditional2 ) assert(allowed === true) const inputOrder2 = await ocean.compute.orderAsset( @@ -1351,7 +1392,8 @@ describe('Compute flow', () => { inputOrder2Service.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + ddoAdditional2 ) assert(inputOrder2 != null, 'inputOrder2 should not be null') const additionalInputs: ComputeInput[] = [ @@ -1377,7 +1419,8 @@ describe('Compute flow', () => { output, `${computeService.index}`, computeService.type, - additionalInputs + additionalInputs, + ddo ) assert(response.status >= 1, 'Invalid response.status') assert(response.jobId, 'Invalid jobId') @@ -1464,7 +1507,9 @@ describe('Compute flow', () => { const allowed = await ocean.compute.isOrderable( ddo.id, computeService.index, - algoDefinition + algoDefinition, + ddo, + algorithmAsset ) assert(allowed === false, 'This should fail, the algo container section was changed!') }) @@ -1500,7 +1545,9 @@ describe('Compute flow', () => { const allowed = await ocean.compute.isOrderable( ddo.id, computeService.index, - algoDefinition + algoDefinition, + ddo, + algorithmAssetRemoteProvider ) assert(allowed === false, 'This should fail, the algo files section was changed!') }) @@ -1556,7 +1603,8 @@ describe('Compute flow', () => { const allowed = await ocean.compute.isOrderable( datasetWithBogusProvider.id, computeService.index, - algoDefinition + algoDefinition, + datasetWithBogusProvider ) assert(allowed === false) // we know that it is not Orderable, but we are trying to force it @@ -1568,7 +1616,8 @@ describe('Compute flow', () => { computeService.index, algoDefinition, null, // no marketplace fee - computeAddress // CtD is the consumer of the dataset + computeAddress, // CtD is the consumer of the dataset + datasetWithBogusProvider ) assert(order === null, 'Order should be null') } catch (error) { @@ -1585,7 +1634,9 @@ describe('Compute flow', () => { algoDefinition, output, `${computeService.index}`, - computeService.type + computeService.type, + undefined, + ddo ) assert(response === null || response === undefined, 'Compute error') }) @@ -1604,7 +1655,12 @@ describe('Compute flow', () => { }) it('Bob should fail to stop a fake compute job on a bogus provider', async () => { const jobid = '1234' - const response = await ocean.compute.stop(bob, datasetWithBogusProvider.id, jobid) + const response = await ocean.compute.stop( + bob, + datasetWithBogusProvider.id, + jobid, + ddo + ) assert(response === null || response === undefined, 'Invalid response') }) }) From ec2e67db353f0cf6199ea5551a73eac0e1f6b611 Mon Sep 17 00:00:00 2001 From: Bogdan Fazakas Date: Fri, 4 Jun 2021 16:46:12 +0300 Subject: [PATCH 2/7] used type guard to detect if ddo or did and resolve just when needed --- src/ocean/Assets.ts | 60 ++++++----- src/ocean/Compute.ts | 113 ++++++++------------ src/provider/Provider.ts | 15 ++- test/integration/ComputeFlow.test.ts | 149 ++++++++++----------------- 4 files changed, 140 insertions(+), 197 deletions(-) diff --git a/src/ocean/Assets.ts b/src/ocean/Assets.ts index a4e8f209..19b47a4c 100644 --- a/src/ocean/Assets.ts +++ b/src/ocean/Assets.ts @@ -40,6 +40,10 @@ export interface Order { serviceType?: string } +function isDdo(arg: any): arg is DDO { + return arg.id !== undefined +} + /** * Assets submodule of Ocean Protocol. */ @@ -335,11 +339,11 @@ export class Assets extends Instantiable { /** * Returns the creator of a asset. - * @param {string} did Decentralized ID. + * @param {DDO|string} asset DID Descriptor Object containing all the data related to an asset or a Decentralized identifier. * @return {Promise} Returns eth address */ - public async creator(did: string): Promise { - const ddo = await this.resolve(did) + public async creator(asset: DDO | string): Promise { + const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) const checksum = ddo.getChecksum() const { creator, signatureValue } = ddo.proof const signer = await this.ocean.utils.signature.verifyText(checksum, signatureValue) @@ -382,9 +386,13 @@ export class Assets extends Instantiable { } as SearchQuery) } - public async getServiceByType(did: string, serviceType: string): Promise { + public async getServiceByType( + asset: DDO | string, + serviceType: string + ): Promise { + const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) let service: Service - const services: Service[] = (await this.resolve(did)).service + const services: Service[] = ddo.service services.forEach((serv) => { if (serv.type.toString() === serviceType) { @@ -394,9 +402,13 @@ export class Assets extends Instantiable { return service } - public async getServiceByIndex(did: string, serviceIndex: number): Promise { + public async getServiceByIndex( + asset: DDO | string, + serviceIndex: number + ): Promise { + const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) let service: Service - const services: Service[] = (await this.resolve(did)).service + const services: Service[] = ddo.service services.forEach((serv) => { if (serv.index === serviceIndex) { @@ -440,7 +452,7 @@ export class Assets extends Instantiable { /** * Initialize a service * Can be used to compute totalCost for ordering a service - * @param {String} did + * @param {DDO|string} asset DID Descriptor Object containing all the data related to an asset or a Decentralized identifier. * @param {String} serviceType * @param {String} consumerAddress * @param {Number} serviceIndex @@ -448,21 +460,19 @@ export class Assets extends Instantiable { * @return {Promise} Order details */ public async initialize( - did: string, + asset: DDO | string, serviceType: string, consumerAddress: string, serviceIndex = -1, - serviceEndpoint: string, - ddo?: DDO + serviceEndpoint: string ): Promise { const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) const res = await provider.initialize( - did, + asset, serviceIndex, serviceType, - consumerAddress, - ddo + consumerAddress ) if (res === null) return null const providerData = JSON.parse(res) @@ -471,7 +481,7 @@ export class Assets extends Instantiable { /** * Orders & pays for a service - * @param {String} did + * @param {DDO|string} asset DID Descriptor Object containing all the data related to an asset or a Decentralized identifier. * @param {String} serviceType * @param {String} payerAddress * @param {Number} serviceIndex @@ -480,7 +490,7 @@ export class Assets extends Instantiable { * @return {Promise} transactionHash of the payment */ public async order( - did: string, + asset: DDO | string, serviceType: string, payerAddress: string, serviceIndex = -1, @@ -489,27 +499,25 @@ export class Assets extends Instantiable { searchPreviousOrders = true ): Promise { let service: Service - - const ddo = await this.resolve(did) + const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) const consumable = await this.isConsumable(ddo) if (consumable.status > 0) return null if (!consumerAddress) consumerAddress = payerAddress if (serviceIndex === -1) { - service = await this.getServiceByType(did, serviceType) + service = await this.getServiceByType(ddo, serviceType) serviceIndex = service.index } else { - service = await this.getServiceByIndex(did, serviceIndex) + service = await this.getServiceByIndex(ddo, serviceIndex) serviceType = service.type } try { const providerData = await this.initialize( - did, + ddo, serviceType, payerAddress, serviceIndex, - service.serviceEndpoint, - ddo + service.serviceEndpoint ) if (!providerData) throw new Error( @@ -560,13 +568,13 @@ export class Assets extends Instantiable { // marketplace flow public async download( - did: string, + asset: DDO | string, txId: string, tokenAddress: string, consumerAccount: Account, destination: string ): Promise { - const ddo = await this.resolve(did) + const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) const { attributes } = ddo.findServiceByType('metadata') const service = ddo.findServiceByType('access') const { files } = attributes.main @@ -586,7 +594,7 @@ export class Assets extends Instantiable { const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) await provider.download( - did, + ddo.id, txId, tokenAddress, service.type, diff --git a/src/ocean/Compute.ts b/src/ocean/Compute.ts index 6870a68e..4b612c5e 100644 --- a/src/ocean/Compute.ts +++ b/src/ocean/Compute.ts @@ -59,6 +59,10 @@ export const ComputeJobStatus = Object.freeze({ Deleted: 90 }) +function isDdo(arg: any): arg is DDO { + return arg.id !== undefined +} + /** * Compute submodule of Ocean Protocol. */ @@ -98,18 +102,17 @@ export class Compute extends Instantiable { /** * Start the execution of a compute job. - * @param {string} did Decentralized identifer for the asset + * @param {DDO|string} asset DID Descriptor Object containing all the data related to an asset or a Decentralized identifier. * @param {string} txId * @param {string} tokenAddress * @param {Account} consumerAccount The account of the consumer ordering the service. * @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset. * @param {MetaData} algorithmMeta Metadata about the algorithm being run if `algorithm` is being used. This is ignored when `algorithmDid` is specified. * @param {Output} output Define algorithm output publishing. Publishing the result of a compute job is turned off by default. - * @param {DDO} ddo If undefined then the ddo will be fetched by did * @return {Promise} Returns compute job ID under status.jobId */ public async start( - did: string, + asset: DDO | string, txId: string, tokenAddress: string, consumerAccount: Account, @@ -117,21 +120,17 @@ export class Compute extends Instantiable { output?: ComputeOutput, serviceIndex?: string, serviceType?: string, - additionalInputs?: ComputeInput[], - ddo?: DDO + additionalInputs?: ComputeInput[] ): Promise { output = this.checkOutput(consumerAccount, output) - if (!ddo) { - ddo = await this.ocean.assets.resolve(did) - if (!ddo) throw new Error(`Couldn't resolve the did ${did}`) - } + const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service - if (did && txId) { + if (ddo.id && txId) { const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) const computeJobsList = await provider.computeStart( - did, + ddo.id, consumerAccount, algorithm, output, @@ -150,26 +149,21 @@ export class Compute extends Instantiable { /** * Ends a running compute job. * @param {Account} consumerAccount The account of the consumer ordering the service. - * @param {string} did Decentralized identifier. + * @param {DDO|string} asset DID Descriptor Object containing all the data related to an asset or a Decentralized identifier. * @param {string} jobId The ID of the compute job to be stopped - * @param {DDO} ddo If undefined then the ddo will be fetched by did * @return {Promise} Returns the new status of a job */ public async stop( consumerAccount: Account, - did: string, - jobId: string, - ddo?: DDO + asset: DDO | string, + jobId: string ): Promise { - if (!ddo) { - ddo = await this.ocean.assets.resolve(did) - if (!ddo) throw new Error(`Couldn't resolve the did ${did}`) - } + const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) - const computeJobsList = await provider.computeStop(did, consumerAccount, jobId) + const computeJobsList = await provider.computeStop(ddo.id, consumerAccount, jobId) if (computeJobsList) return computeJobsList[0] as ComputeJob return null } @@ -177,26 +171,22 @@ export class Compute extends Instantiable { /** * Deletes a compute job and all resources associated with the job. If job is running it will be stopped first. * @param {Account} consumerAccount The account of the consumer ordering the service. - * @param {string} did Decentralized identifier. + * @param {DDO|string} asset DID Descriptor Object containing all the data related to an asset or a Decentralized identifier. * @param {string} jobId The ID of the compute job to be stopped * @param {DDO} ddo If undefined then the ddo will be fetched by did * @return {Promise} Returns the new status of a job */ public async delete( consumerAccount: Account, - did: string, - jobId: string, - ddo?: DDO + asset: DDO | string, + jobId: string ): Promise { - if (!ddo) { - ddo = await this.ocean.assets.resolve(did) - if (!ddo) throw new Error(`Couldn't resolve the did ${did}`) - } + const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) - const computeJobsList = await provider.computeDelete(did, consumerAccount, jobId) + const computeJobsList = await provider.computeDelete(ddo.id, consumerAccount, jobId) if (computeJobsList) return computeJobsList[0] as ComputeJob return null } @@ -256,27 +246,22 @@ export class Compute extends Instantiable { /** * Returns the final result of a specific compute job published as an asset. * @param {Account} consumerAccount The account of the consumer ordering the service. - * @param {string} did Decentralized identifier. + * @param {DDO|string} asset DID Descriptor Object containing all the data related to an asset or a Decentralized identifier. * @param {string} jobId The ID of the compute job to be stopped. - * @param {DDO} ddo If undefined then the ddo will be fetched by did * @return {Promise} Returns the DDO of the result asset. */ public async result( consumerAccount: Account, - did: string, - jobId: string, - ddo?: DDO + asset: DDO | string, + jobId: string ): Promise { - if (!ddo) { - ddo = await this.ocean.assets.resolve(did) - if (!ddo) throw new Error(`Couldn't resolve the did ${did}`) - } + const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) const computeJobsList = await provider.computeStatus( - did, + ddo.id, consumerAccount, jobId, undefined, @@ -417,11 +402,9 @@ export class Compute extends Instantiable { /** * Checks if an asset is orderable with a specific algorithm - * @param {string} datasetDid The DID of the asset (of type `dataset`) to run the algorithm on. + * @param {DDO|string} dataset DID Descriptor Object containing all the data related to an asset or a Decentralized identifier of the asset (of type `dataset`) to run the algorithm on. * @param {string} serviceIndex The Service index - * @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset. - * @param {MetaData} algorithmMeta Metadata about the algorithm being run if `algorithm` is being used. This is ignored when `algorithmDid` is specified. - * @param {DDO} datasetDdo Dataset DDO object. If undefined then the ddo will be fetched by did + * @param {ComputeAlgorithm} algorithm * @param {DDO} algorithmDDO Algorithm DDO object. If undefined then the ddo will be fetched by did * @return {Promise} True is you can order this * @@ -430,16 +413,12 @@ export class Compute extends Instantiable { * but provider will not allow the compute, due to privacy settings of the ddo */ public async isOrderable( - datasetDid: string, + dataset: DDO | string, serviceIndex: number, algorithm: ComputeAlgorithm, - datasetDdo?: DDO, algorithmDDO?: DDO ): Promise { - if (!datasetDdo) { - datasetDdo = await this.ocean.assets.resolve(datasetDid) - if (!datasetDdo) throw new Error(`Couldn't resolve the did ${datasetDid}`) - } + const datasetDdo = isDdo(dataset) ? dataset : await this.ocean.assets.resolve(dataset) const service: Service = datasetDdo.findServiceById(serviceIndex) if (!service) return false if (service.type === 'compute') { @@ -493,7 +472,7 @@ export class Compute extends Instantiable { ) { this.logger.error( 'ERROR: Algorithm container section was altered since it was added as trusted by ' + - datasetDid + datasetDdo.id ) return false } @@ -503,7 +482,7 @@ export class Compute extends Instantiable { ) { this.logger.error( 'ERROR: Algorithm files section was altered since it was added as trusted by ' + - datasetDid + datasetDdo.id ) return false } @@ -513,7 +492,7 @@ export class Compute extends Instantiable { } // algorithmDid was not found this.logger.error( - 'ERROR: Algorithm ' + algorithm.did + ' is not allowed by ' + datasetDid + 'ERROR: Algorithm ' + algorithm.did + ' is not allowed by ' + datasetDdo.id ) return false } @@ -526,7 +505,7 @@ export class Compute extends Instantiable { /** * Starts an order of a compute or access service for a compute job * @param {String} consumerAccount The account of the consumer ordering the service. - * @param {string} datasetDid The DID of the dataset asset (of type `dataset`) to run the algorithm on. + * @param {DDO|string} dataset DID Descriptor Object containing all the data related to an asset or a Decentralized identifier of the asset (of type `dataset`) to run the algorithm on. * @param {string} serviceIndex The Service index * @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset. * @param {string} algorithmServiceIndex The index of the service in the algorithm @@ -539,38 +518,30 @@ export class Compute extends Instantiable { */ public orderAsset( consumerAccount: string, - datasetDid: string, + dataset: DDO | string, serviceIndex: number, algorithm: ComputeAlgorithm, mpAddress?: string, computeAddress?: string, - datasetDdo?: DDO, searchPreviousOrders = true ): SubscribablePromise { return new SubscribablePromise(async (observer) => { + const datasetDdo = isDdo(dataset) + ? dataset + : await this.ocean.assets.resolve(dataset) // first check if we can order this - const allowed = await this.isOrderable( - datasetDid, - serviceIndex, - algorithm, - datasetDdo - ) + const allowed = await this.isOrderable(datasetDdo, serviceIndex, algorithm) if (!allowed) throw new Error( `Dataset order failed, dataset is not orderable with the specified algorithm` ) - - if (!datasetDdo) { - datasetDdo = await this.ocean.assets.resolve(datasetDid) - if (!datasetDdo) throw new Error(`Couldn't resolve the did ${datasetDid}`) - } // const service: Service = ddo.findServiceByType('compute') const service: Service = datasetDdo.findServiceById(serviceIndex) if (!service) throw new Error(`Dataset order failed, Could not find service for the DDO`) try { const order = await this.ocean.assets.order( - datasetDid, + datasetDdo, service.type, consumerAccount, -1, @@ -588,7 +559,7 @@ export class Compute extends Instantiable { /** * Orders & pays for a algorithm - * @param {String} did + * @param {DDO|string} asset DID Descriptor Object containing all the data related to an asset or a Decentralized identifier. * @param {String} serviceType * @param {String} payerAddress * @param {Number} serviceIndex @@ -597,7 +568,7 @@ export class Compute extends Instantiable { * @return {Promise} transactionHash of the payment */ public async orderAlgorithm( - did: string, + asset: DDO | string, serviceType: string, payerAddress: string, serviceIndex = -1, @@ -608,7 +579,7 @@ export class Compute extends Instantiable { // this is only a convienince function, which calls ocean.assets.order try { return await this.ocean.assets.order( - did, + asset, serviceType, payerAddress, serviceIndex, diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index 959f9358..760d2a27 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -19,6 +19,9 @@ export interface ServiceEndpoint { method: string urlPath: string } +function isDdo(arg: any): arg is DDO { + return arg.id !== undefined +} /** * Provides an interface for provider service. * Provider service is the technical component executed @@ -186,21 +189,17 @@ export class Provider extends Instantiable { } public async initialize( - did: string, + asset: DDO | string, serviceIndex: number, serviceType: string, - consumerAddress: string, - ddo?: DDO + consumerAddress: string ): Promise { - if (!ddo) { - ddo = await this.ocean.assets.resolve(did) - if (!ddo) throw new Error(`Couldn't resolve the did ${did}`) - } + const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) let initializeUrl = this.getInitializeEndpoint() ? this.getInitializeEndpoint().urlPath : null if (!initializeUrl) return null - initializeUrl += `?documentId=${did}` + initializeUrl += `?documentId=${ddo.id}` initializeUrl += `&serviceId=${serviceIndex}` initializeUrl += `&serviceType=${serviceType}` initializeUrl += `&dataToken=${ddo.dataToken}` diff --git a/test/integration/ComputeFlow.test.ts b/test/integration/ComputeFlow.test.ts index 2db1eef5..f58263ef 100644 --- a/test/integration/ComputeFlow.test.ts +++ b/test/integration/ComputeFlow.test.ts @@ -844,24 +844,22 @@ describe('Compute flow', () => { meta: algorithmMeta } const allowed = await ocean.compute.isOrderable( - ddo.id, + ddo, computeService.index, - algoDefinition, - ddo + algoDefinition ) assert(allowed === true) computeOrderId = await ocean.compute.orderAsset( bob.getId(), - ddo.id, + ddo, computeService.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - ddo + computeAddress // CtD is the consumer of the dataset ) assert(computeOrderId != null, 'computeOrderId === null') const response = await ocean.compute.start( - ddo.id, + ddo, computeOrderId, tokenAddress, bob, @@ -869,8 +867,7 @@ describe('Compute flow', () => { output, `${computeService.index}`, computeService.type, - undefined, - ddo + undefined ) assert(response, 'Compute error') jobId = response.jobId @@ -928,7 +925,7 @@ describe('Compute flow', () => { }) it('Bob should stop compute job', async () => { assert(jobId != null, 'Jobid is null') - await ocean.compute.stop(bob, ddo.id, jobId, ddo) + await ocean.compute.stop(bob, ddo, jobId) const response = await ocean.compute.status(bob, ddo.id, undefined, undefined, jobId) // TODO: typings say that `stopreq` does not exist assert((response[0] as any).stopreq === 1, 'Response.stopreq is invalid') @@ -947,12 +944,11 @@ describe('Compute flow', () => { try { const order = await ocean.compute.orderAsset( bob.getId(), - datasetNoRawAlgo.id, + datasetNoRawAlgo, service1.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - datasetNoRawAlgo + computeAddress // CtD is the consumer of the dataset ) assert(order === null, 'Order should be null') } catch (error) { @@ -973,10 +969,9 @@ describe('Compute flow', () => { } // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions const allowed = await ocean.compute.isOrderable( - datasetWithTrustedAlgo.id, + datasetWithTrustedAlgo, service1.index, - algoDefinition, - datasetWithTrustedAlgo + algoDefinition ) assert(allowed === false) @@ -984,12 +979,11 @@ describe('Compute flow', () => { try { const order = await ocean.compute.orderAsset( bob.getId(), - datasetWithTrustedAlgo.id, + datasetWithTrustedAlgo, service1.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - datasetWithTrustedAlgo + computeAddress // CtD is the consumer of the dataset ) assert(order === null, 'Order should be null') } catch (error) { @@ -1006,10 +1000,9 @@ describe('Compute flow', () => { did: algorithmAsset.id } const allowed = await ocean.compute.isOrderable( - ddo.id, + ddo, computeService.index, algoDefinition, - ddo, algorithmAsset ) assert(allowed === false) @@ -1017,12 +1010,11 @@ describe('Compute flow', () => { try { const order = await ocean.compute.orderAsset( bob.getId(), - ddo.id, + ddo, computeService.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - ddo + computeAddress // CtD is the consumer of the dataset ) assert(order === null, 'Order should be null') } catch (error) { @@ -1109,22 +1101,20 @@ describe('Compute flow', () => { serviceIndex: serviceAlgo.index } const allowed = await ocean.compute.isOrderable( - ddo.id, + ddo, computeService.index, algoDefinition, - ddo, algorithmAssetRemoteProviderWithCompute ) assert(allowed === false) try { const order = await ocean.compute.orderAsset( bob.getId(), - ddo.id, + ddo, computeService.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - ddo + computeAddress // CtD is the consumer of the dataset ) assert(order === null, 'Order should be null') } catch (error) { @@ -1145,26 +1135,24 @@ describe('Compute flow', () => { } // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions const allowed = await ocean.compute.isOrderable( - ddo.id, + ddo, computeService.index, algoDefinition, - ddo, algorithmAssetwithCompute ) assert(allowed === true) const order = await ocean.compute.orderAsset( bob.getId(), - ddo.id, + ddo, computeService.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - ddo + computeAddress // CtD is the consumer of the dataset ) assert(order != null, 'Order should not be null') // order the algorithm const orderalgo = await ocean.compute.orderAlgorithm( - algorithmAssetwithCompute.id, + algorithmAssetwithCompute, serviceAlgo.type, bob.getId(), serviceAlgo.index, @@ -1175,7 +1163,7 @@ describe('Compute flow', () => { algoDefinition.transferTxId = orderalgo algoDefinition.dataToken = algorithmAssetwithCompute.dataToken const response = await ocean.compute.start( - ddo.id, + ddo, order, tokenAddress, bob, @@ -1183,8 +1171,7 @@ describe('Compute flow', () => { output, `${computeService.index}`, computeService.type, - undefined, - ddo + undefined ) assert(response, 'Compute error') jobId = response.jobId @@ -1206,26 +1193,24 @@ describe('Compute flow', () => { } // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions const allowed = await ocean.compute.isOrderable( - ddo.id, + ddo, computeService.index, algoDefinition, - ddo, algorithmAsset ) assert(allowed === true) const order = await ocean.compute.orderAsset( bob.getId(), - ddo.id, + ddo, computeService.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - ddo + computeAddress // CtD is the consumer of the dataset ) assert(order != null, 'Order should not be null') // order the algorithm const orderalgo = await ocean.compute.orderAlgorithm( - algorithmAsset.id, + algorithmAsset, serviceAlgo.type, bob.getId(), serviceAlgo.index, @@ -1236,7 +1221,7 @@ describe('Compute flow', () => { algoDefinition.transferTxId = orderalgo algoDefinition.dataToken = algorithmAsset.dataToken const response = await ocean.compute.start( - ddo.id, + ddo, order, tokenAddress, bob, @@ -1244,8 +1229,7 @@ describe('Compute flow', () => { output, `${computeService.index}`, computeService.type, - undefined, - ddo + undefined ) assert(response, 'Compute error') jobId = response.jobId @@ -1270,25 +1254,23 @@ describe('Compute flow', () => { } // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions const allowed = await ocean.compute.isOrderable( - ddo.id, + ddo, computeService.index, algoDefinition, - ddo, algorithmAssetRemoteProvider ) assert(allowed === true) const order = await ocean.compute.orderAsset( bob.getId(), - ddo.id, + ddo, computeService.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - ddo + computeAddress // CtD is the consumer of the dataset ) assert(order != null, 'Order should not be null') const orderalgo = await ocean.compute.orderAlgorithm( - algorithmAssetRemoteProvider.id, + algorithmAssetRemoteProvider, serviceAlgo.type, bob.getId(), serviceAlgo.index, @@ -1299,16 +1281,14 @@ describe('Compute flow', () => { algoDefinition.transferTxId = orderalgo algoDefinition.dataToken = algorithmAssetRemoteProvider.dataToken const response = await ocean.compute.start( - ddo.id, + ddo, order, tokenAddress, bob, algoDefinition, output, `${computeService.index}`, - computeService.type, - undefined, - ddo + computeService.type ) assert(response, 'Compute error') assert(response.status >= 1, 'Invalid response status') @@ -1329,26 +1309,24 @@ describe('Compute flow', () => { } let allowed allowed = await ocean.compute.isOrderable( - ddo.id, + ddo, computeService.index, algoDefinition, - ddo, algorithmAsset ) assert(allowed === true) const order = await ocean.compute.orderAsset( bob.getId(), - ddo.id, + ddo, computeService.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - ddo + computeAddress // CtD is the consumer of the dataset ) assert(order != null, 'Order should not be null') // order the algo const orderalgo = await ocean.compute.orderAlgorithm( - algorithmAsset.id, + algorithmAsset, serviceAlgo.type, bob.getId(), serviceAlgo.index, @@ -1360,7 +1338,7 @@ describe('Compute flow', () => { assert(ddoAdditional1 != null, 'ddoAdditional1 should not be null') const inputOrder1Service = ddoAdditional1.findServiceByType('compute') allowed = await ocean.compute.isOrderable( - ddoAdditional1.id, + ddoAdditional1, inputOrder1Service.index, algoDefinition, ddoAdditional1 @@ -1368,19 +1346,18 @@ describe('Compute flow', () => { assert(allowed === true) const inputOrder1 = await ocean.compute.orderAsset( bob.getId(), - ddoAdditional1.id, + ddoAdditional1, inputOrder1Service.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - ddoAdditional1 + computeAddress // CtD is the consumer of the dataset ) assert(inputOrder1 != null, 'inputOrder1 should not be null') assert(ddoAdditional1 != null, 'ddoAdditional1 should not be null') // 2nd additional input const inputOrder2Service = ddoAdditional2.findServiceByType('access') allowed = await ocean.compute.isOrderable( - ddoAdditional2.id, + ddoAdditional2, inputOrder2Service.index, algoDefinition, ddoAdditional2 @@ -1388,12 +1365,11 @@ describe('Compute flow', () => { assert(allowed === true) const inputOrder2 = await ocean.compute.orderAsset( bob.getId(), - ddoAdditional2.id, + ddoAdditional2, inputOrder2Service.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - ddoAdditional2 + computeAddress // CtD is the consumer of the dataset ) assert(inputOrder2 != null, 'inputOrder2 should not be null') const additionalInputs: ComputeInput[] = [ @@ -1411,7 +1387,7 @@ describe('Compute flow', () => { algoDefinition.transferTxId = orderalgo algoDefinition.dataToken = algorithmAsset.dataToken const response = await ocean.compute.start( - ddo.id, + ddo, order, tokenAddress, bob, @@ -1419,8 +1395,7 @@ describe('Compute flow', () => { output, `${computeService.index}`, computeService.type, - additionalInputs, - ddo + additionalInputs ) assert(response.status >= 1, 'Invalid response.status') assert(response.jobId, 'Invalid jobId') @@ -1505,10 +1480,9 @@ describe('Compute flow', () => { } // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions const allowed = await ocean.compute.isOrderable( - ddo.id, + ddo, computeService.index, algoDefinition, - ddo, algorithmAsset ) assert(allowed === false, 'This should fail, the algo container section was changed!') @@ -1543,10 +1517,9 @@ describe('Compute flow', () => { } // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions const allowed = await ocean.compute.isOrderable( - ddo.id, + ddo, computeService.index, algoDefinition, - ddo, algorithmAssetRemoteProvider ) assert(allowed === false, 'This should fail, the algo files section was changed!') @@ -1601,7 +1574,7 @@ describe('Compute flow', () => { } // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions const allowed = await ocean.compute.isOrderable( - datasetWithBogusProvider.id, + datasetWithBogusProvider, computeService.index, algoDefinition, datasetWithBogusProvider @@ -1612,12 +1585,11 @@ describe('Compute flow', () => { try { const order = await ocean.compute.orderAsset( bob.getId(), - datasetWithBogusProvider.id, + datasetWithBogusProvider, computeService.index, algoDefinition, null, // no marketplace fee - computeAddress, // CtD is the consumer of the dataset - datasetWithBogusProvider + computeAddress // CtD is the consumer of the dataset ) assert(order === null, 'Order should be null') } catch (error) { @@ -1627,16 +1599,14 @@ describe('Compute flow', () => { // we are forcing a bogus orderId computeOrderId = '1234' const response = await ocean.compute.start( - datasetWithBogusProvider.id, + datasetWithBogusProvider, computeOrderId, tokenAddress, bob, algoDefinition, output, `${computeService.index}`, - computeService.type, - undefined, - ddo + computeService.type ) assert(response === null || response === undefined, 'Compute error') }) @@ -1655,12 +1625,7 @@ describe('Compute flow', () => { }) it('Bob should fail to stop a fake compute job on a bogus provider', async () => { const jobid = '1234' - const response = await ocean.compute.stop( - bob, - datasetWithBogusProvider.id, - jobid, - ddo - ) + const response = await ocean.compute.stop(bob, datasetWithBogusProvider, jobid) assert(response === null || response === undefined, 'Invalid response') }) }) From c88680f10061b47d1d72d1339975466df0ec5804 Mon Sep 17 00:00:00 2001 From: Bogdan Fazakas Date: Tue, 8 Jun 2021 09:08:24 +0300 Subject: [PATCH 3/7] added AssetResolverHelper --- package-lock.json | 2 +- src/ocean/Assets.ts | 27 +++++++--------------- src/ocean/Compute.ts | 48 ++++++++++++++++++---------------------- src/provider/Provider.ts | 12 ++++------ src/utils/index.ts | 1 + 5 files changed, 36 insertions(+), 54 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3ca2d258..d63d66ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "node-abort-controller": "^2.0.0", "save-file": "^2.3.1", "uuid": "^8.3.2", - "web3": "^1.3.6", + "web3": "^1.3.5", "web3-eth-contract": "^1.3.6" }, "devDependencies": { diff --git a/src/ocean/Assets.ts b/src/ocean/Assets.ts index 3e2a9466..6897e917 100644 --- a/src/ocean/Assets.ts +++ b/src/ocean/Assets.ts @@ -5,7 +5,7 @@ import { Service, ServiceAccess } from '../ddo/interfaces/Service' import { EditableMetadata } from '../ddo/interfaces/EditableMetadata' import Account from './Account' import DID from './DID' -import { SubscribablePromise, didNoZeroX, didPrefixed } from '../utils' +import { SubscribablePromise, didNoZeroX, didPrefixed, assetResolve } from '../utils' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' import { WebServiceConnector } from './utils/WebServiceConnector' import BigNumber from 'bignumber.js' @@ -46,10 +46,6 @@ export interface Order { serviceType?: string } -function isDdo(arg: any): arg is DDO { - return arg.id !== undefined -} - /** * Assets submodule of Ocean Protocol. */ @@ -414,14 +410,14 @@ export class Assets extends Instantiable { * @return {Promise} Returns eth address */ public async creator(asset: DDO | string): Promise { - const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) + const { did, ddo } = await assetResolve(asset) const checksum = ddo.getChecksum() const { creator, signatureValue } = ddo.proof const signer = await this.ocean.utils.signature.verifyText(checksum, signatureValue) if (signer.toLowerCase() !== creator.toLowerCase()) { this.logger.warn( - `Owner of ${ddo.id} doesn't match. Expected ${creator} instead of ${signer}.` + `Owner of ${did} doesn't match. Expected ${creator} instead of ${signer}.` ) } @@ -461,7 +457,7 @@ export class Assets extends Instantiable { asset: DDO | string, serviceType: string ): Promise { - const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) + const { ddo } = await assetResolve(asset) let service: Service const services: Service[] = ddo.service @@ -477,7 +473,7 @@ export class Assets extends Instantiable { asset: DDO | string, serviceIndex: number ): Promise { - const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) + const { ddo } = await assetResolve(asset) let service: Service const services: Service[] = ddo.service @@ -570,18 +566,11 @@ export class Assets extends Instantiable { searchPreviousOrders = true ): Promise { let service: Service -<<<<<<< HEAD - const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) - const consumable = await this.isConsumable(ddo) - if (consumable.status > 0) return null -======= - - const ddo = await this.resolve(did) + const { ddo } = await assetResolve(asset) const consumable = await this.isConsumable(ddo, consumerAddress) if (consumable.status > 0) { throw new Error(`Order asset failed, ` + consumable.message) } ->>>>>>> main if (!consumerAddress) consumerAddress = payerAddress if (serviceIndex === -1) { @@ -654,7 +643,7 @@ export class Assets extends Instantiable { consumerAccount: Account, destination: string ): Promise { - const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) + const { did, ddo } = await assetResolve(asset) const { attributes } = ddo.findServiceByType('metadata') const service = ddo.findServiceByType('access') const { files } = attributes.main @@ -674,7 +663,7 @@ export class Assets extends Instantiable { const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) await provider.download( - ddo.id, + did, txId, tokenAddress, service.type, diff --git a/src/ocean/Compute.ts b/src/ocean/Compute.ts index 4b612c5e..d6158d3e 100644 --- a/src/ocean/Compute.ts +++ b/src/ocean/Compute.ts @@ -1,5 +1,4 @@ import { DDO } from '../ddo/DDO' -import { MetadataAlgorithm } from '../ddo/interfaces/MetadataAlgorithm' import { Service, ServiceComputePrivacy, @@ -7,7 +6,7 @@ import { publisherTrustedAlgorithm } from '../ddo/interfaces/Service' import Account from './Account' -import { SubscribablePromise } from '../utils' +import { SubscribablePromise, assetResolve, AssetResolver } from '../utils' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' import { ComputeOutput, @@ -59,10 +58,6 @@ export const ComputeJobStatus = Object.freeze({ Deleted: 90 }) -function isDdo(arg: any): arg is DDO { - return arg.id !== undefined -} - /** * Compute submodule of Ocean Protocol. */ @@ -123,14 +118,14 @@ export class Compute extends Instantiable { additionalInputs?: ComputeInput[] ): Promise { output = this.checkOutput(consumerAccount, output) - const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) + const { did, ddo } = await assetResolve(asset) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service - if (ddo.id && txId) { + if (did && txId) { const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) const computeJobsList = await provider.computeStart( - ddo.id, + did, consumerAccount, algorithm, output, @@ -158,12 +153,12 @@ export class Compute extends Instantiable { asset: DDO | string, jobId: string ): Promise { - const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) + const { did, ddo } = await assetResolve(asset) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) - const computeJobsList = await provider.computeStop(ddo.id, consumerAccount, jobId) + const computeJobsList = await provider.computeStop(did, consumerAccount, jobId) if (computeJobsList) return computeJobsList[0] as ComputeJob return null } @@ -181,12 +176,12 @@ export class Compute extends Instantiable { asset: DDO | string, jobId: string ): Promise { - const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) + const { did, ddo } = await assetResolve(asset) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) - const computeJobsList = await provider.computeDelete(ddo.id, consumerAccount, jobId) + const computeJobsList = await provider.computeDelete(did, consumerAccount, jobId) if (computeJobsList) return computeJobsList[0] as ComputeJob return null } @@ -255,13 +250,13 @@ export class Compute extends Instantiable { asset: DDO | string, jobId: string ): Promise { - const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) + const { did, ddo } = await assetResolve(asset) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) await provider.setBaseUrl(serviceEndpoint) const computeJobsList = await provider.computeStatus( - ddo.id, + did, consumerAccount, jobId, undefined, @@ -418,8 +413,8 @@ export class Compute extends Instantiable { algorithm: ComputeAlgorithm, algorithmDDO?: DDO ): Promise { - const datasetDdo = isDdo(dataset) ? dataset : await this.ocean.assets.resolve(dataset) - const service: Service = datasetDdo.findServiceById(serviceIndex) + const datasetResolved: AssetResolver = await assetResolve(dataset) + const service: Service = datasetResolved.ddo.findServiceById(serviceIndex) if (!service) return false if (service.type === 'compute') { if (algorithm.meta) { @@ -472,7 +467,7 @@ export class Compute extends Instantiable { ) { this.logger.error( 'ERROR: Algorithm container section was altered since it was added as trusted by ' + - datasetDdo.id + datasetResolved.did ) return false } @@ -482,7 +477,7 @@ export class Compute extends Instantiable { ) { this.logger.error( 'ERROR: Algorithm files section was altered since it was added as trusted by ' + - datasetDdo.id + datasetResolved.ddo ) return false } @@ -492,7 +487,10 @@ export class Compute extends Instantiable { } // algorithmDid was not found this.logger.error( - 'ERROR: Algorithm ' + algorithm.did + ' is not allowed by ' + datasetDdo.id + 'ERROR: Algorithm ' + + algorithm.did + + ' is not allowed by ' + + datasetResolved.did ) return false } @@ -526,22 +524,20 @@ export class Compute extends Instantiable { searchPreviousOrders = true ): SubscribablePromise { return new SubscribablePromise(async (observer) => { - const datasetDdo = isDdo(dataset) - ? dataset - : await this.ocean.assets.resolve(dataset) + const { ddo } = await assetResolve(dataset) // first check if we can order this - const allowed = await this.isOrderable(datasetDdo, serviceIndex, algorithm) + const allowed = await this.isOrderable(ddo, serviceIndex, algorithm) if (!allowed) throw new Error( `Dataset order failed, dataset is not orderable with the specified algorithm` ) // const service: Service = ddo.findServiceByType('compute') - const service: Service = datasetDdo.findServiceById(serviceIndex) + const service: Service = ddo.findServiceById(serviceIndex) if (!service) throw new Error(`Dataset order failed, Could not find service for the DDO`) try { const order = await this.ocean.assets.order( - datasetDdo, + ddo, service.type, consumerAccount, -1, diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index 760d2a27..ceaed830 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -1,5 +1,5 @@ import Account from '../ocean/Account' -import { noZeroX } from '../utils' +import { noZeroX, assetResolve, AssetResolver } from '../utils' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' import { File } from '../ddo/interfaces/File' import { @@ -8,8 +8,6 @@ import { ComputeOutput, ComputeAlgorithm } from '../ocean/interfaces/Compute' -import { MetadataAlgorithm } from '../ddo/interfaces/MetadataAlgorithm' -import { Versions } from '../ocean/Versions' import { DDO } from '../ddo/DDO' import DID from '../ocean/DID' import { Service } from '../ddo/interfaces' @@ -19,9 +17,7 @@ export interface ServiceEndpoint { method: string urlPath: string } -function isDdo(arg: any): arg is DDO { - return arg.id !== undefined -} + /** * Provides an interface for provider service. * Provider service is the technical component executed @@ -194,12 +190,12 @@ export class Provider extends Instantiable { serviceType: string, consumerAddress: string ): Promise { - const ddo = isDdo(asset) ? asset : await this.ocean.assets.resolve(asset) + const { did, ddo } = await assetResolve(asset) let initializeUrl = this.getInitializeEndpoint() ? this.getInitializeEndpoint().urlPath : null if (!initializeUrl) return null - initializeUrl += `?documentId=${ddo.id}` + initializeUrl += `?documentId=${did}` initializeUrl += `&serviceId=${serviceIndex}` initializeUrl += `&serviceType=${serviceType}` initializeUrl += `&dataToken=${ddo.dataToken}` diff --git a/src/utils/index.ts b/src/utils/index.ts index ccf439a7..922ac466 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -5,3 +5,4 @@ export * from './GeneratorHelpers' export * from './SubscribablePromise' export * from './SubscribableObserver' export * from './GasUtils' +export * from './AssetResolverHelper' From 200e0d8832de14a0fc63a2dc2518a3a295e417dc Mon Sep 17 00:00:00 2001 From: Bogdan Fazakas Date: Tue, 8 Jun 2021 09:08:51 +0300 Subject: [PATCH 4/7] staged helper file --- src/utils/AssetResolverHelper.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/utils/AssetResolverHelper.ts diff --git a/src/utils/AssetResolverHelper.ts b/src/utils/AssetResolverHelper.ts new file mode 100644 index 00000000..df552fbf --- /dev/null +++ b/src/utils/AssetResolverHelper.ts @@ -0,0 +1,25 @@ +import { DDO } from '../ddo/DDO' +import { Ocean } from '../ocean/Ocean' + +export interface AssetResolver { + did: string + ddo: DDO +} + +function isDdo(arg: any): arg is DDO { + return arg.id !== undefined +} + +export async function assetResolve(asset: DDO | string): Promise { + let ocean: Ocean + + if (isDdo(asset)) { + const did = asset.id + const ddo = asset + return { did, ddo } + } else { + const ddo = await ocean.assets.resolve(asset) + const did = ddo.id + return { did, ddo } + } +} From 0786c32a7b3390f0165666c0fea039cb6652925f Mon Sep 17 00:00:00 2001 From: Bogdan Fazakas Date: Tue, 8 Jun 2021 14:06:23 +0300 Subject: [PATCH 5/7] fixed lint errors --- src/datatokens/Datatokens.ts | 5 +---- src/ocean/Compute.ts | 18 ++++++++---------- src/utils/ConfigHelper.ts | 20 ++++---------------- src/utils/SubscribablePromise.ts | 4 +--- test/integration/ComputeFlow.test.ts | 23 ++++++++--------------- 5 files changed, 22 insertions(+), 48 deletions(-) diff --git a/src/datatokens/Datatokens.ts b/src/datatokens/Datatokens.ts index 1fd3ac39..bd625424 100644 --- a/src/datatokens/Datatokens.ts +++ b/src/datatokens/Datatokens.ts @@ -47,10 +47,7 @@ export class DataTokens { * Generate new datatoken name & symbol from a word list * @return {<{ name: String; symbol: String }>} datatoken name & symbol. Produces e.g. "Endemic Jellyfish Token" & "ENDJEL-45" */ - public generateDtName(wordList?: { - nouns: string[] - adjectives: string[] - }): { + public generateDtName(wordList?: { nouns: string[]; adjectives: string[] }): { name: string symbol: string } { diff --git a/src/ocean/Compute.ts b/src/ocean/Compute.ts index d6158d3e..fd5b48d4 100644 --- a/src/ocean/Compute.ts +++ b/src/ocean/Compute.ts @@ -641,9 +641,8 @@ export class Compute extends Instantiable { } if (typeof ddo.service[serviceIndex] === 'undefined') return null if (ddo.service[serviceIndex].type !== 'compute') return null - ddo.service[ - serviceIndex - ].attributes.main.privacy.allowAllPublishedAlgorithms = newState + ddo.service[serviceIndex].attributes.main.privacy.allowAllPublishedAlgorithms = + newState return ddo } @@ -758,13 +757,12 @@ export class Compute extends Instantiable { if (ddo.service[serviceIndex].type !== 'compute') return ddo if (!ddo.service[serviceIndex].attributes.main.privacy.publisherTrustedAlgorithms) return ddo - ddo.service[ - serviceIndex - ].attributes.main.privacy.publisherTrustedAlgorithms = ddo.service[ - serviceIndex - ].attributes.main.privacy.publisherTrustedAlgorithms.filter(function (el) { - return el.did !== algoDid - }) + ddo.service[serviceIndex].attributes.main.privacy.publisherTrustedAlgorithms = + ddo.service[serviceIndex].attributes.main.privacy.publisherTrustedAlgorithms.filter( + function (el) { + return el.did !== algoDid + } + ) return ddo } } diff --git a/src/utils/ConfigHelper.ts b/src/utils/ConfigHelper.ts index 05db7929..c9193c51 100644 --- a/src/utils/ConfigHelper.ts +++ b/src/utils/ConfigHelper.ts @@ -150,14 +150,8 @@ export class ConfigHelper { // use the defaults first let configAddresses: Partial if (DefaultContractsAddresses[network]) { - const { - DTFactory, - BFactory, - FixedRateExchange, - Dispenser, - Metadata, - Ocean - } = DefaultContractsAddresses[network] + const { DTFactory, BFactory, FixedRateExchange, Dispenser, Metadata, Ocean } = + DefaultContractsAddresses[network] configAddresses = { factoryAddress: DTFactory, poolFactoryAddress: BFactory, @@ -178,14 +172,8 @@ export class ConfigHelper { 'utf8' ) ) - const { - DTFactory, - BFactory, - FixedRateExchange, - Dispenser, - Metadata, - Ocean - } = data[network] + const { DTFactory, BFactory, FixedRateExchange, Dispenser, Metadata, Ocean } = + data[network] configAddresses = { factoryAddress: DTFactory, poolFactoryAddress: BFactory, diff --git a/src/utils/SubscribablePromise.ts b/src/utils/SubscribablePromise.ts index 3e0c8fe0..5a72e618 100644 --- a/src/utils/SubscribablePromise.ts +++ b/src/utils/SubscribablePromise.ts @@ -17,9 +17,7 @@ export class SubscribablePromise { setTimeout(() => this.init(executor), 1) } - public subscribe( - onNext: (next: T) => void - ): { + public subscribe(onNext: (next: T) => void): { unsubscribe: () => boolean } { return this.observer.subscribe(onNext) diff --git a/test/integration/ComputeFlow.test.ts b/test/integration/ComputeFlow.test.ts index f58263ef..6535c6d5 100644 --- a/test/integration/ComputeFlow.test.ts +++ b/test/integration/ComputeFlow.test.ts @@ -104,8 +104,7 @@ describe('Compute flow', () => { language: 'js', format: 'docker-image', version: '0.1', - url: - 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + url: 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', container: { entrypoint: 'node $ALGO', image: 'node', @@ -250,8 +249,7 @@ describe('Compute flow', () => { license: 'CC-BY', files: [ { - url: - 'https://raw.githubusercontent.com/tbertinmahieux/MSongsDB/master/Tasks_Demos/CoverSongs/shs_dataset_test.txt', + url: 'https://raw.githubusercontent.com/tbertinmahieux/MSongsDB/master/Tasks_Demos/CoverSongs/shs_dataset_test.txt', checksum: 'efb2c764274b745f5fc37f97c6b0e764', contentLength: '4535431', contentType: 'text/csv', @@ -487,8 +485,7 @@ describe('Compute flow', () => { license: 'CC-BY', files: [ { - url: - 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + url: 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', contentType: 'text/js', encoding: 'UTF-8' } @@ -540,8 +537,7 @@ describe('Compute flow', () => { license: 'CC-BY', files: [ { - url: - 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + url: 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', contentType: 'text/js', encoding: 'UTF-8' } @@ -602,8 +598,7 @@ describe('Compute flow', () => { license: 'CC-BY', files: [ { - url: - 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + url: 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', contentType: 'text/js', encoding: 'UTF-8' } @@ -667,8 +662,7 @@ describe('Compute flow', () => { license: 'CC-BY', files: [ { - url: - 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + url: 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', contentType: 'text/js', encoding: 'UTF-8' } @@ -1089,9 +1083,8 @@ describe('Compute flow', () => { algorithmAssetRemoteProviderWithCompute != null, 'algorithmAsset should not be null' ) - const serviceAlgo = algorithmAssetRemoteProviderWithCompute.findServiceByType( - 'compute' - ) + const serviceAlgo = + algorithmAssetRemoteProviderWithCompute.findServiceByType('compute') assert(serviceAlgo != null, 'serviceAlgo should not be null') // get the compute address first computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) From 4f9ed040866e7ee5bfd80c4ab5cd71d56c1abefc Mon Sep 17 00:00:00 2001 From: Bogdan Fazakas Date: Tue, 8 Jun 2021 17:24:54 +0300 Subject: [PATCH 6/7] sent ocean instance param to asset resolve helper --- src/ocean/Assets.ts | 10 +++++----- src/ocean/Compute.ts | 12 ++++++------ src/provider/Provider.ts | 2 +- src/utils/AssetResolverHelper.ts | 7 ++++--- test/integration/ComputeFlow.test.ts | 9 ++------- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/ocean/Assets.ts b/src/ocean/Assets.ts index 6897e917..bc4eebff 100644 --- a/src/ocean/Assets.ts +++ b/src/ocean/Assets.ts @@ -410,7 +410,7 @@ export class Assets extends Instantiable { * @return {Promise} Returns eth address */ public async creator(asset: DDO | string): Promise { - const { did, ddo } = await assetResolve(asset) + const { did, ddo } = await assetResolve(asset, this.ocean) const checksum = ddo.getChecksum() const { creator, signatureValue } = ddo.proof const signer = await this.ocean.utils.signature.verifyText(checksum, signatureValue) @@ -457,7 +457,7 @@ export class Assets extends Instantiable { asset: DDO | string, serviceType: string ): Promise { - const { ddo } = await assetResolve(asset) + const { ddo } = await assetResolve(asset, this.ocean) let service: Service const services: Service[] = ddo.service @@ -473,7 +473,7 @@ export class Assets extends Instantiable { asset: DDO | string, serviceIndex: number ): Promise { - const { ddo } = await assetResolve(asset) + const { ddo } = await assetResolve(asset, this.ocean) let service: Service const services: Service[] = ddo.service @@ -566,7 +566,7 @@ export class Assets extends Instantiable { searchPreviousOrders = true ): Promise { let service: Service - const { ddo } = await assetResolve(asset) + const { ddo } = await assetResolve(asset, this.ocean) const consumable = await this.isConsumable(ddo, consumerAddress) if (consumable.status > 0) { throw new Error(`Order asset failed, ` + consumable.message) @@ -643,7 +643,7 @@ export class Assets extends Instantiable { consumerAccount: Account, destination: string ): Promise { - const { did, ddo } = await assetResolve(asset) + const { did, ddo } = await assetResolve(asset, this.ocean) const { attributes } = ddo.findServiceByType('metadata') const service = ddo.findServiceByType('access') const { files } = attributes.main diff --git a/src/ocean/Compute.ts b/src/ocean/Compute.ts index fd5b48d4..25274483 100644 --- a/src/ocean/Compute.ts +++ b/src/ocean/Compute.ts @@ -118,7 +118,7 @@ export class Compute extends Instantiable { additionalInputs?: ComputeInput[] ): Promise { output = this.checkOutput(consumerAccount, output) - const { did, ddo } = await assetResolve(asset) + const { did, ddo } = await assetResolve(asset, this.ocean) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service if (did && txId) { @@ -153,7 +153,7 @@ export class Compute extends Instantiable { asset: DDO | string, jobId: string ): Promise { - const { did, ddo } = await assetResolve(asset) + const { did, ddo } = await assetResolve(asset, this.ocean) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) @@ -176,7 +176,7 @@ export class Compute extends Instantiable { asset: DDO | string, jobId: string ): Promise { - const { did, ddo } = await assetResolve(asset) + const { did, ddo } = await assetResolve(asset, this.ocean) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) @@ -250,7 +250,7 @@ export class Compute extends Instantiable { asset: DDO | string, jobId: string ): Promise { - const { did, ddo } = await assetResolve(asset) + const { did, ddo } = await assetResolve(asset, this.ocean) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service const provider = await Provider.getInstance(this.instanceConfig) @@ -413,7 +413,7 @@ export class Compute extends Instantiable { algorithm: ComputeAlgorithm, algorithmDDO?: DDO ): Promise { - const datasetResolved: AssetResolver = await assetResolve(dataset) + const datasetResolved: AssetResolver = await assetResolve(dataset, this.ocean) const service: Service = datasetResolved.ddo.findServiceById(serviceIndex) if (!service) return false if (service.type === 'compute') { @@ -524,7 +524,7 @@ export class Compute extends Instantiable { searchPreviousOrders = true ): SubscribablePromise { return new SubscribablePromise(async (observer) => { - const { ddo } = await assetResolve(dataset) + const { ddo } = await assetResolve(dataset, this.ocean) // first check if we can order this const allowed = await this.isOrderable(ddo, serviceIndex, algorithm) if (!allowed) diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index ceaed830..4f3a317a 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -190,7 +190,7 @@ export class Provider extends Instantiable { serviceType: string, consumerAddress: string ): Promise { - const { did, ddo } = await assetResolve(asset) + const { did, ddo } = await assetResolve(asset, this.ocean) let initializeUrl = this.getInitializeEndpoint() ? this.getInitializeEndpoint().urlPath : null diff --git a/src/utils/AssetResolverHelper.ts b/src/utils/AssetResolverHelper.ts index df552fbf..228d9d22 100644 --- a/src/utils/AssetResolverHelper.ts +++ b/src/utils/AssetResolverHelper.ts @@ -10,9 +10,10 @@ function isDdo(arg: any): arg is DDO { return arg.id !== undefined } -export async function assetResolve(asset: DDO | string): Promise { - let ocean: Ocean - +export async function assetResolve( + asset: DDO | string, + ocean: Ocean +): Promise { if (isDdo(asset)) { const did = asset.id const ddo = asset diff --git a/test/integration/ComputeFlow.test.ts b/test/integration/ComputeFlow.test.ts index 6535c6d5..d3fec4bd 100644 --- a/test/integration/ComputeFlow.test.ts +++ b/test/integration/ComputeFlow.test.ts @@ -4,11 +4,7 @@ import { DataTokens } from '../../src/datatokens/Datatokens' import { Ocean } from '../../src/ocean/Ocean' import { ConfigHelper } from '../../src/utils/ConfigHelper' import { assert } from 'chai' -import { - Service, - ServiceComputePrivacy, - publisherTrustedAlgorithm -} from '../../src/ddo/interfaces/Service' +import { ServiceComputePrivacy } from '../../src/ddo/interfaces/Service' import Web3 from 'web3' import factory from '@oceanprotocol/contracts/artifacts/DTFactory.json' import datatokensTemplate from '@oceanprotocol/contracts/artifacts/DataTokenTemplate.json' @@ -860,8 +856,7 @@ describe('Compute flow', () => { algoDefinition, output, `${computeService.index}`, - computeService.type, - undefined + computeService.type ) assert(response, 'Compute error') jobId = response.jobId From 4e02a1b2a5edc3cde91cb60a7c6f98b7f7e7e793 Mon Sep 17 00:00:00 2001 From: Bogdan Fazakas Date: Wed, 9 Jun 2021 10:44:59 +0300 Subject: [PATCH 7/7] small refactor --- src/ocean/Compute.ts | 4 ++-- src/provider/Provider.ts | 2 +- src/utils/AssetResolverHelper.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ocean/Compute.ts b/src/ocean/Compute.ts index 25274483..92c51720 100644 --- a/src/ocean/Compute.ts +++ b/src/ocean/Compute.ts @@ -6,7 +6,7 @@ import { publisherTrustedAlgorithm } from '../ddo/interfaces/Service' import Account from './Account' -import { SubscribablePromise, assetResolve, AssetResolver } from '../utils' +import { SubscribablePromise, assetResolve, AssetResolved } from '../utils' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' import { ComputeOutput, @@ -413,7 +413,7 @@ export class Compute extends Instantiable { algorithm: ComputeAlgorithm, algorithmDDO?: DDO ): Promise { - const datasetResolved: AssetResolver = await assetResolve(dataset, this.ocean) + const datasetResolved: AssetResolved = await assetResolve(dataset, this.ocean) const service: Service = datasetResolved.ddo.findServiceById(serviceIndex) if (!service) return false if (service.type === 'compute') { diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index 4f3a317a..d1d0ecc2 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -1,5 +1,5 @@ import Account from '../ocean/Account' -import { noZeroX, assetResolve, AssetResolver } from '../utils' +import { noZeroX, assetResolve } from '../utils' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' import { File } from '../ddo/interfaces/File' import { diff --git a/src/utils/AssetResolverHelper.ts b/src/utils/AssetResolverHelper.ts index 228d9d22..1969c7f5 100644 --- a/src/utils/AssetResolverHelper.ts +++ b/src/utils/AssetResolverHelper.ts @@ -1,7 +1,7 @@ import { DDO } from '../ddo/DDO' import { Ocean } from '../ocean/Ocean' -export interface AssetResolver { +export interface AssetResolved { did: string ddo: DDO } @@ -13,7 +13,7 @@ function isDdo(arg: any): arg is DDO { export async function assetResolve( asset: DDO | string, ocean: Ocean -): Promise { +): Promise { if (isDdo(asset)) { const did = asset.id const ddo = asset