diff --git a/src/ocean/ServiceAgreement.ts b/src/ocean/ServiceAgreement.ts index d2b1cec..e836781 100644 --- a/src/ocean/ServiceAgreement.ts +++ b/src/ocean/ServiceAgreement.ts @@ -8,26 +8,35 @@ import ServiceAgreementTemplate from "./ServiceAgreementTemplate" export default class ServiceAgreement extends OceanBase { - public static async signServiceAgreement(serviceAgreementTemplate: ServiceAgreementTemplate, publisher: Account, - did: string, assetId: string, consumer: Account): - Promise { + public static async createServiceAgreement(serviceAgreementTemplate: ServiceAgreementTemplate, assetId: string, + did: string, consumer: Account, publisher: Account) { + // todo: this should come from ddo const serviceAgreementId = IdGenerator.generateId() - - const valueHashes = [ - ServiceAgreement.hashSingleValue("bool", true), - ServiceAgreement.hashSingleValue("bool", false), - ServiceAgreement.hashSingleValue("uint", 120), - // assetId - ServiceAgreement.hashSingleValue("string", assetId), + const timeoutValues = [0, 0, 0, 500] // timeout 500 blocks @ condition 4 + const values = [ + {type: "bool", value: true}, + {type: "bool", value: false}, + {type: "uint", value: 120}, + {type: "string", value: assetId}, ] - const timeoutValues = [0, 0, 0, 500] // timeout 500 blocks @ condition 4 + const saHashSig = await ServiceAgreement.createSAHashSignature(serviceAgreementTemplate, serviceAgreementId, + values, timeoutValues, consumer) - const serviceAgreementHash = ServiceAgreement.hashServiceAgreement(serviceAgreementTemplate, valueHashes, - timeoutValues, serviceAgreementId) - const serviceAgreementHashSignature = - await Web3Provider.getWeb3().eth.sign(serviceAgreementHash, consumer.getId()) + const serviceAgreement: ServiceAgreement = await ServiceAgreement.signServiceAgreement(serviceAgreementTemplate, + serviceAgreementId, assetId, did, values, timeoutValues, saHashSig, consumer, publisher) + + return serviceAgreement + } + + private static async signServiceAgreement(serviceAgreementTemplate: ServiceAgreementTemplate, + serviceAgreementId: string, assetId: string, did: string, values: any[], + timeoutValues: number[], serviceAgreementHashSignature: string, + consumer: Account, publisher: Account): + Promise { + + const valueHashes = ServiceAgreement.createValueHashes(values) const serviceAgreement: ServiceAgreementContract = await ServiceAgreementContract.getInstance() @@ -49,11 +58,31 @@ export default class ServiceAgreement extends OceanBase { ) } - protected static hashSingleValue(type: string, value: any): string { + private static createValueHashes(values: any[]): any[] { + return values.map((value) => { + return ServiceAgreement.hashSingleValue(value.type, value.value) + }) + } + + private static hashSingleValue(type: string, value: any): string { const args = {type, value} return Web3Provider.getWeb3().utils.soliditySha3(args).toString("hex") } + private static async createSAHashSignature(serviceAgreementTemplate: ServiceAgreementTemplate, + serviceAgreementId: string, values: any[], timeoutValues: number[], + consumer: Account): Promise { + + const valueHashes = ServiceAgreement.createValueHashes(values) + + const serviceAgreementHash = ServiceAgreement.hashServiceAgreement(serviceAgreementTemplate, valueHashes, + timeoutValues, serviceAgreementId) + const serviceAgreementHashSignature = + await Web3Provider.getWeb3().eth.sign(serviceAgreementHash, consumer.getId()) + + return serviceAgreementHashSignature + } + private static hashServiceAgreement(serviceAgreementTemplate: ServiceAgreementTemplate, valueHashes: string[], timeouts: number[], serviceAgreementId: string) { const args = [ diff --git a/src/ocean/ServiceAgreementTemplate.ts b/src/ocean/ServiceAgreementTemplate.ts index da3d004..330ac76 100644 --- a/src/ocean/ServiceAgreementTemplate.ts +++ b/src/ocean/ServiceAgreementTemplate.ts @@ -7,18 +7,16 @@ import OceanBase from "./OceanBase" export default class ServiceAgreementTemplate extends OceanBase { - public static async registerServiceAgreementsTemplate(serviceName: string, templateOwner: Account): + public static async registerServiceAgreementsTemplate(serviceName: string, methods: string[], + dependencyMatrix: number[], templateOwner: Account): Promise { - const methodReflections: MethodReflection[] = [ - await ContractReflector.reflectContractMethod("PaymentConditions.lockPayment"), - await ContractReflector.reflectContractMethod("AccessConditions.grantAccess"), - await ContractReflector.reflectContractMethod("PaymentConditions.releasePayment"), - await ContractReflector.reflectContractMethod("PaymentConditions.refundPayment"), - ] - - // tslint:disable - const dependencyMatrix = [0, 1, 4, 1 | 2 ** 4 | 2 ** 5] // dependency bit | timeout bit + const methodReflections: MethodReflection[] = + await Promise.all(methods.map(async (method) => { + const methodReflection = await + ContractReflector.reflectContractMethod(method) + return methodReflection + })) const serviceAgreement: ServiceAgreement = await ServiceAgreement.getInstance() diff --git a/test/ocean/ServiceAgreement.test.ts b/test/ocean/ServiceAgreement.test.ts index a9e1b8b..15ed40d 100644 --- a/test/ocean/ServiceAgreement.test.ts +++ b/test/ocean/ServiceAgreement.test.ts @@ -29,20 +29,29 @@ describe("ServiceAgreement", () => { consumerAccount = accounts[2] const resourceName = "superb car data" - testServiceAgreementTemplate = - await ServiceAgreementTemplate.registerServiceAgreementsTemplate(resourceName, templateOwnerAccount) + const methods: string[] = [ + "PaymentConditions.lockPayment", + "AccessConditions.grantAccess", + "PaymentConditions.releasePayment", + "PaymentConditions.refundPayment", + ] + // tslint:disable + const dependencyMatrix = [0, 1, 4, 1 | 2 ** 4 | 2 ** 5] // dependency bit | timeout bit + testServiceAgreementTemplate = + await ServiceAgreementTemplate.registerServiceAgreementsTemplate(resourceName, methods, + dependencyMatrix, templateOwnerAccount) }) - describe("#executeServiceAgreement()", () => { + describe("#createServiceAgreement()", () => { it("should execute an service agreement", async () => { const did: string = IdGenerator.generateId() const assetId: string = IdGenerator.generateId() const serviceAgreement: ServiceAgreement = - await ServiceAgreement.signServiceAgreement(testServiceAgreementTemplate, publisherAccount, - did, assetId, consumerAccount) + await ServiceAgreement.createServiceAgreement(testServiceAgreementTemplate, assetId, did, + consumerAccount, publisherAccount) assert(serviceAgreement) const id = serviceAgreement.getId() @@ -58,8 +67,8 @@ describe("ServiceAgreement", () => { const assetId: string = IdGenerator.generateId() const serviceAgreement: ServiceAgreement = - await ServiceAgreement.signServiceAgreement(testServiceAgreementTemplate, publisherAccount, - did, assetId, consumerAccount) + await ServiceAgreement.createServiceAgreement(testServiceAgreementTemplate, assetId, did, + consumerAccount, publisherAccount) assert(serviceAgreement) const status = await serviceAgreement.getStatus() @@ -73,13 +82,9 @@ describe("ServiceAgreement", () => { const did: string = IdGenerator.generateId() const assetId: string = IdGenerator.generateId() - const resourceName = "nice service" - const serviceAgreementTemplate = - await ServiceAgreementTemplate.registerServiceAgreementsTemplate(resourceName, templateOwnerAccount) - const serviceAgreement: ServiceAgreement = - await ServiceAgreement.signServiceAgreement(serviceAgreementTemplate, publisherAccount, - did, assetId, consumerAccount) + await ServiceAgreement.createServiceAgreement(testServiceAgreementTemplate, assetId, did, + consumerAccount, publisherAccount) assert(serviceAgreement) const fulfilled: boolean = await serviceAgreement.grantAccess(did, IdGenerator.generateId()) diff --git a/test/ocean/ServiceAgreementTemplate.test.ts b/test/ocean/ServiceAgreementTemplate.test.ts index 719a9f0..d44c7b4 100644 --- a/test/ocean/ServiceAgreementTemplate.test.ts +++ b/test/ocean/ServiceAgreementTemplate.test.ts @@ -8,6 +8,14 @@ import config from "../config" let ocean: Ocean let accounts: Account[] +const methods: string[] = [ + "PaymentConditions.lockPayment", + "AccessConditions.grantAccess", + "PaymentConditions.releasePayment", + "PaymentConditions.refundPayment", +] +// tslint:disable +const dependencyMatrix = [0, 1, 4, 1 | 2 ** 4 | 2 ** 5] // dependency bit | timeout bit describe("ServiceAgreementTemplate", () => { @@ -22,9 +30,11 @@ describe("ServiceAgreementTemplate", () => { it("should setup an agreement template", async () => { const templateOwner = accounts[0] - const resourceName = "test data" + const resourceName = "consume" const serviceAgreementTemplate: ServiceAgreementTemplate = - await ServiceAgreementTemplate.registerServiceAgreementsTemplate(resourceName, templateOwner) + await ServiceAgreementTemplate.registerServiceAgreementsTemplate(resourceName, methods, + dependencyMatrix, templateOwner) + assert(serviceAgreementTemplate) assert(serviceAgreementTemplate.getId()) assert(serviceAgreementTemplate.getOwner().getId() === templateOwner.getId()) @@ -35,9 +45,12 @@ describe("ServiceAgreementTemplate", () => { it("should get the status of a newly deployed agreement template", async () => { const publisherAccount = accounts[0] - const resourceName = "template status" + const resourceName = "consume" + const serviceAgreementTemplate: ServiceAgreementTemplate = - await ServiceAgreementTemplate.registerServiceAgreementsTemplate(resourceName, publisherAccount) + await ServiceAgreementTemplate.registerServiceAgreementsTemplate(resourceName, methods, + dependencyMatrix, publisherAccount) + assert(serviceAgreementTemplate) const templateStatus = await serviceAgreementTemplate.getStatus() assert(templateStatus === true)