diff --git a/src/aquarius/Aquarius.ts b/src/aquarius/Aquarius.ts index b5e03b4..f945251 100644 --- a/src/aquarius/Aquarius.ts +++ b/src/aquarius/Aquarius.ts @@ -37,42 +37,50 @@ export default class Aquarius { return accessUrl } - public async queryMetadata(query: SearchQuery): Promise { + public async queryMetadata(query: SearchQuery): Promise { - const result = await AquariusConnectorProvider.getConnector() + const result: DDO[] = await AquariusConnectorProvider.getConnector() .post(this.url + "/api/v1/aquarius/assets/ddo/query", JSON.stringify(query)) .then((response: any) => { if (response.ok) { return response.json() } Logger.error("queryMetadata failed:", response.status, response.statusText) - return null + return [] + }) + .then((res: string) => { + return JSON.parse(res) as DDO[] }) .catch((error) => { Logger.error("Error fetching querying metadata: ", error) + return [] }) return result } - public async queryMetadataByText(query: SearchQuery): Promise { + public async queryMetadataByText(query: SearchQuery): Promise { const fullUrl = new URL(this.url + "/api/v1/aquarius/assets/ddo/query") fullUrl.searchParams.append("text", query.text) - fullUrl.searchParams.append("sort", JSON.stringify(query.sort)) + fullUrl.searchParams.append("sort", decodeURIComponent(JSON.stringify(query.sort))) fullUrl.searchParams.append("offset", query.offset.toString()) fullUrl.searchParams.append("page", query.page.toString()) - const result = await AquariusConnectorProvider.getConnector() + const result: DDO[] = await AquariusConnectorProvider.getConnector() .get(fullUrl) .then((response: any) => { if (response.ok) { return response.json() } Logger.log("queryMetadataByText failed:", response.status, response.statusText) - return null + return [] + }) + .then((res: string) => { + return JSON.parse(res) as DDO[] }) .catch((error) => { Logger.error("Error fetching querying metadata: ", error) + return [] }) return result diff --git a/src/ddo/MetaData.ts b/src/ddo/MetaData.ts index ac1989b..237a43a 100644 --- a/src/ddo/MetaData.ts +++ b/src/ddo/MetaData.ts @@ -3,52 +3,65 @@ import Curation from "./Curation" import MetaDataBase from "./MetaDataBase" import StructuredMarkup from "./StructuredMarkup" +const base: MetaDataBase = { + name: "UK Weather information 2011", + type: "dataset", + description: "Weather information of UK including temperature and humidity", + size: "3.1gb", + dateCreated: "2012-02-01T10:55:11+00:00", + author: "Met Office", + license: "CC-BY", + copyrightHolder: "Met Office", + encoding: "UTF-8", + compression: "zip", + contentType: "text/csv", + // tslint:disable-next-line + workExample: "stationId,latitude,longitude,datetime,temperature,humidity423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68", + contentUrls: [ + "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip", + ], + links: [ + {sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"}, + {sample2: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/"}, + {fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/"}, + ], + inLanguage: "en", + tags: "weather, uk, 2011, temperature, humidity", + price: 10, +} as MetaDataBase + +const curation: Curation = { + rating: 0.93, + numVotes: 123, + schema: "Binary Votting", +} as Curation + +const additionalInformation: AdditionalInformation = { + updateFrecuency: "yearly", + structuredMarkup: [ + { + uri: "http://skos.um.es/unescothes/C01194/jsonld", + mediaType: "application/ld+json", + } as StructuredMarkup, + { + uri: "http://skos.um.es/unescothes/C01194/turtle", + mediaType: "text/turtle", + } as StructuredMarkup, + ], +} as AdditionalInformation + export default class MetaData { - public base: MetaDataBase = { - name: "UK Weather information 2011", - type: "dataset", - description: "Weather information of UK including temperature and humidity", - size: "3.1gb", - dateCreated: "2012-02-01T10:55:11+00:00", - author: "Met Office", - license: "CC-BY", - copyrightHolder: "Met Office", - encoding: "UTF-8", - compression: "zip", - contentType: "text/csv", - // tslint:disable-next-line - workExample: "stationId,latitude,longitude,datetime,temperature,humidity423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68", - contentUrls: [ - "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip", - ], - links: [ - {sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"}, - {sample2: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/"}, - {fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/"}, - ], - inLanguage: "en", - tags: "weather, uk, 2011, temperature, humidity", - price: 10, - } as MetaDataBase + public base: MetaDataBase + public curation: Curation + public additionalInformation: AdditionalInformation - public curation: Curation = { - rating: 0.93, - numVotes: 123, - schema: "Binary Votting", - } as Curation + constructor(metaData?: MetaData) { + this.base = metaData ? metaData.base ? metaData.base : base : base + this.curation = metaData ? metaData.curation ? metaData.curation : curation : curation + this.additionalInformation = metaData ? + metaData.additionalInformation ? metaData.additionalInformation : + additionalInformation : additionalInformation + } - public additionalInformation: AdditionalInformation = { - updateFrecuency: "yearly", - structuredMarkup: [ - { - uri: "http://skos.um.es/unescothes/C01194/jsonld", - mediaType: "application/ld+json", - } as StructuredMarkup, - { - uri: "http://skos.um.es/unescothes/C01194/turtle", - mediaType: "text/turtle", - } as StructuredMarkup, - ], - } as AdditionalInformation } diff --git a/src/examples/ExecuteAgreement.ts b/src/examples/ExecuteAgreement.ts new file mode 100644 index 0000000..2bb81a2 --- /dev/null +++ b/src/examples/ExecuteAgreement.ts @@ -0,0 +1,59 @@ +import DDO from "../ddo/DDO" +import MetaData from "../ddo/MetaData" +import MetaDataBase from "../ddo/MetaDataBase" +import {Account, Logger, Ocean, ServiceAgreement} from "../squid" + +(async () => { + const ocean: Ocean = await Ocean.getInstance({ + nodeUri: "http://localhost:8545", + aquariusUri: "http://localhost:5000", + brizoUri: "https://localhost:8030", + parityUri: "http://localhost:9545", + secretStoreUri: "https://secret-store.dev-ocean.com", + threshold: 2, + password: "unittest", + address: "0xed243adfb84a6626eba46178ccb567481c6e655d", + }) + + const publisher: Account = (await ocean.getAccounts())[0] + const consumer: Account = (await ocean.getAccounts())[1] + + const metaData = new MetaData({ + base: { + name: "Office Humidity", + type: "dataset", + description: "Weather information of UK including temperature and humidity", + size: "3.1gb", + dateCreated: "2012-02-01T10:55:11+00:00", + author: "Met Office", + license: "CC-BY", + copyrightHolder: "Met Office", + encoding: "UTF-8", + compression: "zip", + contentType: "text/csv", + // tslint:disable-next-line + workExample: "stationId,latitude,longitude,datetime,temperature,humidity423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68", + contentUrls: [ + "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip", + ], + links: [ + {sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"}, + {sample2: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/"}, + {fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/"}, + ], + inLanguage: "en", + tags: "weather, uk, 2011, temperature, humidity", + price: 10, + } as MetaDataBase, + } as MetaData) + + const ddo: DDO = await ocean.registerAsset(metaData, publisher) + Logger.log(ddo.id) + + const serviceAgreementSignature: string = await ocean.signServiceAgreement(ddo.id, consumer) + Logger.log(serviceAgreementSignature) + + const serviceAgreement: ServiceAgreement = await ocean.executeServiceAgreement(ddo.id, serviceAgreementSignature, + consumer, publisher) + Logger.log(serviceAgreement) +})() diff --git a/src/examples/Register.ts b/src/examples/Register.ts index ce08f85..96d177e 100644 --- a/src/examples/Register.ts +++ b/src/examples/Register.ts @@ -1,5 +1,6 @@ import DDO from "../ddo/DDO" import MetaData from "../ddo/MetaData" +import MetaDataBase from "../ddo/MetaDataBase" import {Account, Logger, Ocean} from "../squid" (async () => { @@ -16,6 +17,35 @@ import {Account, Logger, Ocean} from "../squid" const publisher: Account = (await ocean.getAccounts())[0] - const ddo: DDO = await ocean.registerAsset(new MetaData(), publisher) + const metaData = new MetaData({ + base: { + name: "Office Humidity", + type: "dataset", + description: "Weather information of UK including temperature and humidity", + size: "3.1gb", + dateCreated: "2012-02-01T10:55:11+00:00", + author: "Met Office", + license: "CC-BY", + copyrightHolder: "Met Office", + encoding: "UTF-8", + compression: "zip", + contentType: "text/csv", + // tslint:disable-next-line + workExample: "stationId,latitude,longitude,datetime,temperature,humidity423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68", + contentUrls: [ + "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip", + ], + links: [ + {sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"}, + {sample2: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/"}, + {fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/"}, + ], + inLanguage: "en", + tags: "weather, uk, 2011, temperature, humidity", + price: 10, + } as MetaDataBase, + } as MetaData) + + const ddo: DDO = await ocean.registerAsset(metaData, publisher) Logger.log(ddo.id) })() diff --git a/src/examples/Search.ts b/src/examples/Search.ts new file mode 100644 index 0000000..8e661a1 --- /dev/null +++ b/src/examples/Search.ts @@ -0,0 +1,22 @@ +import DDO from "../ddo/DDO" +import {Logger, Ocean} from "../squid" + +(async () => { + const ocean: Ocean = await Ocean.getInstance({ + nodeUri: "http://localhost:8545", + aquariusUri: "http://localhost:5000", + brizoUri: "https://localhost:8030", + parityUri: "http://localhost:9545", + secretStoreUri: "https://secret-store.dev-ocean.com", + threshold: 2, + password: "unittest", + address: "0xed243adfb84a6626eba46178ccb567481c6e655d", + }) + + const result: DDO[] = await ocean.searchAssetsByText("Office Humidity") + const dids = result.map((res: DDO) => { + return res.id + }) + + Logger.log(dids.length, JSON.stringify(dids, null, 2)) +})() diff --git a/src/examples/SignAgreement.ts b/src/examples/SignAgreement.ts new file mode 100644 index 0000000..e0900f1 --- /dev/null +++ b/src/examples/SignAgreement.ts @@ -0,0 +1,55 @@ +import DDO from "../ddo/DDO" +import MetaData from "../ddo/MetaData" +import MetaDataBase from "../ddo/MetaDataBase" +import {Account, Logger, Ocean} from "../squid" + +(async () => { + const ocean: Ocean = await Ocean.getInstance({ + nodeUri: "http://localhost:8545", + aquariusUri: "http://localhost:5000", + brizoUri: "https://localhost:8030", + parityUri: "http://localhost:9545", + secretStoreUri: "https://secret-store.dev-ocean.com", + threshold: 2, + password: "unittest", + address: "0xed243adfb84a6626eba46178ccb567481c6e655d", + }) + + const publisher: Account = (await ocean.getAccounts())[0] + const consumer: Account = (await ocean.getAccounts())[1] + + const metaData = new MetaData({ + base: { + name: "Office Humidity", + type: "dataset", + description: "Weather information of UK including temperature and humidity", + size: "3.1gb", + dateCreated: "2012-02-01T10:55:11+00:00", + author: "Met Office", + license: "CC-BY", + copyrightHolder: "Met Office", + encoding: "UTF-8", + compression: "zip", + contentType: "text/csv", + // tslint:disable-next-line + workExample: "stationId,latitude,longitude,datetime,temperature,humidity423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68", + contentUrls: [ + "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip", + ], + links: [ + {sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"}, + {sample2: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/"}, + {fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/"}, + ], + inLanguage: "en", + tags: "weather, uk, 2011, temperature, humidity", + price: 10, + } as MetaDataBase, + } as MetaData) + + const ddo: DDO = await ocean.registerAsset(metaData, publisher) + Logger.log(ddo.id) + + const serviceAgreementSignature = await ocean.signServiceAgreement(ddo.id, consumer) + Logger.log(serviceAgreementSignature) +})() diff --git a/src/ocean/Ocean.ts b/src/ocean/Ocean.ts index edc494a..7f3afb7 100644 --- a/src/ocean/Ocean.ts +++ b/src/ocean/Ocean.ts @@ -85,6 +85,7 @@ export default class Ocean { parameters: condition.methodReflection.inputs.map((input: ValuePair) => { return { ...input, + // todo: change remove, move to execute value: "xxx", } as Parameter }), @@ -118,21 +119,18 @@ export default class Ocean { { type: template.templateName, purchaseEndpoint: this.brizo.getPurchaseEndpoint(), + serviceEndpoint: this.brizo.getConsumeEndpoint(publisher.getId(), + serviceDefinitionId, metadata.base.contentUrls[0]), // the id of the service agreement? serviceDefinitionId, // the id of the service agreement template templateId: serviceAgreementTemplate.getId(), conditions: ddoConditions, } as Service, - { - serviceEndpoint: this.brizo.getConsumeEndpoint(publisher.getId(), - serviceDefinitionId, metadata.base.contentUrls[0]), - type: "Consume", - } as Service, { serviceEndpoint: this.brizo.getComputeEndpoint(publisher.getId(), serviceDefinitionId, "xxx", "xxx"), - type: "Consume", + type: "Compute", } as Service, { type: "Metadata", @@ -150,27 +148,39 @@ export default class Ocean { return storedDdo } - public async purchase(did: string, consumer: Account): Promise { + public async signServiceAgreement(did: string, consumer: Account): Promise { const ddo = await AquariusProvider.getAquarius().retrieveDDO(did) const id = did.replace("did:op:", "") const serviceAgreementId: string = IdGenerator.generateId() - const serviceAgreement: ServiceAgreement = await ServiceAgreement.signServiceAgreement(id, - // todo get publisher from ddo - ddo, serviceAgreementId, consumer, new Account()) + const serviceAgrementSignature: string = await ServiceAgreement.signServiceAgreement(id, + ddo, serviceAgreementId, consumer) - return serviceAgreement + return serviceAgrementSignature } - public async searchAssets(query: SearchQuery): Promise { + public async executeServiceAgreement(did: string, serviceAgreementSignature: string, + consumer: Account, publisher: Account): Promise { + + const ddo = await AquariusProvider.getAquarius().retrieveDDO(did) + const id = did.replace("did:op:", "") + + const serviceAgreementId: string = IdGenerator.generateId() + const serviceAgrement: ServiceAgreement = await ServiceAgreement.executeServiceAgreement(id, + ddo, serviceAgreementId, serviceAgreementSignature, consumer, publisher) + + return serviceAgrement + } + + public async searchAssets(query: SearchQuery): Promise { return this.aquarius.queryMetadata(query) } - public async searchAssetsByText(text: string): Promise { + public async searchAssetsByText(text: string): Promise { return this.aquarius.queryMetadataByText({ text, - page: 1, + page: 0, offset: 100, query: { value: 1, diff --git a/src/ocean/ServiceAgreements/ServiceAgreement.ts b/src/ocean/ServiceAgreements/ServiceAgreement.ts index 09d4c29..fbcb405 100644 --- a/src/ocean/ServiceAgreements/ServiceAgreement.ts +++ b/src/ocean/ServiceAgreements/ServiceAgreement.ts @@ -8,9 +8,8 @@ import OceanBase from "../OceanBase" export default class ServiceAgreement extends OceanBase { - public static async signServiceAgreement(assetId: string, ddo: DDO, serviceAgreementId: string, consumer: Account, - publisher: Account): - Promise { + public static async signServiceAgreement(assetId: string, ddo: DDO, serviceAgreementId: string, consumer: Account): + Promise { const values: ValuePair[] = ServiceAgreement.getValuesFromDDO(ddo, serviceAgreementId) const valueHashes = ServiceAgreement.createValueHashes(values) @@ -19,14 +18,25 @@ export default class ServiceAgreement extends OceanBase { const serviceAgreementHashSignature = await ServiceAgreement.createSAHashSignature(ddo, serviceAgreementId, values, valueHashes, timeoutValues, consumer) + return serviceAgreementHashSignature + } + + public static async executeServiceAgreement(assetId: string, ddo: DDO, serviceAgreementId: string, + serviceAgreementHashSignature: string, consumer: Account, + publisher: Account): Promise { + + const values: ValuePair[] = ServiceAgreement.getValuesFromDDO(ddo, serviceAgreementId) + const valueHashes = ServiceAgreement.createValueHashes(values) + const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromDDO(ddo) + const serviceAgreement: ServiceAgreement = await ServiceAgreement.executeAgreement(ddo, serviceAgreementId, values, valueHashes, timeoutValues, serviceAgreementHashSignature, consumer, publisher) return serviceAgreement } - public static async createSAHashSignature(ddo: DDO, serviceAgreementId: string, values: ValuePair[], - valueHashes: string[], timeoutValues: number[], consumer: Account): + private static async createSAHashSignature(ddo: DDO, serviceAgreementId: string, values: ValuePair[], + valueHashes: string[], timeoutValues: number[], consumer: Account): Promise { const conditionKeys: string[] = ddo.service[0].conditions.map((condition) => { diff --git a/test/ocean/ServiceAgreement.test.ts b/test/ocean/ServiceAgreement.test.ts index cf6e4fe..a11666e 100644 --- a/test/ocean/ServiceAgreement.test.ts +++ b/test/ocean/ServiceAgreement.test.ts @@ -66,6 +66,25 @@ describe("ServiceAgreement", () => { }) describe("#signServiceAgreement()", () => { + it("should sign an service agreement", async () => { + + const id: string = IdGenerator.generateId() + const did: string = `did:op:${id}` + const ddo = new DDO({id: did, service: serviceDefinition}) + const assetId: string = IdGenerator.generateId() + const serviceAgreementId: string = IdGenerator.generateId() + + // @ts-ignore + AquariusConnectorProvider.setConnector(new AquariusConnectorMock(ddo)) + const serviceAgreementSignature: string = + await ServiceAgreement.signServiceAgreement(assetId, ddo, serviceAgreementId, consumerAccount) + + assert(serviceAgreementSignature) + assert(serviceAgreementSignature.startsWith("0x")) + }) + }) + + describe("#executeServiceAgreement()", () => { it("should execute an service agreement", async () => { const id: string = IdGenerator.generateId() @@ -76,9 +95,12 @@ describe("ServiceAgreement", () => { // @ts-ignore AquariusConnectorProvider.setConnector(new AquariusConnectorMock(ddo)) + const serviceAgreementSignature: string = + await ServiceAgreement.signServiceAgreement(assetId, ddo, serviceAgreementId, consumerAccount) + const serviceAgreement: ServiceAgreement = - await ServiceAgreement.signServiceAgreement(assetId, ddo, serviceAgreementId, consumerAccount, - publisherAccount) + await ServiceAgreement.executeServiceAgreement(assetId, ddo, serviceAgreementId, + serviceAgreementSignature, consumerAccount, publisherAccount) assert(serviceAgreement) const serviceDefinitionId = serviceAgreement.getId() @@ -98,9 +120,13 @@ describe("ServiceAgreement", () => { // @ts-ignore AquariusConnectorProvider.setConnector(new AquariusConnectorMock(ddo)) + const serviceAgreementSignature: string = + await ServiceAgreement.signServiceAgreement(assetId, ddo, serviceAgreementId, consumerAccount) + assert(serviceAgreementSignature) + const serviceAgreement: ServiceAgreement = - await ServiceAgreement.signServiceAgreement(assetId, ddo, serviceAgreementId, consumerAccount, - publisherAccount) + await ServiceAgreement.executeServiceAgreement(assetId, ddo, serviceAgreementId, + serviceAgreementSignature, consumerAccount, publisherAccount) assert(serviceAgreement) const status = await serviceAgreement.getStatus() @@ -119,9 +145,13 @@ describe("ServiceAgreement", () => { // @ts-ignore AquariusConnectorProvider.setConnector(new AquariusConnectorMock(ddo)) + const serviceAgreementSignature: string = + await ServiceAgreement.signServiceAgreement(assetId, ddo, serviceAgreementId, consumerAccount) + assert(serviceAgreementSignature) + const serviceAgreement: ServiceAgreement = - await ServiceAgreement.signServiceAgreement(assetId, ddo, serviceAgreementId, consumerAccount, - publisherAccount) + await ServiceAgreement.executeServiceAgreement(assetId, ddo, serviceAgreementId, + serviceAgreementSignature, consumerAccount, publisherAccount) assert(serviceAgreement) const fulfilled: boolean = await serviceAgreement.grantAccess(assetId, IdGenerator.generateId())