diff --git a/src/ocean/Compute.ts b/src/ocean/Compute.ts index 7a132d1a..5796bd8f 100644 --- a/src/ocean/Compute.ts +++ b/src/ocean/Compute.ts @@ -284,6 +284,62 @@ export class Compute extends Instantiable { owner: output.owner || consumerAccount.getId() } } + + /** + * Starts an order of a compute service that is defined in an asset's services. + * @param {Account} 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 {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. + * @return {Promise} Returns the Service Agreement ID, representation of `bytes32` ID. + * + * Note: algorithmDid and algorithmMeta are optional, but if they are not passed, + * you can end up in the situation that you are ordering and paying for your agreement, + * but brizo will not allow the compute, due to privacy settings of the ddo + */ + public order( + consumerAccount: string, + datasetDid: string, + serviceIndex: number, + algorithmDid?: string, + algorithmMeta?: MetadataAlgorithm + ): SubscribablePromise { + return new SubscribablePromise(async (observer) => { + const ddo: DDO = await this.ocean.assets.resolve(datasetDid) + // const service: Service = ddo.findServiceByType('compute') + const service: Service = ddo.findServiceById(serviceIndex) + if (!service) return null + if (service.type !== 'compute') return null + if (algorithmMeta) { + // check if raw algo is allowed + if (service.attributes.main.privacy) + if (!service.attributes.main.privacy.allowRawAlgorithm) { + console.error('This service does not allow Raw Algo') + return null + } + } + if (algorithmDid) { + // check if did is in trusted list + if (service.attributes.main.privacy) + if (service.attributes.main.privacy.trustedAlgorithms) + if (service.attributes.main.privacy.trustedAlgorithms.length > 0) + if ( + !service.attributes.main.privacy.trustedAlgorithms.includes( + algorithmDid + ) + ) { + console.error('This service does not allow this Algo') + return null + } + } + const order = await this.ocean.assets.order( + datasetDid, + service.type, + consumerAccount + ) + return order + }) + } } // "creator": "0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e", // "datePublished": "2019-04-09T19:02:11Z", diff --git a/test/integration/ComputeFlow.test.ts b/test/integration/ComputeFlow.test.ts index 86d314b4..bf5520fb 100644 --- a/test/integration/ComputeFlow.test.ts +++ b/test/integration/ComputeFlow.test.ts @@ -46,6 +46,18 @@ describe('Marketplace flow', () => { const tokenAmount = 100 const timeout = 86400 + const algorithmMeta = { + language: 'js', + format: 'docker-image', + version: '0.1', + url: + 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', + container: { + entrypoint: 'node $ALGO', + image: 'node', + tag: '10' + } + } describe('#MarketplaceComputeFlow-Test', () => { it('Initialize Ocean contracts v3', async () => { @@ -101,7 +113,7 @@ describe('Marketplace flow', () => { } }) - it('Alice publishes dataset with a compute service', async () => { + it('Alice publishes dataset with a compute service that allows Raw Algo', async () => { price = 10 // in datatoken cluster = ocean.compute.createClusterAttributes( 'Kubernetes', @@ -133,12 +145,17 @@ describe('Marketplace flow', () => { containers, servers ) - + const origComputePrivacy = { + allowRawAlgorithm: true, + allowNetworkAccess: false, + trustedAlgorithms: [] + } const computeService = ocean.compute.createComputeService( alice, price, dateCreated, - provider + provider, + origComputePrivacy as ServiceComputePrivacy ) ddo = await ocean.assets.create(asset, alice, [computeService], tokenAddress) assert(ddo.dataToken === tokenAddress) @@ -254,25 +271,15 @@ describe('Marketplace flow', () => { }) it('Bob starts compute job with a raw Algo', async () => { - const algorithmMeta = { - language: 'js', - format: 'docker-image', - version: '0.1', - url: - 'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js', - container: { - entrypoint: 'node $ALGO', - image: 'node', - tag: '10' - } - } - const output = {} - const order = await ocean.assets.order( + const order = await ocean.compute.order( + bob.getId(), ddo.id, - computeService.type, - bob.getId() + computeService.index, + undefined, + algorithmMeta ) + assert(order != null) const computeOrder = JSON.parse(order) const tx = await datatoken.transfer( computeOrder['dataToken'], @@ -306,8 +313,30 @@ describe('Marketplace flow', () => { assert(response.length > 0) }) - // it('should not allow order the compute service with raw algo for dataset that does not allow raw algo', async () => {}) - // it('should not allow order the compute service with did != did:op:1234 for dataset that allows only did:op:1234 as algo', async () => {}) + it('should not allow order the compute service with raw algo for dataset that does not allow raw algo', async () => { + const service1 = datasetNoRawAlgo.findServiceByType('compute') + assert(service1 !== null) + const order = await ocean.compute.order( + bob.getId(), + datasetNoRawAlgo.id, + service1.index, + undefined, + algorithmMeta + ) + assert(order === null) + }) + it('should not allow order the compute service with algoDid != "did:op:1234" for dataset that allows only "did:op:1234" as algo', async () => { + const service1 = datasetWithTrustedAlgo.findServiceByType('compute') + assert(service1 !== null) + const order = await ocean.compute.order( + bob.getId(), + datasetWithTrustedAlgo.id, + service1.index, + 'did:op:77777', + undefined + ) + assert(order === null) + }) // it('should start a compute job with a published algo', async () => { // it('Bob restarts compute job', async () => {}) // it('Bob gets outputs', async () => {})