From c6876ca9e2734a9dcf8a8dd1ca8501f453af5cd5 Mon Sep 17 00:00:00 2001 From: ssallam Date: Thu, 16 Jan 2020 09:52:26 +0100 Subject: [PATCH] New template interface almost completed. --- ...terEscrowAccessSecretStoreTemplate.test.ts | 15 +- ...sterEscrowComputeExecutionTemplate.test.ts | 9 +- package-lock.json | 83 ++++----- src/keeper/Keeper.ts | 16 +- .../managers/AgreementStoreManager.ts | 12 ++ .../managers/TemplateStoreManager.ts | 53 ++++-- .../templates/AgreementTemplateBase.ts | 176 ++++++++++++++++-- .../EscrowAccessSecretStoreTemplate.ts | 6 +- .../EscrowComputeExecutionTemplate.ts | 4 +- src/keeper/contracts/templates/index.ts | 2 +- src/ocean/OceanAgreements.ts | 6 +- src/squid.ts | 1 - 12 files changed, 283 insertions(+), 100 deletions(-) diff --git a/integration/ocean/RegisterEscrowAccessSecretStoreTemplate.test.ts b/integration/ocean/RegisterEscrowAccessSecretStoreTemplate.test.ts index 0dd54c8..9100faa 100644 --- a/integration/ocean/RegisterEscrowAccessSecretStoreTemplate.test.ts +++ b/integration/ocean/RegisterEscrowAccessSecretStoreTemplate.test.ts @@ -48,7 +48,7 @@ describe('Register Escrow Access Secret Store Template', () => { describe('Propose and approve template', () => { it('should propose the template', async () => { await keeper.templateStoreManager.proposeTemplate( - template.getAddress(), + template.getId(), consumer.getId(), true ) @@ -58,7 +58,7 @@ describe('Register Escrow Access Secret Store Template', () => { it('should approve the template', async () => { await keeper.templateStoreManager.approveTemplate( - template.getAddress(), + template.getId(), templateManagerOwner.getId(), true ) @@ -122,7 +122,9 @@ describe('Register Escrow Access Secret Store Template', () => { }) it('should have condition instances asociated', async () => { - const conditionInstances = await template.getConditions() + const conditionInstances = (await template.getConditionTypes()).map(address => + keeper.getConditionByAddress(address) + ) assert.equal(conditionInstances.length, 3, 'Expected 3 conditions.') @@ -145,13 +147,14 @@ describe('Register Escrow Access Secret Store Template', () => { }) it('should create a new agreement', async () => { - const agreement = await template.createAgreement( + const agreement = await keeper.agreementStoreManager.createAgreement( agreementId, did, - [conditionIdAccess, conditionIdLock, conditionIdEscrow], + template.getId(), + [conditionIdLock, conditionIdAccess, conditionIdEscrow], [0, 0, 0], [0, 0, 0], - consumer.getId(), + [consumer.getId(), publisher.getId()], publisher.getId() ) diff --git a/integration/ocean/RegisterEscrowComputeExecutionTemplate.test.ts b/integration/ocean/RegisterEscrowComputeExecutionTemplate.test.ts index f885d53..89f05d1 100644 --- a/integration/ocean/RegisterEscrowComputeExecutionTemplate.test.ts +++ b/integration/ocean/RegisterEscrowComputeExecutionTemplate.test.ts @@ -48,7 +48,7 @@ describe('Register Escrow Compute Execution Template', () => { describe('Propose and approve template', () => { it('should propose the template', async () => { await keeper.templateStoreManager.proposeTemplate( - template.getAddress(), + template.getId(), consumer.getId(), true ) @@ -58,7 +58,7 @@ describe('Register Escrow Compute Execution Template', () => { it('should approve the template', async () => { await keeper.templateStoreManager.approveTemplate( - template.getAddress(), + template.getId(), templateManagerOwner.getId(), true ) @@ -145,13 +145,14 @@ describe('Register Escrow Compute Execution Template', () => { }) it('should create a new agreement', async () => { - const agreement = await template.createAgreement( + const agreement = await keeper.agreementStoreManager.createAgreement( agreementId, did, + template.getId(), [conditionIdCompute, conditionIdLock, conditionIdEscrow], [0, 0, 0], [0, 0, 0], - consumer.getId(), + [consumer.getId(), publisher.getId()], publisher.getId() ) diff --git a/package-lock.json b/package-lock.json index c4cd1bb..249bf29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -407,7 +407,7 @@ "ethereumjs-util": "^6.1.0", "ethereumjs-wallet": "^0.6.3", "web3": "1.2.1", - "web3-provider-engine": "git+https://github.com/trufflesuite/provider-engine.git#web3-one" + "web3-provider-engine": "git+https://github.com/trufflesuite/provider-engine.git#3538c60bc4836b73ccae1ac3f64c8fed8ef19c1a" }, "dependencies": { "eth-lib": { @@ -714,7 +714,7 @@ "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.1", - "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + "websocket": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e" }, "dependencies": { "nan": { @@ -1550,7 +1550,7 @@ }, "util": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -1707,7 +1707,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -1720,7 +1720,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -2514,7 +2514,7 @@ }, "bl": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", "requires": { "readable-stream": "^2.3.5", @@ -2627,7 +2627,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "requires": { "buffer-xor": "^1.0.3", @@ -2661,7 +2661,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "requires": { "bn.js": "^4.1.0", @@ -3626,7 +3626,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "requires": { "cipher-base": "^1.0.1", @@ -3638,7 +3638,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "requires": { "cipher-base": "^1.0.3", @@ -3881,12 +3881,12 @@ "dependencies": { "file-type": { "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" }, "get-stream": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", "requires": { "object-assign": "^4.0.1", @@ -4071,7 +4071,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "requires": { "bn.js": "^4.1.0", @@ -4867,7 +4867,7 @@ "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", "dev": true, "requires": { - "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git", + "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#1cfbb13862f90f0b391d8a699544d5fe4dfb8c7b", "ethereumjs-util": "^5.1.1" }, "dependencies": { @@ -6195,8 +6195,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6239,8 +6238,7 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", @@ -6251,8 +6249,7 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6369,8 +6366,7 @@ "inherits": { "version": "2.0.4", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6382,7 +6378,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6405,14 +6400,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6431,7 +6424,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -6521,8 +6513,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6534,7 +6525,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -6620,8 +6610,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -6657,7 +6646,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6677,7 +6665,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6721,14 +6708,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -8666,7 +8651,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "mem": { @@ -8865,7 +8850,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minipass": { @@ -8941,7 +8926,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -10120,7 +10105,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, @@ -10450,7 +10435,7 @@ }, "query-string": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "requires": { "decode-uri-component": "^0.2.0", @@ -10620,7 +10605,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -11312,7 +11297,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -11360,7 +11345,7 @@ }, "scrypt-js": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", + "resolved": "http://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" }, "scrypt.js": { @@ -11565,7 +11550,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "requires": { "inherits": "^2.0.1", @@ -12241,7 +12226,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -12584,7 +12569,7 @@ }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { diff --git a/src/keeper/Keeper.ts b/src/keeper/Keeper.ts index 517703c..0fd4954 100644 --- a/src/keeper/Keeper.ts +++ b/src/keeper/Keeper.ts @@ -11,7 +11,6 @@ import { ComputeExecutionCondition } from './contracts/conditions' import { - AgreementTemplate, EscrowAccessSecretStoreTemplate, EscrowComputeExecutionTemplate } from './contracts/templates' @@ -25,6 +24,7 @@ import { objectPromiseAll } from '../utils' import { EventHandler } from './EventHandler' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' +import { AgreementTemplateBase } from "./contracts/templates/AgreementTemplateBase"; /** * Interface with Ocean Keeper contracts. @@ -204,22 +204,22 @@ export class Keeper extends Instantiable { /** * Returns a template by name. * @param {string} name Template name. - * @return {AgreementTemplate} Agreement template instance. + * @return {AgreementTemplateBase} AgreementTemplateBase instance. */ - public getTemplateByName(name: string): AgreementTemplate { + public getTemplateByName(name: string): AgreementTemplateBase { return Object.values(this.templates).find( - template => template.contractName === name + template => template.templateName === name ) } /** * Returns a template by address. - * @param {string} address Template address. - * @return {AgreementTemplate} Agreement template instance. + * @param {string} templateId Template id (hex representation of bytes32). + * @return {AgreementTemplateBase} AgreementTemplateBase instance. */ - public getTemplateByAddress(address: string): AgreementTemplate { + public getTemplateById(templateId: string): AgreementTemplateBase { return Object.values(this.templates).find( - template => template.getAddress() === address + template => template.getId() === templateId ) } diff --git a/src/keeper/contracts/managers/AgreementStoreManager.ts b/src/keeper/contracts/managers/AgreementStoreManager.ts index 06d8d9f..948e70c 100644 --- a/src/keeper/contracts/managers/AgreementStoreManager.ts +++ b/src/keeper/contracts/managers/AgreementStoreManager.ts @@ -82,4 +82,16 @@ export class AgreementStoreManager extends ContractBase { from ) } + + /** + * Generates and returns the agreement creation event. + * @param {string} agreementId Agreement ID. + * @return {Event} Agreement created event. + */ + public getAgreementCreatedEvent(agreementId: string) { + return this.getEvent('AgreementCreated', { + agreementId: zeroX(agreementId) + }) + } + } diff --git a/src/keeper/contracts/managers/TemplateStoreManager.ts b/src/keeper/contracts/managers/TemplateStoreManager.ts index 5e48c7f..a6092b0 100644 --- a/src/keeper/contracts/managers/TemplateStoreManager.ts +++ b/src/keeper/contracts/managers/TemplateStoreManager.ts @@ -14,6 +14,8 @@ export interface TemplateMetadata { owner: string lastUpdatedBy: string blockNumberUpdated: number + conditionTypes: string[] + actorTypeIds: string[] } export class TemplateStoreManager extends ContractBase { @@ -27,54 +29,77 @@ export class TemplateStoreManager extends ContractBase { return templateStoreManeger } + public generateId(templateName: string) { + return this.call( + "generateId", + [templateName] + ) + } + public getOwner(): Promise { return this.call('owner', []) } - public async proposeTemplate(address: string, from?: string, ignoreExists?: boolean) { - const template = await this.getTemplate(address) + public async proposeTemplate(templateId: string, from?: string, ignoreExists?: boolean) { + const template = await this.getTemplate(templateId) if (template.blockNumberUpdated !== 0) { - this.logger.warn(`Template "${address}" already exist.`) + this.logger.warn(`Template "${templateId}" already exist.`) if (!ignoreExists) { throw new Error('Template already exist.') } } else { - return this.sendFrom('proposeTemplate', [zeroX(address)], from) + return this.sendFrom('proposeTemplate', [zeroX(templateId)], from) } } public async approveTemplate( - address: string, + templateId: string, from?: string, ignoreApproved?: boolean ) { - const template = await this.getTemplate(address) + const template = await this.getTemplate(templateId) if (template.state !== TemplateState.Proposed) { - this.logger.warn(`Template "${address}" is not in "proposed" state.`) + this.logger.warn(`Template "${templateId}" is not in "proposed" state.`) if (!ignoreApproved) { throw new Error(`Template not in "proposed" state.`) } } else { - return this.sendFrom('approveTemplate', [zeroX(address)], from) + return this.sendFrom('approveTemplate', [zeroX(templateId)], from) } } - public revokeTemplate(address: string, from?: string) { - return this.sendFrom('revokeTemplate', [zeroX(address)], from) + public revokeTemplate(templateId: string, from?: string) { + return this.sendFrom('revokeTemplate', [zeroX(templateId)], from) } - public async getTemplate(address: string) { + public async getConditionTypes(templateId: string): Promise { + const { conditionTypes } = await this.getTemplate(templateId) + return conditionTypes + } + + public getConditions(conditionTypes: string[]) { + return conditionTypes.map(address => + this.ocean.keeper.getConditionByAddress(address) + ) + } + + public async getTemplate(templateId: string) { const { state, owner, lastUpdatedBy, - blockNumberUpdated - } = await this.call('getTemplate', [zeroX(address)]) + blockNumberUpdated, + conditionTypes, + actorTypeIds + } = await this.call('getTemplate', [zeroX(templateId)]) return { state: +state, owner, lastUpdatedBy, - blockNumberUpdated: +blockNumberUpdated + blockNumberUpdated: +blockNumberUpdated, + conditionTypes, + actorTypeIds + } as TemplateMetadata } } diff --git a/src/keeper/contracts/templates/AgreementTemplateBase.ts b/src/keeper/contracts/templates/AgreementTemplateBase.ts index 11a3840..a5c3962 100644 --- a/src/keeper/contracts/templates/AgreementTemplateBase.ts +++ b/src/keeper/contracts/templates/AgreementTemplateBase.ts @@ -1,12 +1,14 @@ import { escrowAccessServiceAgreementTemplate } from './EscrowAccess.serviceAgreementTemplate' -import { TemplateStoreManager, AgreementStoreManager } from '../managers' +import {TemplateStoreManager, AgreementStoreManager, ConditionStoreManager} from '../managers' import DIDRegistry from '../DIDRegistry' import { LockRewardCondition } from '../conditions/LockRewardCondition' import { AccessSecretStoreCondition } from '../conditions/AccessSecretStoreCondition' import { EscrowReward } from '../conditions/EscrowReward' import { DDO } from '../../../ddo/DDO' -import { generateId, zeroX } from '../../../utils' -import { ComputeExecutionCondition } from '../conditions' +import {generateId, LoggerInstance, Logger, zeroX} from '../../../utils' + +import {ComputeExecutionCondition, Condition, ConditionState, conditionStateNames} from '../conditions' + export interface Conditions { lockRewardCondition: LockRewardCondition @@ -15,8 +17,20 @@ export interface Conditions { escrowReward: EscrowReward } + +export interface AgreementConditionsStatus { + [condition: string]: { + condition: string + contractName: string + state: ConditionState + blocked: boolean + blockedBy: string[] + } +} + + export class AgreementTemplateBase { - public static templateName: string + public templateName: string public templateManager: TemplateStoreManager @@ -26,6 +40,8 @@ export class AgreementTemplateBase { public conditions: Conditions + private logger: Logger + public constructor( templateManager: TemplateStoreManager, agreementStoreManager: AgreementStoreManager, @@ -36,10 +52,8 @@ export class AgreementTemplateBase { this.agreementStoreManager = agreementStoreManager this.didRegistry = didRegistry this.conditions = conditions - } - public async getServiceAgreementTemplate() { - return escrowAccessServiceAgreementTemplate + this.logger = LoggerInstance } public async createAgreementFromDDO( @@ -99,14 +113,15 @@ export class AgreementTemplateBase { ) const publisher = await this.didRegistry.getDIDOwner(did) - + const timeouts = [0, 0, 0] + const timelocks = [0, 0, 0] await this.agreementStoreManager.createAgreement( agreementId, did, this.getId(), conditionIds, - [0, 0, 0], - [0, 0, 0], + timelocks, + timeouts, [consumer, publisher], from ) @@ -119,7 +134,146 @@ export class AgreementTemplateBase { did: string, amount: number | string, consumer: string - ): Promise { + ): Promise { return null } + + // getAgreementData + /** + * Conditions address list. + * @return {Promise} Conditions address. + */ + public getConditionTypes(): Promise { + return this.templateManager.getConditionTypes(this.getId()) + } + + /** + * List of condition contracts. + * @return {Promise} Conditions contracts. + */ + public async getConditions(): Promise { + return this.templateManager.getConditions(await this.getConditionTypes()) + } + + public async getServiceAgreementTemplate() { + return null + } + + public async getServiceAgreementTemplateConditions() { + const serviceAgreementTemplate = await this.getServiceAgreementTemplate() + return serviceAgreementTemplate.conditions + } + + public async getServiceAgreementTemplateConditionByRef(ref: string) { + const name = (await this.getServiceAgreementTemplateConditions()).find( + ({ name: conditionRef }) => conditionRef === ref + ).contractName + return (await this.getConditions()).find( + condition => condition.contractName === name + ) + } + + public async getServiceAgreementTemplateDependencies() { + const serviceAgreementTemplate = await this.getServiceAgreementTemplate() + return serviceAgreementTemplate.conditionDependency + } + + /** + * Returns the status of the conditions. + * @param {string} agreementId Agreement ID. + * @param {ConditionStoreManager} conditionStoreManager + * @return {Promise} Conditions status. + */ + public async getAgreementStatus( + agreementId: string, conditionStoreManager: ConditionStoreManager + ): Promise { + + const dependencies = await this.getServiceAgreementTemplateDependencies() + const { conditionIds } = await this.agreementStoreManager.getAgreement(agreementId) + + if (!conditionIds.length) { + // this.logger.error(`Agreement not creeated yet: "${agreementId}"`) + return false + } + + const conditionIdByCondition = (await this.getConditions()).reduce( + (acc, { contractName }, i) => ({ + ...acc, + [contractName]: conditionIds[i] + }), + {} + ) + + const statesPromises = Object.keys(dependencies).map(async (ref, i) => { + const { contractName } = await this.getServiceAgreementTemplateConditionByRef( + ref + ) + return { + ref, + contractName, + state: ( + await conditionStoreManager.getCondition( + conditionIdByCondition[contractName] + ) + ).state + } + }) + const states = await Promise.all(statesPromises) + + return states.reduce((acc, { contractName, ref, state }) => { + const blockers = dependencies[ref] + .map(dependency => states.find(_ => _.ref === dependency)) + .filter(condition => condition.state !== ConditionState.Fulfilled) + return { + ...acc, + [ref]: { + condition: ref, + contractName, + state, + blocked: !!blockers.length, + blockedBy: blockers.map(_ => _.ref) + } + } + }, {}) + } + + /** + * Prints the agreement status. + * @param {string} agreementId Agreement ID. + * @param {ConditionStoreManager} conditionStoreManager + */ + public async printAgreementStatus(agreementId: string, conditionStoreManager: ConditionStoreManager) { + const status = await this.getAgreementStatus(agreementId, conditionStoreManager) + + this.logger.bypass('-'.repeat(80)) + this.logger.bypass('Template:', this.templateName) + this.logger.bypass('Agreement ID:', agreementId) + this.logger.bypass('-'.repeat(40)) + if (!status) { + this.logger.bypass('Agreement not created yet!') + } + Object.values(status || []).forEach( + ({ condition, contractName, state, blocked, blockedBy }, i) => { + if (i) { + this.logger.bypass('-'.repeat(20)) + } + this.logger.bypass(`${condition} (${contractName})`) + this.logger.bypass(' Status:', state, `(${conditionStateNames[state]})`) + if (blocked) { + this.logger.bypass(' Blocked by:', blockedBy) + } + } + ) + this.logger.bypass('-'.repeat(80)) + } + + /** + * Generates and returns the agreement creation event. + * @param {string} agreementId Agreement ID. + * @return {Event} Agreement created event. + */ + public getAgreementCreatedEvent(agreementId: string) { + return this.agreementStoreManager.getAgreementCreatedEvent(agreementId) + } + } diff --git a/src/keeper/contracts/templates/EscrowAccessSecretStoreTemplate.ts b/src/keeper/contracts/templates/EscrowAccessSecretStoreTemplate.ts index a906514..b93e885 100644 --- a/src/keeper/contracts/templates/EscrowAccessSecretStoreTemplate.ts +++ b/src/keeper/contracts/templates/EscrowAccessSecretStoreTemplate.ts @@ -41,6 +41,10 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplateBase { accessSecretStoreConditionId ) - return [lockRewardConditionId, accessSecretStoreConditionId, escrowRewardId] + return [ + lockRewardConditionId, + accessSecretStoreConditionId, + escrowRewardId + ] } } diff --git a/src/keeper/contracts/templates/EscrowComputeExecutionTemplate.ts b/src/keeper/contracts/templates/EscrowComputeExecutionTemplate.ts index 0bf41b1..6636ad9 100644 --- a/src/keeper/contracts/templates/EscrowComputeExecutionTemplate.ts +++ b/src/keeper/contracts/templates/EscrowComputeExecutionTemplate.ts @@ -41,10 +41,10 @@ export class EscrowComputeExecutionTemplate extends AgreementTemplateBase { computeExecutionConditionId ) - return { + return [ lockRewardConditionId, computeExecutionConditionId, escrowRewardId - } + ] } } diff --git a/src/keeper/contracts/templates/index.ts b/src/keeper/contracts/templates/index.ts index b8c2746..3aa871d 100644 --- a/src/keeper/contracts/templates/index.ts +++ b/src/keeper/contracts/templates/index.ts @@ -1,4 +1,4 @@ -export * from './AgreementTemplate.abstract' +export * from './AgreementTemplateBase' export { BaseEscrowTemplate } from './BaseEscrowTemplate.abstract' export { EscrowAccessSecretStoreTemplate } from './EscrowAccessSecretStoreTemplate' export { EscrowComputeExecutionTemplate } from './EscrowComputeExecutionTemplate' diff --git a/src/ocean/OceanAgreements.ts b/src/ocean/OceanAgreements.ts index 5a1bd9e..c7855d7 100644 --- a/src/ocean/OceanAgreements.ts +++ b/src/ocean/OceanAgreements.ts @@ -3,7 +3,7 @@ import Account from './Account' import DID from './DID' import { zeroX, didPrefixed } from '../utils' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' -import { AgreementConditionsStatus } from '../keeper/contracts/templates/AgreementTemplate.abstract' +import { AgreementConditionsStatus } from '../keeper/contracts/templates/AgreementTemplateBase' import { ConditionState } from '../keeper/contracts/conditions/Condition.abstract' import { OceanAgreementsConditions } from './OceanAgreementsConditions' @@ -150,8 +150,8 @@ export class OceanAgreements extends Instantiable { agreementId ) const fullStatus = await this.ocean.keeper - .getTemplateByAddress(templateId) - .getAgreementStatus(agreementId) + .getTemplateById(templateId) + .getAgreementStatus(agreementId, this.ocean.keeper.conditionStoreManager) if (!fullStatus) { return diff --git a/src/squid.ts b/src/squid.ts index 973039f..5ef4ec6 100644 --- a/src/squid.ts +++ b/src/squid.ts @@ -21,7 +21,6 @@ export { OceanPlatformVersions } from './ocean/OceanVersions' -export { AgreementTemplate } from './keeper/contracts/templates' export { Condition, ConditionState } from './keeper/contracts/conditions' export { Ocean, Account, Config, DID, Logger, Keeper, conditions, templates, utils }