mirror of
https://github.com/oceanprotocol-archive/squid-js.git
synced 2024-02-02 15:31:51 +01:00
Merge branch 'master' into feature/transferOwnership
This commit is contained in:
commit
204c5645b8
@ -24,9 +24,9 @@ before_script:
|
||||
- git clone https://github.com/oceanprotocol/barge
|
||||
- cd barge
|
||||
- export AQUARIUS_VERSION=unstable
|
||||
- export BRIZO_VERSION=v0.8.1
|
||||
- export BRIZO_VERSION=v0.9.3
|
||||
- export KEEPER_VERSION=v0.13.2
|
||||
- export EVENTS_HANDLER_VERSION=v0.4.4
|
||||
- export EVENTS_HANDLER_VERSION=v0.4.5
|
||||
- export KEEPER_OWNER_ROLE_ADDRESS="0xe2DD09d719Da89e5a3D0F2549c7E24566e947260"
|
||||
- rm -rf "${HOME}/.ocean/keeper-contracts/artifacts"
|
||||
- bash -x start_ocean.sh --no-commons --no-dashboard 2>&1 > start_ocean.log &
|
||||
|
58
CHANGELOG.md
58
CHANGELOG.md
@ -4,24 +4,70 @@ All notable changes to this project will be documented in this file. Dates are d
|
||||
|
||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
|
||||
#### [v1.3.0](https://github.com/oceanprotocol/squid-js/compare/v1.2.0...v1.3.0)
|
||||
#### [v2.0.0-beta.5](https://github.com/oceanprotocol/squid-js/compare/2.0.0-beta.4...v2.0.0-beta.5)
|
||||
|
||||
> 10 March 2020
|
||||
|
||||
- Update the compute condition name in ddo jason definition. [`#380`](https://github.com/oceanprotocol/squid-js/pull/380)
|
||||
|
||||
#### [2.0.0-beta.4](https://github.com/oceanprotocol/squid-js/compare/v2.0.0-beta.3...2.0.0-beta.4)
|
||||
|
||||
> 6 March 2020
|
||||
|
||||
- v2: Compute to Data [`#350`](https://github.com/oceanprotocol/squid-js/pull/350)
|
||||
- Fix style issues and failing unit tests. [`c26ae88`](https://github.com/oceanprotocol/squid-js/commit/c26ae88fa3d63a65b7cba38224cbdcb23cbe6685)
|
||||
- Fix publishing compute service (fill in parameters value in agreement conditions). Update agreement template events and conditions in the sample json. [`75a0ef0`](https://github.com/oceanprotocol/squid-js/commit/75a0ef05d9789a9358180707b28bad95a84d6499)
|
||||
- Return proper value from the compute endpoints. [`e2ed974`](https://github.com/oceanprotocol/squid-js/commit/e2ed974af27c7b828980919cb2846fc514fda142)
|
||||
|
||||
#### [v2.0.0-beta.3](https://github.com/oceanprotocol/squid-js/compare/v2.0.0-beta.2...v2.0.0-beta.3)
|
||||
|
||||
> 20 February 2020
|
||||
|
||||
- Adding output section [`#372`](https://github.com/oceanprotocol/squid-js/pull/372)
|
||||
- add Output Object passed to brizo [`a60e415`](https://github.com/oceanprotocol/squid-js/commit/a60e4159255aadeba00bec2e72cf0fbb4b71489c)
|
||||
- lint fix [`6e2289b`](https://github.com/oceanprotocol/squid-js/commit/6e2289b27ddc8643076385ee3fe8cfb743d4ecfb)
|
||||
- add Output interface [`9cf716e`](https://github.com/oceanprotocol/squid-js/commit/9cf716ebe472ec24603c1bcf052848ad4464d9dd)
|
||||
|
||||
#### [v2.0.0-beta.2](https://github.com/oceanprotocol/squid-js/compare/v1.3.0...v2.0.0-beta.2)
|
||||
|
||||
> 31 January 2020
|
||||
|
||||
- Release 2.0.0-beta.2 [`4e45a77`](https://github.com/oceanprotocol/squid-js/commit/4e45a773d67b0f4199ffd5eae00b06213ba5622f)
|
||||
|
||||
#### [v2.0.0-beta.1](https://github.com/oceanprotocol/squid-js/compare/v2.0.0-beta.0...v2.0.0-beta.1)
|
||||
|
||||
> 28 January 2020
|
||||
|
||||
- remove `index` parameter from ocean.assets.consume() [`138a6bf`](https://github.com/oceanprotocol/squid-js/commit/138a6bf75abc402396606fab3bc3701875d7a393)
|
||||
- Release 2.0.0-beta.1 [`1d7105c`](https://github.com/oceanprotocol/squid-js/commit/1d7105cfb1e80cb45711517ae6840d9ac22e80a6)
|
||||
|
||||
#### [v2.0.0-beta.0](https://github.com/oceanprotocol/squid-js/compare/v1.2.0...v2.0.0-beta.0)
|
||||
|
||||
> 28 January 2020
|
||||
|
||||
- Update cross-env to the latest version 🚀 [`#363`](https://github.com/oceanprotocol/squid-js/pull/363)
|
||||
- Update mocha to the latest version 🚀 [`#364`](https://github.com/oceanprotocol/squid-js/pull/364)
|
||||
- new ocean.utils.services [`40754ca`](https://github.com/oceanprotocol/squid-js/commit/40754ca46a10578cfdf0f460a7c33ba37bb2ffde)
|
||||
- DDO & compute test tweaks [`e7acadb`](https://github.com/oceanprotocol/squid-js/commit/e7acadb2fe91739eee1bff3589801f12c7ab0b1b)
|
||||
- test data consolidation [`ac39369`](https://github.com/oceanprotocol/squid-js/commit/ac39369543779370b9be6f00b0f2063a7e50c763)
|
||||
|
||||
#### [v1.3.0](https://github.com/oceanprotocol/squid-js/compare/v2.0.0-beta.1...v1.3.0)
|
||||
|
||||
> 31 January 2020
|
||||
|
||||
- switch to @ethereum-navigator for network lookup [`#366`](https://github.com/oceanprotocol/squid-js/pull/366)
|
||||
- consolidate test files [`#371`](https://github.com/oceanprotocol/squid-js/pull/371)
|
||||
- package updates [`#368`](https://github.com/oceanprotocol/squid-js/pull/368)
|
||||
- Update cross-env to the latest version 🚀 [`#363`](https://github.com/oceanprotocol/squid-js/pull/363)
|
||||
- Update mocha to the latest version 🚀 [`#364`](https://github.com/oceanprotocol/squid-js/pull/364)
|
||||
- chore(package): update lockfile package-lock.json [`46c4def`](https://github.com/oceanprotocol/squid-js/commit/46c4defee5beb43fbea41006c5957d086721aff9)
|
||||
- switch to @ethereum-navigator/navigator for network lookup [`92dbaae`](https://github.com/oceanprotocol/squid-js/commit/92dbaaeb25b26e28df644be356c347058ca1256a)
|
||||
- chore(package): update lockfile package-lock.json [`eb141a6`](https://github.com/oceanprotocol/squid-js/commit/eb141a6d3d3131a65e4385f781568d015dac8429)
|
||||
- service interface refactor and cleanup [`768c69b`](https://github.com/oceanprotocol/squid-js/commit/768c69bdbdc0591e2e747d87082e859bc52cd7d2)
|
||||
- fix compute unit tests [`e37420d`](https://github.com/oceanprotocol/squid-js/commit/e37420dabfd23d5f307be695992cac7324d47dd0)
|
||||
- job status cleanup [`f11eaca`](https://github.com/oceanprotocol/squid-js/commit/f11eacaabdc15285ba78a8096e492fd8863c933a)
|
||||
|
||||
#### [v1.2.0](https://github.com/oceanprotocol/squid-js/compare/v1.1.0...v1.2.0)
|
||||
|
||||
> 23 January 2020
|
||||
|
||||
- Decouple aquarius from ocean [`#354`](https://github.com/oceanprotocol/squid-js/pull/354)
|
||||
- merge fixes [`c8ea5f7`](https://github.com/oceanprotocol/squid-js/commit/c8ea5f77c2ec541fdbfb6f77cdabcd5691e4bffa)
|
||||
- Release 1.2.0 [`56f7d11`](https://github.com/oceanprotocol/squid-js/commit/56f7d1113a6aa1f3318040fb32cfdcc22f5dc13b)
|
||||
|
||||
#### [v1.1.0](https://github.com/oceanprotocol/squid-js/compare/v1.1.0-beta.0...v1.1.0)
|
||||
|
30
MIGRATION.md
30
MIGRATION.md
@ -1,6 +1,34 @@
|
||||
# Migration Guide
|
||||
|
||||
Instructions on how to migrate between breaking versions.
|
||||
Instructions on how to migrate between versions with breaking changes.
|
||||
|
||||
## v1.2.0 → v2.0.0
|
||||
|
||||
### Ocean Protocol Components Requirements
|
||||
|
||||
squid-js v2.0.0 only works against:
|
||||
|
||||
- Aquarius v1.0.7+
|
||||
- Brizo v0.9.3+
|
||||
- Events Handler v0.4.5+
|
||||
- Keeper Contracts v0.13.2+
|
||||
|
||||
### Service index parameter removal from `ocean.assets` methods
|
||||
|
||||
Removes the need to get the respective service from the DDO, the `ocean.assets` methods will now do this on their own automatically.
|
||||
|
||||
```js
|
||||
// old
|
||||
const service = ddo.findServiceByType('access')
|
||||
const did = ddo.id
|
||||
const agreementId = await ocean.assets.order(did, service.index, account)
|
||||
const path = await ocean.assets.consume(agreementId, did, service.index, account, folder)
|
||||
|
||||
// NEW
|
||||
const did = ddo.id
|
||||
const agreementId = await ocean.assets.order(did, account)
|
||||
const path = await ocean.assets.consume(agreementId, did, account, folder)
|
||||
```
|
||||
|
||||
## v0.8.3 → v1.0.0
|
||||
|
||||
|
@ -11,15 +11,15 @@
|
||||
},
|
||||
{
|
||||
"name": "brizo",
|
||||
"version": "~0.8.1"
|
||||
"version": "~0.9.0"
|
||||
},
|
||||
{
|
||||
"name": "aquarius",
|
||||
"version": "~1.0.5"
|
||||
"version": "~1.0.7"
|
||||
},
|
||||
{
|
||||
"name": "events-handler",
|
||||
"version": "~0.4.1"
|
||||
"version": "~0.4.4"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
2641
package-lock.json
generated
2641
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
36
package.json
36
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@oceanprotocol/squid",
|
||||
"version": "1.3.0",
|
||||
"version": "2.0.0-beta.5",
|
||||
"description": "JavaScript client library for Ocean Protocol",
|
||||
"main": "./dist/node/squid.js",
|
||||
"typings": "./dist/node/squid.d.ts",
|
||||
@ -58,41 +58,43 @@
|
||||
"deprecated-decorator": "^0.1.6",
|
||||
"node-fetch": "^2.6.0",
|
||||
"save-file": "^2.3.1",
|
||||
"uuid": "^3.4.0",
|
||||
"web3": "^1.2.5",
|
||||
"uuid": "^7.0.2",
|
||||
"web3": "^1.2.6",
|
||||
"whatwg-url": "^8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@release-it/bumper": "^1.0.5",
|
||||
"@truffle/hdwallet-provider": "^1.0.29",
|
||||
"@types/chai": "^4.2.8",
|
||||
"@release-it/bumper": "^1.1.0",
|
||||
"@truffle/hdwallet-provider": "^1.0.33",
|
||||
"@types/chai": "^4.2.11",
|
||||
"@types/chai-spies": "^1.0.1",
|
||||
"@types/mocha": "^7.0.1",
|
||||
"@types/node": "^13.5.1",
|
||||
"@types/node-fetch": "^2.5.4",
|
||||
"@typescript-eslint/eslint-plugin": "^2.18.0",
|
||||
"@typescript-eslint/parser": "^2.18.0",
|
||||
"@types/mocha": "^7.0.2",
|
||||
"@types/node": "^13.9.1",
|
||||
"@types/node-fetch": "^2.5.5",
|
||||
"@types/sinon": "^7.5.2",
|
||||
"@typescript-eslint/eslint-plugin": "^2.23.0",
|
||||
"@typescript-eslint/parser": "^2.23.0",
|
||||
"auto-changelog": "^1.16.2",
|
||||
"chai": "^4.2.0",
|
||||
"chai-spies": "^1.0.0",
|
||||
"cross-env": "^7.0.0",
|
||||
"cross-env": "^7.0.2",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-oceanprotocol": "^1.5.0",
|
||||
"eslint-config-prettier": "^6.10.0",
|
||||
"eslint-plugin-prettier": "^3.1.2",
|
||||
"lcov-result-merger": "^3.1.0",
|
||||
"mocha": "^7.0.1",
|
||||
"mocha": "^7.1.0",
|
||||
"mock-local-storage": "^1.1.11",
|
||||
"nyc": "^15.0.0",
|
||||
"ora": "^4.0.2",
|
||||
"prettier": "^1.19.1",
|
||||
"sinon": "^9.0.1",
|
||||
"source-map-support": "^0.5.16",
|
||||
"ts-node": "^8.6.2",
|
||||
"typedoc": "^0.16.9",
|
||||
"typescript": "^3.7.5",
|
||||
"typedoc": "^0.17.1",
|
||||
"typescript": "^3.8.3",
|
||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||
"webpack": "^4.41.5",
|
||||
"webpack-cli": "^3.3.10",
|
||||
"webpack": "^4.42.0",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-merge": "^4.2.2"
|
||||
},
|
||||
"nyc": {
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { File } from '../ddo/MetaData'
|
||||
import { File, MetaDataAlgorithm } from '../ddo/MetaData'
|
||||
import Account from '../ocean/Account'
|
||||
import { noZeroX } from '../utils'
|
||||
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
|
||||
import { DDO } from '../ddo/DDO'
|
||||
import { ServiceType } from '../ddo/Service'
|
||||
import { ComputeJob, Output } from '../ocean/OceanCompute'
|
||||
|
||||
const apiPath = '/api/v1/brizo/services'
|
||||
|
||||
@ -35,15 +38,22 @@ export class Brizo extends Instantiable {
|
||||
return `${this.url}${apiPath}/publish`
|
||||
}
|
||||
|
||||
public getComputeEndpoint(
|
||||
pubKey: string,
|
||||
serviceIndex: number,
|
||||
_notUsed: string,
|
||||
container: string
|
||||
) {
|
||||
public getComputeEndpoint() {
|
||||
return `${this.url}${apiPath}/compute`
|
||||
}
|
||||
|
||||
public async getEndpointFromAgreement(
|
||||
type: ServiceType,
|
||||
agreementId: string
|
||||
): Promise<string> {
|
||||
const { assets, keeper } = this.ocean
|
||||
const { did } = await keeper.agreementStoreManager.getAgreement(agreementId)
|
||||
const ddo: DDO = await assets.resolve(did)
|
||||
const { serviceEndpoint } = ddo.findServiceByType(type)
|
||||
|
||||
return serviceEndpoint
|
||||
}
|
||||
|
||||
public async initializeServiceAgreement(
|
||||
did: string,
|
||||
serviceAgreementId: string,
|
||||
@ -78,12 +88,7 @@ export class Brizo extends Instantiable {
|
||||
destination: string,
|
||||
index: number = -1
|
||||
): Promise<string> {
|
||||
const signature =
|
||||
(await account.getToken()) ||
|
||||
(await this.ocean.utils.signature.signText(
|
||||
noZeroX(agreementId),
|
||||
account.getId()
|
||||
))
|
||||
const signature = await this.createSignature(account, agreementId)
|
||||
const filesPromises = files
|
||||
.filter((_, i) => index === -1 || i === index)
|
||||
.map(async ({ index: i }) => {
|
||||
@ -105,6 +110,93 @@ export class Brizo extends Instantiable {
|
||||
return destination
|
||||
}
|
||||
|
||||
public async compute(
|
||||
method: string,
|
||||
serviceAgreementId: string,
|
||||
consumerAccount: Account,
|
||||
algorithmDid?: string,
|
||||
algorithmMeta?: MetaDataAlgorithm,
|
||||
jobId?: string,
|
||||
output?: Output
|
||||
): Promise<ComputeJob | ComputeJob[]> {
|
||||
const signature = await this.createSignature(consumerAccount, serviceAgreementId)
|
||||
const address = consumerAccount.getId()
|
||||
const serviceEndpoint = await this.getEndpointFromAgreement(
|
||||
'compute',
|
||||
serviceAgreementId
|
||||
)
|
||||
|
||||
if (!serviceEndpoint) {
|
||||
throw new Error(
|
||||
'Computing on asset failed, service definition is missing the `serviceEndpoint`.'
|
||||
)
|
||||
}
|
||||
|
||||
// construct Brizo URL
|
||||
let url = serviceEndpoint
|
||||
url += `?signature=${signature}`
|
||||
url += `&consumerAddress=${address}`
|
||||
url += `&serviceAgreementId=${noZeroX(serviceAgreementId)}`
|
||||
url += (algorithmDid && `&algorithmDid=${algorithmDid}`) || ''
|
||||
url +=
|
||||
(algorithmMeta &&
|
||||
`&algorithmMeta=${encodeURIComponent(JSON.stringify(algorithmMeta))}`) ||
|
||||
''
|
||||
url += (output && `&output=${JSON.stringify(output)}`) || ''
|
||||
url += (jobId && `&jobId=${jobId}`) || ''
|
||||
|
||||
// switch fetch method
|
||||
let fetch
|
||||
|
||||
switch (method) {
|
||||
case 'post':
|
||||
fetch = this.ocean.utils.fetch.post(url, '')
|
||||
break
|
||||
case 'put':
|
||||
fetch = this.ocean.utils.fetch.put(url, '')
|
||||
break
|
||||
case 'delete':
|
||||
fetch = this.ocean.utils.fetch.delete(url)
|
||||
break
|
||||
default:
|
||||
fetch = this.ocean.utils.fetch.get(url)
|
||||
break
|
||||
}
|
||||
|
||||
const result = await fetch
|
||||
.then((response: any) => {
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
}
|
||||
|
||||
this.logger.error(
|
||||
'Compute job failed:',
|
||||
response.status,
|
||||
response.statusText
|
||||
)
|
||||
|
||||
return null
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
this.logger.error('Error with compute job')
|
||||
this.logger.error(error.message)
|
||||
throw error
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
public async createSignature(account: Account, agreementId: string): Promise<string> {
|
||||
const signature =
|
||||
(await account.getToken()) ||
|
||||
(await this.ocean.utils.signature.signText(
|
||||
noZeroX(agreementId),
|
||||
account.getId()
|
||||
))
|
||||
|
||||
return signature
|
||||
}
|
||||
|
||||
public async encrypt(
|
||||
did: string,
|
||||
signature: string,
|
||||
|
@ -1,25 +0,0 @@
|
||||
export interface Provider {
|
||||
type: string
|
||||
description: string
|
||||
environment: {
|
||||
cluster: {
|
||||
type: string
|
||||
url: string
|
||||
}
|
||||
supportedContainers: {
|
||||
image: string
|
||||
tag: string
|
||||
checksum: string
|
||||
}[]
|
||||
supportedServers: {
|
||||
serverId: string
|
||||
serverType: string
|
||||
price: string
|
||||
cpu: string
|
||||
gpu: string
|
||||
memory: string
|
||||
disk: string
|
||||
maxExecutionTime: number
|
||||
}[]
|
||||
}
|
||||
}
|
@ -1,72 +1,3 @@
|
||||
export interface StageRequirements {
|
||||
container: {
|
||||
image: string
|
||||
tag: string
|
||||
checksum: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface StageInput {
|
||||
index: number
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface StageTransformation {
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface StageOutput {
|
||||
metadataUrl: string
|
||||
secretStoreUrl: string
|
||||
accessProxyUrl: string
|
||||
metadata: MetaDataMain
|
||||
}
|
||||
|
||||
export interface Stage {
|
||||
index: number
|
||||
stageType?: string
|
||||
requirements: StageRequirements
|
||||
input: StageInput
|
||||
transformation: StageTransformation
|
||||
output: StageOutput
|
||||
}
|
||||
|
||||
export interface Workflow {
|
||||
stages: Stage[]
|
||||
}
|
||||
|
||||
export interface Algorithm {
|
||||
language: string
|
||||
format?: string
|
||||
version?: string
|
||||
entrypoint: string
|
||||
requirements: {
|
||||
requirement: string
|
||||
version: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface ServiceDefinition {
|
||||
auth: {
|
||||
type: string
|
||||
user?: string
|
||||
password?: string
|
||||
token?: string
|
||||
}
|
||||
endpoints: {
|
||||
index: number
|
||||
url: string
|
||||
method: string
|
||||
contentTypes: string[]
|
||||
}
|
||||
}
|
||||
|
||||
export interface Service {
|
||||
spec?: string
|
||||
specChecksum?: string
|
||||
definition: ServiceDefinition
|
||||
}
|
||||
|
||||
export interface File {
|
||||
/**
|
||||
* File name.
|
||||
@ -132,6 +63,19 @@ export interface File {
|
||||
compression?: string
|
||||
}
|
||||
|
||||
export interface MetaDataAlgorithm {
|
||||
url?: string
|
||||
rawcode?: string
|
||||
language?: string
|
||||
format?: string
|
||||
version?: string
|
||||
container: {
|
||||
entrypoint: string
|
||||
image: string
|
||||
tag: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main attributes of assets metadata.
|
||||
* @see https://github.com/oceanprotocol/OEPs/tree/master/8
|
||||
@ -145,12 +89,11 @@ export interface MetaDataMain {
|
||||
name: string
|
||||
|
||||
/**
|
||||
* Type of the Asset. Helps to filter by the type of asset,
|
||||
* initially ("dataset", "algorithm", "container", "workflow", "other").
|
||||
* Type of the Asset. Helps to filter by the type of asset ("dataset" or "algorithm").
|
||||
* @type {string}
|
||||
* @example "dataset"
|
||||
*/
|
||||
type: 'dataset' | 'algorithm' | 'container' | 'workflow' | 'other'
|
||||
type: 'dataset' | 'algorithm'
|
||||
|
||||
/**
|
||||
* The date on which the asset was created by the originator in
|
||||
@ -185,7 +128,7 @@ export interface MetaDataMain {
|
||||
license: string
|
||||
|
||||
/**
|
||||
* Price of the asset.
|
||||
* Price of the asset in vodka (attoOCEAN). It must be an integer encoded as a string.
|
||||
* @type {string}
|
||||
* @example "1000000000000000000"
|
||||
*/
|
||||
@ -197,13 +140,11 @@ export interface MetaDataMain {
|
||||
*/
|
||||
files: File[]
|
||||
|
||||
encryptedService?: any
|
||||
|
||||
workflow?: Workflow
|
||||
|
||||
algorithm?: Algorithm
|
||||
|
||||
service?: Service
|
||||
/**
|
||||
* Metadata used only for assets with type `algorithm`.
|
||||
* @type {MetaDataAlgorithm}
|
||||
*/
|
||||
algorithm?: MetaDataAlgorithm
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,21 +1,65 @@
|
||||
import { MetaData } from './MetaData'
|
||||
import { ServiceAgreementTemplate } from './ServiceAgreementTemplate'
|
||||
import { Provider } from './ComputingProvider'
|
||||
|
||||
export type ServiceType =
|
||||
| 'authorization'
|
||||
| 'metadata'
|
||||
| 'access'
|
||||
| 'compute'
|
||||
| 'computing'
|
||||
| 'fitchainCompute'
|
||||
export type ServiceType = 'authorization' | 'metadata' | 'access' | 'compute'
|
||||
|
||||
export interface ServiceCommon {
|
||||
type: ServiceType
|
||||
index: number
|
||||
serviceEndpoint?: string
|
||||
attributes: any & {
|
||||
main: { [key: string]: any }
|
||||
attributes: ServiceCommonAttributes
|
||||
}
|
||||
|
||||
export interface ServiceCommonAttributes {
|
||||
main: { [key: string]: any }
|
||||
additionalInformation?: { [key: string]: any }
|
||||
serviceAgreementTemplate?: ServiceAgreementTemplate
|
||||
}
|
||||
|
||||
export interface ServiceAccessAttributes extends ServiceCommonAttributes {
|
||||
main: {
|
||||
creator: string
|
||||
name: string
|
||||
datePublished: string
|
||||
price: string
|
||||
timeout: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface ServiceComputeAttributes extends ServiceCommonAttributes {
|
||||
main: {
|
||||
creator: string
|
||||
datePublished: string
|
||||
price: string
|
||||
timeout: number
|
||||
provider?: ServiceComputeProvider
|
||||
name: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface ServiceComputeProvider {
|
||||
type: string
|
||||
description: string
|
||||
environment: {
|
||||
cluster: {
|
||||
type: string
|
||||
url: string
|
||||
}
|
||||
supportedContainers: {
|
||||
image: string
|
||||
tag: string
|
||||
checksum: string
|
||||
}[]
|
||||
supportedServers: {
|
||||
serverId: string
|
||||
serverType: string
|
||||
price: string
|
||||
cpu: string
|
||||
gpu: string
|
||||
memory: string
|
||||
disk: string
|
||||
maxExecutionTime: number
|
||||
}[]
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,30 +76,13 @@ export interface ServiceMetadata extends ServiceCommon {
|
||||
export interface ServiceAccess extends ServiceCommon {
|
||||
type: 'access'
|
||||
templateId?: string
|
||||
attributes: {
|
||||
main: {
|
||||
creator: string
|
||||
name: string
|
||||
datePublished: string
|
||||
price: string
|
||||
timeout: number
|
||||
}
|
||||
serviceAgreementTemplate?: ServiceAgreementTemplate
|
||||
additionalInformation: {
|
||||
description: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface ServiceComputing extends ServiceCommon {
|
||||
type: 'computing'
|
||||
templateId?: string
|
||||
provider?: Provider
|
||||
serviceAgreementTemplate?: ServiceAgreementTemplate
|
||||
attributes: ServiceAccessAttributes
|
||||
}
|
||||
|
||||
export interface ServiceCompute extends ServiceCommon {
|
||||
type: 'compute'
|
||||
templateId?: string
|
||||
attributes: ServiceComputeAttributes
|
||||
}
|
||||
|
||||
export type Service<
|
||||
@ -64,8 +91,6 @@ export type Service<
|
||||
? ServiceAuthorization
|
||||
: T extends 'metadata'
|
||||
? ServiceMetadata
|
||||
: T extends 'computing'
|
||||
? ServiceComputing
|
||||
: T extends 'access'
|
||||
? ServiceAccess
|
||||
: T extends 'compute'
|
||||
|
@ -95,24 +95,19 @@ export class Keeper extends Instantiable {
|
||||
computeExecutionCondition: keeper.instances.computeExecutionCondition
|
||||
}
|
||||
// Templates
|
||||
keeper.instances.escrowAccessSecretStoreTemplate = new EscrowAccessSecretStoreTemplate(
|
||||
keeper.templates = Object()
|
||||
keeper.templates.escrowAccessSecretStoreTemplate = new EscrowAccessSecretStoreTemplate(
|
||||
keeper.templateStoreManager,
|
||||
keeper.agreementStoreManager,
|
||||
keeper.didRegistry,
|
||||
keeper.conditions
|
||||
)
|
||||
keeper.instances.escrowComputeExecutionTemplate = new EscrowComputeExecutionTemplate(
|
||||
keeper.templates.escrowComputeExecutionTemplate = new EscrowComputeExecutionTemplate(
|
||||
keeper.templateStoreManager,
|
||||
keeper.agreementStoreManager,
|
||||
keeper.didRegistry,
|
||||
keeper.conditions
|
||||
)
|
||||
keeper.templates = {
|
||||
escrowAccessSecretStoreTemplate:
|
||||
keeper.instances.escrowAccessSecretStoreTemplate,
|
||||
escrowComputeExecutionTemplate:
|
||||
keeper.instances.escrowComputeExecutionTemplate
|
||||
}
|
||||
// Utils
|
||||
keeper.utils = {
|
||||
eventHandler: new EventHandler(config)
|
||||
|
@ -4,10 +4,10 @@ export const escrowAccessServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
contractName: 'EscrowAccessSecretStoreTemplate',
|
||||
events: [
|
||||
{
|
||||
name: 'AgreementCreated',
|
||||
actorType: 'consumer',
|
||||
name: 'AgreementActorAdded',
|
||||
actorType: 'provider',
|
||||
handler: {
|
||||
moduleName: 'escrowAccessSecretStoreTemplate',
|
||||
moduleName: '',
|
||||
functionName: 'fulfillLockRewardCondition',
|
||||
version: '0.1'
|
||||
}
|
||||
@ -45,7 +45,7 @@ export const escrowAccessServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
events: [
|
||||
{
|
||||
name: 'Fulfilled',
|
||||
actorType: 'publisher',
|
||||
actorType: 'provider',
|
||||
handler: {
|
||||
moduleName: 'lockRewardCondition',
|
||||
functionName: 'fulfillAccessSecretStoreCondition',
|
||||
@ -75,7 +75,7 @@ export const escrowAccessServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
events: [
|
||||
{
|
||||
name: 'Fulfilled',
|
||||
actorType: 'publisher',
|
||||
actorType: 'provider',
|
||||
handler: {
|
||||
moduleName: 'accessSecretStore',
|
||||
functionName: 'fulfillEscrowRewardCondition',
|
||||
@ -87,7 +87,7 @@ export const escrowAccessServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
actorType: 'consumer',
|
||||
handler: {
|
||||
moduleName: 'accessSecretStore',
|
||||
functionName: 'fulfillEscrowRewardCondition',
|
||||
functionName: 'refundReward',
|
||||
version: '0.1'
|
||||
}
|
||||
}
|
||||
@ -129,7 +129,7 @@ export const escrowAccessServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
events: [
|
||||
{
|
||||
name: 'Fulfilled',
|
||||
actorType: 'publisher',
|
||||
actorType: 'provider',
|
||||
handler: {
|
||||
moduleName: 'escrowRewardCondition',
|
||||
functionName: 'verifyRewardTokens',
|
||||
|
@ -4,10 +4,10 @@ export const escrowComputeServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
contractName: 'EscrowComputeExecutionTemplate',
|
||||
events: [
|
||||
{
|
||||
name: 'AgreementCreated',
|
||||
actorType: 'consumer',
|
||||
name: 'AgreementActorAdded',
|
||||
actorType: 'provider',
|
||||
handler: {
|
||||
moduleName: 'serviceExecutionTemplate',
|
||||
moduleName: '',
|
||||
functionName: 'fulfillLockRewardCondition',
|
||||
version: '0.1'
|
||||
}
|
||||
@ -15,13 +15,13 @@ export const escrowComputeServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
],
|
||||
fulfillmentOrder: [
|
||||
'lockReward.fulfill',
|
||||
'serviceExecution.fulfill',
|
||||
'computeExecution.fulfill',
|
||||
'escrowReward.fulfill'
|
||||
],
|
||||
conditionDependency: {
|
||||
lockReward: [],
|
||||
serviceExecution: [],
|
||||
escrowReward: ['lockReward', 'serviceExecution']
|
||||
computeExecution: [],
|
||||
escrowReward: ['lockReward', 'computeExecution']
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
@ -45,17 +45,17 @@ export const escrowComputeServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
events: [
|
||||
{
|
||||
name: 'Fulfilled',
|
||||
actorType: 'publisher',
|
||||
actorType: 'provider',
|
||||
handler: {
|
||||
moduleName: 'lockRewardCondition',
|
||||
functionName: 'fulfillServiceExecutionCondition',
|
||||
moduleName: 'lockRewardExecutionCondition',
|
||||
functionName: 'fulfillComputeExecutionCondition',
|
||||
version: '0.1'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'serviceExecution',
|
||||
name: 'computeExecution',
|
||||
timelock: 0,
|
||||
timeout: 0,
|
||||
contractName: 'ComputeExecutionCondition',
|
||||
@ -75,10 +75,10 @@ export const escrowComputeServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
events: [
|
||||
{
|
||||
name: 'Fulfilled',
|
||||
actorType: 'publisher',
|
||||
actorType: 'provider',
|
||||
handler: {
|
||||
moduleName: 'serviceExecution',
|
||||
functionName: 'fulfillServiceExecutionCondition',
|
||||
moduleName: 'accessSecretStore',
|
||||
functionName: 'fulfillEscrowRewardCondition',
|
||||
version: '0.1'
|
||||
}
|
||||
},
|
||||
@ -86,8 +86,8 @@ export const escrowComputeServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
name: 'TimedOut',
|
||||
actorType: 'consumer',
|
||||
handler: {
|
||||
moduleName: 'serviceExec',
|
||||
functionName: 'fulfillServiceExecutionCondition',
|
||||
moduleName: 'accessSecretStore',
|
||||
functionName: 'refundReward',
|
||||
version: '0.1'
|
||||
}
|
||||
}
|
||||
@ -129,7 +129,7 @@ export const escrowComputeServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||
events: [
|
||||
{
|
||||
name: 'Fulfilled',
|
||||
actorType: 'publisher',
|
||||
actorType: 'provider',
|
||||
handler: {
|
||||
moduleName: 'escrowRewardCondition',
|
||||
functionName: 'verifyRewardTokens',
|
||||
|
@ -2,6 +2,7 @@ import { OceanAccounts } from './OceanAccounts'
|
||||
import { OceanAgreements } from './OceanAgreements'
|
||||
import { OceanAssets } from './OceanAssets'
|
||||
import { OceanAuth } from './OceanAuth'
|
||||
import { OceanCompute } from './OceanCompute'
|
||||
import { OceanSecretStore } from './OceanSecretStore'
|
||||
import { OceanTokens } from './OceanTokens'
|
||||
import { OceanVersions } from './OceanVersions'
|
||||
@ -49,6 +50,7 @@ export class Ocean extends Instantiable {
|
||||
instance.accounts = await OceanAccounts.getInstance(instanceConfig)
|
||||
instance.auth = await OceanAuth.getInstance(instanceConfig)
|
||||
instance.assets = await OceanAssets.getInstance(instanceConfig)
|
||||
instance.compute = await OceanCompute.getInstance(instanceConfig)
|
||||
instance.agreements = await OceanAgreements.getInstance(instanceConfig)
|
||||
instance.secretStore = await OceanSecretStore.getInstance(instanceConfig)
|
||||
instance.tokens = await OceanTokens.getInstance(instanceConfig)
|
||||
@ -99,6 +101,12 @@ export class Ocean extends Instantiable {
|
||||
*/
|
||||
public agreements: OceanAgreements
|
||||
|
||||
/**
|
||||
* Ocean compute submodule
|
||||
* @type {OceanCompute}
|
||||
*/
|
||||
public compute: OceanCompute
|
||||
|
||||
/**
|
||||
* Ocean secretStore submodule
|
||||
* @type {OceanSecretStore}
|
||||
|
@ -7,6 +7,7 @@ import { AgreementConditionsStatus } from '../keeper/contracts/templates/Agreeme
|
||||
import { ConditionState } from '../keeper/contracts/conditions/Condition.abstract'
|
||||
|
||||
import { OceanAgreementsConditions } from './OceanAgreementsConditions'
|
||||
import { Service } from '../ddo/Service'
|
||||
|
||||
export interface AgreementPrepareResult {
|
||||
agreementId: string
|
||||
@ -121,7 +122,7 @@ export class OceanAgreements extends Instantiable {
|
||||
) {
|
||||
const d: DID = DID.parse(did)
|
||||
const ddo = await this.ocean.aquarius.retrieveDDO(d)
|
||||
const service = ddo.findServiceById(index)
|
||||
const service: Service = ddo.findServiceById(index)
|
||||
const templateName = service.attributes.serviceAgreementTemplate.contractName
|
||||
return this.ocean.keeper
|
||||
.getTemplateByName(templateName)
|
||||
|
@ -81,13 +81,13 @@ export class OceanAgreementsConditions extends Instantiable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorize the consumer defined in the agreement to execute a remote service associated with this asset.
|
||||
* Authorize the consumer defined in the agreement to compute on this asset.
|
||||
* @param {string} agreementId Agreement ID.
|
||||
* @param {string} did Asset ID.
|
||||
* @param {string} grantee Consumer address.
|
||||
* @param {Account} from Account of sender.
|
||||
*/
|
||||
public async grantServiceExecution(
|
||||
public async grantCompute(
|
||||
agreementId: string,
|
||||
did: string,
|
||||
grantee: string,
|
||||
|
@ -2,11 +2,12 @@ import { TransactionReceipt } from 'web3-core'
|
||||
import { SearchQuery } from '../aquarius/Aquarius'
|
||||
import { DDO } from '../ddo/DDO'
|
||||
import { MetaData } from '../ddo/MetaData'
|
||||
import { Service } from '../ddo/Service'
|
||||
import { Service, ServiceAccess } from '../ddo/Service'
|
||||
import Account from './Account'
|
||||
import DID from './DID'
|
||||
import { fillConditionsWithDDO, SubscribablePromise, generateId, zeroX } from '../utils'
|
||||
import { fillConditionsWithDDO, SubscribablePromise } from '../utils'
|
||||
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
|
||||
import { OrderProgressStep } from './utils/ServiceUtils'
|
||||
|
||||
export enum CreateProgressStep {
|
||||
EncryptingFiles,
|
||||
@ -19,13 +20,6 @@ export enum CreateProgressStep {
|
||||
DdoStored
|
||||
}
|
||||
|
||||
export enum OrderProgressStep {
|
||||
CreatingAgreement,
|
||||
AgreementInitialized,
|
||||
LockingPayment,
|
||||
LockedPayment
|
||||
}
|
||||
|
||||
/**
|
||||
* Assets submodule of Ocean Protocol.
|
||||
*/
|
||||
@ -82,6 +76,16 @@ export class OceanAssets extends Instantiable {
|
||||
this.logger.log('Files encrypted')
|
||||
observer.next(CreateProgressStep.FilesEncrypted)
|
||||
|
||||
// make sure that access service is defined if services is empty
|
||||
if (services.length === 0) {
|
||||
const accessService = await this.createAccessServiceAttributes(
|
||||
publisher,
|
||||
metadata.main.price,
|
||||
metadata.main.datePublished
|
||||
)
|
||||
services.push(accessService)
|
||||
}
|
||||
|
||||
const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate()
|
||||
|
||||
const serviceEndpoint = this.ocean.aquarius.getServiceEndpoint(did)
|
||||
@ -104,21 +108,6 @@ export class OceanAssets extends Instantiable {
|
||||
}
|
||||
],
|
||||
service: [
|
||||
{
|
||||
type: 'access',
|
||||
serviceEndpoint: this.ocean.brizo.getConsumeEndpoint(),
|
||||
templateId: templates.escrowAccessSecretStoreTemplate.getId(),
|
||||
attributes: {
|
||||
main: {
|
||||
creator: publisher.getId(),
|
||||
datePublished: metadata.main.datePublished,
|
||||
name: 'dataAssetAccessServiceAgreement',
|
||||
price: metadata.main.price,
|
||||
timeout: 3600
|
||||
},
|
||||
serviceAgreementTemplate
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'authorization',
|
||||
service: 'SecretStore',
|
||||
@ -165,9 +154,18 @@ export class OceanAssets extends Instantiable {
|
||||
})
|
||||
|
||||
// Overwrite initial service agreement conditions
|
||||
const rawConditions = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplateConditions()
|
||||
const conditions = fillConditionsWithDDO(rawConditions, ddo)
|
||||
serviceAgreementTemplate.conditions = conditions
|
||||
serviceAgreementTemplate.conditions = fillConditionsWithDDO(
|
||||
await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplateConditions(),
|
||||
ddo
|
||||
)
|
||||
for (const service of services) {
|
||||
if (service.type === 'compute') {
|
||||
service.attributes.serviceAgreementTemplate.conditions = fillConditionsWithDDO(
|
||||
await templates.escrowComputeExecutionTemplate.getServiceAgreementTemplateConditions(),
|
||||
ddo
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.log('Generating proof')
|
||||
observer.next(CreateProgressStep.GeneratingProof)
|
||||
@ -200,17 +198,16 @@ export class OceanAssets extends Instantiable {
|
||||
public async consume(
|
||||
agreementId: string,
|
||||
did: string,
|
||||
serviceIndex: number,
|
||||
consumerAccount: Account,
|
||||
resultPath: string,
|
||||
index?: number,
|
||||
useSecretStore?: boolean
|
||||
): Promise<string>
|
||||
|
||||
/* eslint-disable no-dupe-class-members */
|
||||
public async consume(
|
||||
agreementId: string,
|
||||
did: string,
|
||||
serviceIndex: number,
|
||||
consumerAccount: Account,
|
||||
resultPath?: undefined | null,
|
||||
index?: number,
|
||||
@ -220,7 +217,6 @@ export class OceanAssets extends Instantiable {
|
||||
public async consume(
|
||||
agreementId: string,
|
||||
did: string,
|
||||
serviceIndex: number,
|
||||
consumerAccount: Account,
|
||||
resultPath?: string,
|
||||
index: number = -1,
|
||||
@ -228,8 +224,7 @@ export class OceanAssets extends Instantiable {
|
||||
): Promise<string | true> {
|
||||
const ddo = await this.resolve(did)
|
||||
const { attributes } = ddo.findServiceByType('metadata')
|
||||
|
||||
const accessService = ddo.findServiceById(serviceIndex)
|
||||
const accessService = ddo.findServiceByType('access')
|
||||
|
||||
const { files } = attributes.main
|
||||
|
||||
@ -244,7 +239,7 @@ export class OceanAssets extends Instantiable {
|
||||
this.logger.log('Consuming files')
|
||||
|
||||
resultPath = resultPath
|
||||
? `${resultPath}/datafile.${ddo.shortId()}.${serviceIndex}/`
|
||||
? `${resultPath}/datafile.${ddo.shortId()}.${accessService.index}/`
|
||||
: undefined
|
||||
|
||||
if (!useSecretStore) {
|
||||
@ -277,109 +272,43 @@ export class OceanAssets extends Instantiable {
|
||||
}
|
||||
return true
|
||||
}
|
||||
/* eslint-enable no-dupe-class-members */
|
||||
|
||||
/**
|
||||
* Start the purchase/order of an asset's service. Starts by signing the service agreement
|
||||
* then sends the request to the publisher via the service endpoint (Brizo http service).
|
||||
* @param {string} did Decentralized ID.
|
||||
* @param {number} index Service index.
|
||||
* @param {Account} consumer Consumer account.
|
||||
* @param {Account} consumerAccount Consumer account.
|
||||
* @param {string} provider ethereum address of service provider (optional)
|
||||
* @return {Promise<string>} Returns Agreement ID
|
||||
*/
|
||||
public order(
|
||||
did: string,
|
||||
index: number,
|
||||
consumer: Account,
|
||||
consumerAccount: Account,
|
||||
provider?: string
|
||||
): SubscribablePromise<OrderProgressStep, string> {
|
||||
return new SubscribablePromise(async observer => {
|
||||
const oceanAgreements = this.ocean.agreements
|
||||
const { keeper, utils } = this.ocean
|
||||
const ddo: DDO = await this.resolve(did)
|
||||
const condition = keeper.conditions.accessSecretStoreCondition
|
||||
|
||||
const agreementId = zeroX(generateId())
|
||||
const ddo = await this.resolve(did)
|
||||
|
||||
const { keeper } = this.ocean
|
||||
const templateName = ddo.findServiceByType('access').attributes
|
||||
.serviceAgreementTemplate.contractName
|
||||
const template = keeper.getTemplateByName(templateName)
|
||||
const accessCondition = keeper.conditions.accessSecretStoreCondition
|
||||
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
const paymentFlow = new Promise(async (resolve, reject) => {
|
||||
await template.getAgreementCreatedEvent(agreementId).once()
|
||||
|
||||
this.logger.log('Agreement initialized')
|
||||
observer.next(OrderProgressStep.AgreementInitialized)
|
||||
|
||||
const { attributes } = ddo.findServiceByType('metadata')
|
||||
|
||||
this.logger.log('Locking payment')
|
||||
|
||||
const accessGranted = accessCondition
|
||||
.getConditionFulfilledEvent(agreementId)
|
||||
.once()
|
||||
|
||||
observer.next(OrderProgressStep.LockingPayment)
|
||||
const paid = await oceanAgreements.conditions.lockReward(
|
||||
agreementId,
|
||||
attributes.main.price,
|
||||
consumer
|
||||
)
|
||||
observer.next(OrderProgressStep.LockedPayment)
|
||||
|
||||
if (paid) {
|
||||
this.logger.log('Payment was OK')
|
||||
} else {
|
||||
this.logger.error('Payment was KO')
|
||||
this.logger.error('Agreement ID: ', agreementId)
|
||||
this.logger.error('DID: ', ddo.id)
|
||||
reject(new Error('Error on payment'))
|
||||
}
|
||||
|
||||
await accessGranted
|
||||
|
||||
this.logger.log('Access granted')
|
||||
resolve()
|
||||
})
|
||||
|
||||
observer.next(OrderProgressStep.CreatingAgreement)
|
||||
this.logger.log('Creating agreement')
|
||||
|
||||
// Get provider from didRegistry if not given in arguments
|
||||
let _provider = provider
|
||||
if (!provider) {
|
||||
const providers = await keeper.didRegistry.getDIDProviders(ddo.shortId())
|
||||
if (providers) {
|
||||
_provider = providers[0]
|
||||
}
|
||||
}
|
||||
|
||||
await oceanAgreements.create(
|
||||
did,
|
||||
agreementId,
|
||||
index,
|
||||
undefined,
|
||||
consumer,
|
||||
_provider,
|
||||
consumer
|
||||
const agreementId = await utils.services.order(
|
||||
'access',
|
||||
condition,
|
||||
observer,
|
||||
consumerAccount,
|
||||
ddo,
|
||||
provider
|
||||
)
|
||||
this.logger.log('Agreement created')
|
||||
|
||||
try {
|
||||
await paymentFlow
|
||||
} catch (e) {
|
||||
throw new Error('Error paying the asset.')
|
||||
}
|
||||
|
||||
return agreementId
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner of a asset.
|
||||
* Returns the owner of an asset.
|
||||
* @param {string} did Decentralized ID.
|
||||
* @return {Promise<string>} Returns eth address
|
||||
* @return {Promise<string>} Returns Account ID
|
||||
*/
|
||||
public async owner(did: string): Promise<string> {
|
||||
const ddo = await this.resolve(did)
|
||||
@ -495,4 +424,29 @@ export class OceanAssets extends Instantiable {
|
||||
}
|
||||
} as SearchQuery)
|
||||
}
|
||||
|
||||
public async createAccessServiceAttributes(
|
||||
consumerAccount: Account,
|
||||
price: string,
|
||||
datePublished: string
|
||||
): Promise<ServiceAccess> {
|
||||
const { templates } = this.ocean.keeper
|
||||
const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate()
|
||||
return {
|
||||
type: 'access',
|
||||
index: 2,
|
||||
serviceEndpoint: this.ocean.brizo.getConsumeEndpoint(),
|
||||
templateId: templates.escrowAccessSecretStoreTemplate.getId(),
|
||||
attributes: {
|
||||
main: {
|
||||
creator: consumerAccount.getId(),
|
||||
datePublished,
|
||||
price,
|
||||
timeout: 3600,
|
||||
name: 'dataAssetAccessServiceAgreement'
|
||||
},
|
||||
serviceAgreementTemplate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
291
src/ocean/OceanCompute.ts
Normal file
291
src/ocean/OceanCompute.ts
Normal file
@ -0,0 +1,291 @@
|
||||
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
|
||||
import { MetaData, MetaDataAlgorithm } from '../ddo/MetaData'
|
||||
import Account from './Account'
|
||||
import { DDO } from '../ddo/DDO'
|
||||
import { SubscribablePromise } from '../utils'
|
||||
import { OrderProgressStep } from './utils/ServiceUtils'
|
||||
import { DID } from '../squid'
|
||||
import { ServiceCompute } from '../ddo/Service'
|
||||
|
||||
export const ComputeJobStatus = Object.freeze({
|
||||
Started: 10,
|
||||
ConfiguringVolumes: 20,
|
||||
ProvisioningSuccess: 30,
|
||||
DataProvisioningFailed: 31,
|
||||
AlgorithmProvisioningFailed: 32,
|
||||
RunningAlgorithm: 40,
|
||||
FilteringResults: 50,
|
||||
PublishingResult: 60,
|
||||
Completed: 70,
|
||||
Stopped: 80,
|
||||
Deleted: 90
|
||||
})
|
||||
|
||||
export interface Output {
|
||||
publishAlgorithmLog?: boolean
|
||||
publishOutput?: boolean
|
||||
brizoAddress?: string
|
||||
brizoUri?: string
|
||||
metadata?: MetaData
|
||||
metadataUri?: string
|
||||
nodeUri?: string
|
||||
owner?: string
|
||||
secretStoreUri?: string
|
||||
whitelist?: string[]
|
||||
}
|
||||
|
||||
export interface ComputeJob {
|
||||
owner: string
|
||||
agreementId: string
|
||||
jobId: string
|
||||
dateCreated: string
|
||||
dateFinished: string
|
||||
status: number
|
||||
statusText: string
|
||||
algorithmLogUrl: string
|
||||
resultsUrls: string[]
|
||||
resultsDid?: DID
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute submodule of Ocean Protocol.
|
||||
*/
|
||||
export class OceanCompute extends Instantiable {
|
||||
/**
|
||||
* Returns the instance of OceanCompute.
|
||||
* @return {Promise<OceanCompute>}
|
||||
*/
|
||||
public static async getInstance(config: InstantiableConfig): Promise<OceanCompute> {
|
||||
const instance = new OceanCompute()
|
||||
instance.setInstanceConfig(config)
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @return {Promise<string>} Returns the Service Agreement ID, representation of `bytes32` ID.
|
||||
*/
|
||||
public order(
|
||||
consumerAccount: Account,
|
||||
datasetDid: string,
|
||||
provider?: string
|
||||
): SubscribablePromise<OrderProgressStep, string> {
|
||||
return new SubscribablePromise(async observer => {
|
||||
const { assets, keeper, utils } = this.ocean
|
||||
const ddo: DDO = await assets.resolve(datasetDid)
|
||||
const condition = keeper.conditions.computeExecutionCondition
|
||||
|
||||
const agreementId = await utils.services.order(
|
||||
'compute',
|
||||
condition,
|
||||
observer,
|
||||
consumerAccount,
|
||||
ddo,
|
||||
provider
|
||||
)
|
||||
|
||||
return agreementId
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the output object and add default properties if needed
|
||||
* @param {Account} consumerAccount The account of the consumer ordering the service.
|
||||
* @param {Output} output Output section used for publishing the result.
|
||||
* @return {Promise<Output>} Returns output object
|
||||
*/
|
||||
public checkOutput(consumerAccount: Account, output?: Output): Output {
|
||||
const isDefault =
|
||||
!output || (!output.publishAlgorithmLog && !output.publishOutput)
|
||||
|
||||
if (isDefault) {
|
||||
return {
|
||||
publishAlgorithmLog: false,
|
||||
publishOutput: false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
publishAlgorithmLog: output.publishAlgorithmLog,
|
||||
publishOutput: output.publishOutput,
|
||||
brizoAddress: output.brizoAddress || this.config.brizoAddress,
|
||||
brizoUri: output.brizoUri || this.config.brizoUri,
|
||||
metadataUri: output.metadataUri || this.config.aquariusUri,
|
||||
nodeUri: output.nodeUri || this.config.nodeUri,
|
||||
owner: output.owner || consumerAccount.getId(),
|
||||
secretStoreUri: output.secretStoreUri || this.config.secretStoreUri
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the execution of a compute job.
|
||||
* @param {Account} consumerAccount The account of the consumer ordering the service.
|
||||
* @param {string} agreementId The service agreement ID.
|
||||
* @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.
|
||||
* @return {Promise<ComputeJob>} Returns compute job ID under status.jobId
|
||||
*/
|
||||
public async start(
|
||||
consumerAccount: Account,
|
||||
agreementId: string,
|
||||
algorithmDid?: string,
|
||||
algorithmMeta?: MetaDataAlgorithm,
|
||||
output?: Output
|
||||
): Promise<ComputeJob> {
|
||||
output = this.checkOutput(consumerAccount, output)
|
||||
const computeJobsList = await this.ocean.brizo.compute(
|
||||
'post',
|
||||
agreementId,
|
||||
consumerAccount,
|
||||
algorithmDid,
|
||||
algorithmMeta,
|
||||
undefined,
|
||||
output
|
||||
)
|
||||
|
||||
return computeJobsList[0] as ComputeJob
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a running compute job.
|
||||
* @param {Account} consumerAccount The account of the consumer ordering the service.
|
||||
* @param {string} agreementId The service agreement ID.
|
||||
* @param {string} jobId The ID of the compute job to be stopped
|
||||
* @return {Promise<ComputeJob>} Returns the new status of a job
|
||||
*/
|
||||
public async stop(
|
||||
consumerAccount: Account,
|
||||
agreementId: string,
|
||||
jobId: string
|
||||
): Promise<ComputeJob> {
|
||||
const computeJobsList = await this.ocean.brizo.compute(
|
||||
'put',
|
||||
agreementId,
|
||||
consumerAccount,
|
||||
undefined,
|
||||
undefined,
|
||||
jobId
|
||||
)
|
||||
|
||||
return computeJobsList[0] as ComputeJob
|
||||
}
|
||||
|
||||
/**
|
||||
* 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} agreementId The service agreement ID.
|
||||
* @param {string} jobId The ID of the compute job to be stopped
|
||||
* @return {Promise<ComputeJob>} Returns the new status of a job
|
||||
*/
|
||||
public async delete(
|
||||
consumerAccount: Account,
|
||||
agreementId: string,
|
||||
jobId: string
|
||||
): Promise<ComputeJob> {
|
||||
const computeJobsList = await this.ocean.brizo.compute(
|
||||
'delete',
|
||||
agreementId,
|
||||
consumerAccount,
|
||||
undefined,
|
||||
undefined,
|
||||
jobId
|
||||
)
|
||||
|
||||
return computeJobsList[0] as ComputeJob
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a running compute job and starts it again.
|
||||
* @param {Account} consumerAccount The account of the consumer ordering the service.
|
||||
* @param {string} agreementId The service agreement ID.
|
||||
* @param {string} jobId The ID of the compute job to be stopped
|
||||
* @return {Promise<ComputeJob>} Returns the new status of a job
|
||||
*/
|
||||
public async restart(
|
||||
consumerAccount: Account,
|
||||
agreementId: string,
|
||||
jobId: string
|
||||
): Promise<ComputeJob> {
|
||||
await this.stop(consumerAccount, agreementId, jobId)
|
||||
const result = await this.start(consumerAccount, agreementId, jobId)
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the status of all compute jobs, or a single compute job.
|
||||
* @param {Account} consumerAccount The account of the consumer ordering the service.
|
||||
* @param {string} agreementId The service agreement ID.
|
||||
* @param {string} jobId The ID of the compute job to be stopped
|
||||
* @return {Promise<ComputeJob[]>} Returns the status
|
||||
*/
|
||||
public async status(
|
||||
consumerAccount: Account,
|
||||
agreementId?: string,
|
||||
jobId?: string
|
||||
): Promise<ComputeJob[]> {
|
||||
const computeJobsList = await this.ocean.brizo.compute(
|
||||
'get',
|
||||
agreementId,
|
||||
consumerAccount,
|
||||
undefined,
|
||||
undefined,
|
||||
jobId
|
||||
)
|
||||
|
||||
return computeJobsList as ComputeJob[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 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} agreementId The service agreement ID.
|
||||
* @param {string} jobId The ID of the compute job to be stopped.
|
||||
* @return {Promise<ComputeJob>} Returns the DDO of the result asset.
|
||||
*/
|
||||
public async result(
|
||||
consumerAccount: Account,
|
||||
agreementId: string,
|
||||
jobId: string
|
||||
): Promise<ComputeJob> {
|
||||
const computeJobsList = await this.ocean.brizo.compute(
|
||||
'get',
|
||||
agreementId,
|
||||
consumerAccount,
|
||||
undefined,
|
||||
undefined,
|
||||
jobId
|
||||
)
|
||||
|
||||
return computeJobsList[0] as ComputeJob
|
||||
}
|
||||
|
||||
public async createComputeServiceAttributes(
|
||||
consumerAccount: Account,
|
||||
price: string,
|
||||
datePublished: string
|
||||
): Promise<ServiceCompute> {
|
||||
const { templates } = this.ocean.keeper
|
||||
const serviceAgreementTemplate = await templates.escrowComputeExecutionTemplate.getServiceAgreementTemplate()
|
||||
const name = 'dataAssetComputingServiceAgreement'
|
||||
return {
|
||||
type: 'compute',
|
||||
index: 3,
|
||||
serviceEndpoint: this.ocean.brizo.getComputeEndpoint(),
|
||||
templateId: templates.escrowComputeExecutionTemplate.getId(),
|
||||
attributes: {
|
||||
main: {
|
||||
creator: consumerAccount.getId(),
|
||||
datePublished,
|
||||
price,
|
||||
timeout: 3600,
|
||||
name
|
||||
},
|
||||
serviceAgreementTemplate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
|
||||
|
||||
import { ServiceUtils } from './ServiceUtils'
|
||||
import { ServiceAgreement } from './ServiceAgreement'
|
||||
import { SignatureUtils } from './SignatureUtils'
|
||||
import { WebServiceConnector } from './WebServiceConnector'
|
||||
@ -21,6 +22,7 @@ export class OceanUtils extends Instantiable {
|
||||
config.logger,
|
||||
config.web3
|
||||
)
|
||||
instance.services = new ServiceUtils(config.ocean, config.logger)
|
||||
instance.signature = new SignatureUtils(config.web3, config.logger)
|
||||
instance.fetch = new WebServiceConnector(config.logger)
|
||||
|
||||
@ -33,6 +35,12 @@ export class OceanUtils extends Instantiable {
|
||||
*/
|
||||
public agreements: ServiceAgreement
|
||||
|
||||
/**
|
||||
* Service utils.
|
||||
* @type {ServiceUtils}
|
||||
*/
|
||||
public services: ServiceUtils
|
||||
|
||||
/**
|
||||
* Signature utils.
|
||||
* @type {SignatureUtils}
|
||||
|
115
src/ocean/utils/ServiceUtils.ts
Normal file
115
src/ocean/utils/ServiceUtils.ts
Normal file
@ -0,0 +1,115 @@
|
||||
import { DDO } from '../../ddo/DDO'
|
||||
import Account from '../Account'
|
||||
import { zeroX, Logger, generateId } from '../../utils'
|
||||
import { Ocean } from '../../squid'
|
||||
import { Condition } from '../../keeper/contracts/conditions'
|
||||
import { ServiceType, Service } from '../../ddo/Service'
|
||||
|
||||
export enum OrderProgressStep {
|
||||
CreatingAgreement,
|
||||
AgreementInitialized,
|
||||
LockingPayment,
|
||||
LockedPayment
|
||||
}
|
||||
|
||||
export class ServiceUtils {
|
||||
private ocean: Ocean
|
||||
private logger: Logger
|
||||
|
||||
constructor(ocean: Ocean, logger: Logger) {
|
||||
this.ocean = ocean
|
||||
this.logger = logger
|
||||
}
|
||||
|
||||
public async order(
|
||||
type: ServiceType,
|
||||
condition: Condition,
|
||||
observer: any,
|
||||
consumerAccount: Account,
|
||||
ddo: DDO,
|
||||
provider?: string
|
||||
): Promise<string> {
|
||||
const { keeper, agreements } = this.ocean
|
||||
|
||||
const agreementId = zeroX(generateId())
|
||||
const service: Service = ddo.findServiceByType(type)
|
||||
const metadata = ddo.findServiceByType('metadata')
|
||||
|
||||
const templateName = service.attributes.serviceAgreementTemplate.contractName
|
||||
const template = keeper.getTemplateByName(templateName)
|
||||
|
||||
// use price from compute service,
|
||||
// otherwise always take the price from metadata
|
||||
const price =
|
||||
type === 'compute'
|
||||
? service.attributes.main.price
|
||||
: metadata.attributes.main.price
|
||||
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
const paymentFlow = new Promise(async (resolve, reject) => {
|
||||
await template.getAgreementCreatedEvent(agreementId).once()
|
||||
|
||||
this.logger.log('Agreement initialized')
|
||||
observer.next(OrderProgressStep.AgreementInitialized)
|
||||
|
||||
this.logger.log('Locking payment')
|
||||
|
||||
const serviceGranted = condition
|
||||
.getConditionFulfilledEvent(agreementId)
|
||||
.once()
|
||||
|
||||
observer.next(OrderProgressStep.LockingPayment)
|
||||
const paid = await agreements.conditions.lockReward(
|
||||
agreementId,
|
||||
price,
|
||||
consumerAccount
|
||||
)
|
||||
observer.next(OrderProgressStep.LockedPayment)
|
||||
|
||||
if (paid) {
|
||||
this.logger.log('Payment was OK')
|
||||
} else {
|
||||
this.logger.error('Payment was KO')
|
||||
this.logger.error('Agreement ID: ', agreementId)
|
||||
this.logger.error('DID: ', ddo.id)
|
||||
reject(new Error('Error on payment'))
|
||||
}
|
||||
|
||||
await serviceGranted
|
||||
|
||||
this.logger.log(`Service ${type} granted`)
|
||||
resolve()
|
||||
})
|
||||
|
||||
observer.next(OrderProgressStep.CreatingAgreement)
|
||||
this.logger.log('Creating agreement')
|
||||
|
||||
// Get provider from didRegistry if not given in arguments
|
||||
let _provider = provider
|
||||
if (!provider) {
|
||||
const providers = await keeper.didRegistry.getDIDProviders(ddo.shortId())
|
||||
if (providers) {
|
||||
_provider = providers[0]
|
||||
}
|
||||
}
|
||||
|
||||
await agreements.create(
|
||||
ddo.id,
|
||||
agreementId,
|
||||
service.index,
|
||||
undefined,
|
||||
consumerAccount,
|
||||
_provider,
|
||||
consumerAccount
|
||||
)
|
||||
this.logger.log('Agreement created')
|
||||
|
||||
try {
|
||||
await paymentFlow
|
||||
} catch (e) {
|
||||
throw new Error(`Error paying the ${type} service.`)
|
||||
}
|
||||
|
||||
return agreementId
|
||||
}
|
||||
}
|
@ -43,6 +43,15 @@ export class WebServiceConnector {
|
||||
})
|
||||
}
|
||||
|
||||
public delete(url: string): Promise<Response> {
|
||||
return this.fetch(url, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public async downloadFile(
|
||||
url: string,
|
||||
destination?: string,
|
||||
|
@ -14,7 +14,9 @@ import * as utils from './utils'
|
||||
export * from './ddo/DDO'
|
||||
export * from './ddo/MetaData'
|
||||
|
||||
export { OrderProgressStep, CreateProgressStep } from './ocean/OceanAssets'
|
||||
export { CreateProgressStep } from './ocean/OceanAssets'
|
||||
export { ComputeJob, ComputeJobStatus } from './ocean/OceanCompute'
|
||||
export { OrderProgressStep } from './ocean/utils/ServiceUtils'
|
||||
export {
|
||||
OceanPlatformTechStatus,
|
||||
OceanPlatformTech,
|
||||
|
@ -85,12 +85,15 @@ describe('Asset Owners', () => {
|
||||
// Granting access
|
||||
try {
|
||||
await account2.requestTokens(
|
||||
+metadata.main.price * 10 ** -(await ocean.keeper.token.decimals())
|
||||
parseInt(
|
||||
(
|
||||
+metadata.main.price *
|
||||
10 ** -(await ocean.keeper.token.decimals())
|
||||
).toString()
|
||||
)
|
||||
)
|
||||
} catch {}
|
||||
const { index } = ddo.findServiceByType('access')
|
||||
|
||||
await ocean.assets.order(ddo.id, index, account2)
|
||||
await ocean.assets.order(ddo.id, account2)
|
||||
// Access granted
|
||||
const { length: finalLength2 } = await ocean.assets.consumerAssets(
|
||||
account2.getId()
|
||||
|
121
test/integration/ocean/Compute.test.ts
Normal file
121
test/integration/ocean/Compute.test.ts
Normal file
@ -0,0 +1,121 @@
|
||||
import { assert } from 'chai'
|
||||
|
||||
import { config } from '../config'
|
||||
import {
|
||||
Ocean,
|
||||
Account,
|
||||
DDO,
|
||||
MetaData,
|
||||
ComputeJobStatus,
|
||||
Config,
|
||||
MetaDataAlgorithm
|
||||
} from '../../../src'
|
||||
import { getMetadata } from '../utils'
|
||||
import { ServiceCompute } from '../../../src/ddo/Service'
|
||||
|
||||
const metadataAsset = getMetadata()
|
||||
const metadataAlgorithm = getMetadata(0, 'algorithm')
|
||||
|
||||
const customConfig: Config = {
|
||||
...config,
|
||||
// nodeUri: 'https://nile.dev-ocean.com',
|
||||
// aquariusUri: 'https://aquarius.nile.dev-ocean.com',
|
||||
// brizoUri: 'http://89.46.156.10:8030',
|
||||
// secretStoreUri: 'https://secret-store.nile.dev-ocean.com',
|
||||
// brizoAddress: '0x413c9ba0a05b8a600899b41b0c62dd661e689354',
|
||||
verbose: true
|
||||
}
|
||||
|
||||
describe('Compute', () => {
|
||||
let ocean: Ocean
|
||||
let account: Account
|
||||
let agreementId: string
|
||||
let dataset: DDO
|
||||
let algorithm: DDO
|
||||
let computeService: ServiceCompute
|
||||
|
||||
before(async () => {
|
||||
ocean = await Ocean.getInstance(customConfig)
|
||||
;[account] = await ocean.accounts.list()
|
||||
})
|
||||
|
||||
it('should authenticate the consumer account', async () => {
|
||||
await account.authenticate()
|
||||
})
|
||||
|
||||
it('should publish a dataset with a compute service object', async () => {
|
||||
const stepsAsset = []
|
||||
computeService = await ocean.compute.createComputeServiceAttributes(
|
||||
account,
|
||||
'1000',
|
||||
metadataAsset.main.datePublished
|
||||
)
|
||||
dataset = await ocean.assets
|
||||
.create(metadataAsset as MetaData, account, [computeService])
|
||||
.next(step => stepsAsset.push(step))
|
||||
|
||||
assert.instanceOf(dataset, DDO)
|
||||
assert.isDefined(
|
||||
dataset.findServiceByType('compute'),
|
||||
`DDO compute service doesn't exist`
|
||||
)
|
||||
assert.deepEqual(stepsAsset, [0, 1, 2, 3, 4, 5, 6, 7])
|
||||
})
|
||||
|
||||
it('should publish an algorithm', async () => {
|
||||
const stepsAlgorithm = []
|
||||
algorithm = await ocean.assets
|
||||
.create(metadataAlgorithm as MetaData, account)
|
||||
.next(step => stepsAlgorithm.push(step))
|
||||
|
||||
assert.instanceOf(algorithm, DDO)
|
||||
assert.deepEqual(stepsAlgorithm, [0, 1, 2, 3, 4, 5, 6, 7])
|
||||
})
|
||||
|
||||
it('should order the compute service of the dataset', async () => {
|
||||
const steps = []
|
||||
try {
|
||||
await account.requestTokens(
|
||||
parseInt(
|
||||
(
|
||||
+computeService.attributes.main.price *
|
||||
10 ** -(await ocean.keeper.token.decimals())
|
||||
).toString()
|
||||
)
|
||||
)
|
||||
|
||||
agreementId = await ocean.compute
|
||||
.order(account, dataset.id)
|
||||
.next(step => steps.push(step))
|
||||
|
||||
console.log(agreementId)
|
||||
assert.isDefined(agreementId)
|
||||
assert.deepEqual(steps, [0, 1, 2, 3])
|
||||
} catch {}
|
||||
})
|
||||
|
||||
it('should start a compute job with a published algo', async () => {
|
||||
const response = await ocean.compute.start(account, agreementId, algorithm.id)
|
||||
|
||||
assert.equal(response.status, ComputeJobStatus.Started)
|
||||
})
|
||||
|
||||
it('should start a compute job with a rawcode algo', async () => {
|
||||
const algoMeta: MetaDataAlgorithm = {
|
||||
rawcode: `console.log('Hello world!')`,
|
||||
container: {
|
||||
entrypoint: 'node $ALGO',
|
||||
image: 'node',
|
||||
tag: '10'
|
||||
}
|
||||
}
|
||||
const response = await ocean.compute.start(
|
||||
account,
|
||||
agreementId,
|
||||
undefined,
|
||||
algoMeta
|
||||
)
|
||||
|
||||
assert.equal(response.status, ComputeJobStatus.Started)
|
||||
})
|
||||
})
|
@ -45,8 +45,12 @@ describe('Consume Asset', () => {
|
||||
|
||||
it('should be able to request tokens for consumer', async () => {
|
||||
const initialBalance = (await consumer.getBalance()).ocn
|
||||
const claimedTokens =
|
||||
+metadata.main.price * 10 ** -(await ocean.keeper.token.decimals())
|
||||
const claimedTokens = parseInt(
|
||||
(
|
||||
+metadata.main.price *
|
||||
10 ** -(await ocean.keeper.token.decimals())
|
||||
).toString()
|
||||
)
|
||||
|
||||
try {
|
||||
await consumer.requestTokens(claimedTokens)
|
||||
@ -156,13 +160,10 @@ describe('Consume Asset', () => {
|
||||
})
|
||||
|
||||
it('should consume and store the assets', async () => {
|
||||
const accessService = ddo.findServiceByType('access')
|
||||
|
||||
const folder = '/tmp/ocean/squid-js-1'
|
||||
const path = await ocean.assets.consume(
|
||||
serviceAgreementSignatureResult.agreementId,
|
||||
ddo.id,
|
||||
accessService.index,
|
||||
consumer,
|
||||
folder
|
||||
)
|
||||
@ -183,13 +184,10 @@ describe('Consume Asset', () => {
|
||||
})
|
||||
|
||||
it('should consume and store one asset', async () => {
|
||||
const accessService = ddo.findServiceByType('access')
|
||||
|
||||
const folder = '/tmp/ocean/squid-js-2'
|
||||
const path = await ocean.assets.consume(
|
||||
serviceAgreementSignatureResult.agreementId,
|
||||
ddo.id,
|
||||
accessService.index,
|
||||
consumer,
|
||||
folder,
|
||||
1
|
||||
|
@ -50,34 +50,30 @@ describe('Consume Asset (Brizo)', () => {
|
||||
})
|
||||
|
||||
it('should order the asset', async () => {
|
||||
const accessService = ddo.findServiceByType('access')
|
||||
const steps = []
|
||||
|
||||
try {
|
||||
await consumer.requestTokens(
|
||||
+metadata.main.price * 10 ** -(await ocean.keeper.token.decimals())
|
||||
parseInt(
|
||||
(
|
||||
+metadata.main.price *
|
||||
10 ** -(await ocean.keeper.token.decimals())
|
||||
).toString()
|
||||
)
|
||||
)
|
||||
} catch {}
|
||||
|
||||
const steps = []
|
||||
agreementId = await ocean.assets
|
||||
.order(ddo.id, accessService.index, consumer)
|
||||
.next(step => steps.push(step))
|
||||
agreementId = await ocean.assets
|
||||
.order(ddo.id, consumer)
|
||||
.next(step => steps.push(step))
|
||||
} catch {}
|
||||
|
||||
assert.isDefined(agreementId)
|
||||
assert.deepEqual(steps, [0, 1, 2, 3])
|
||||
})
|
||||
|
||||
it('should consume and store the assets', async () => {
|
||||
const accessService = ddo.findServiceByType('access')
|
||||
|
||||
const folder = '/tmp/ocean/squid-js'
|
||||
const path = await ocean.assets.consume(
|
||||
agreementId,
|
||||
ddo.id,
|
||||
accessService.index,
|
||||
consumer,
|
||||
folder
|
||||
)
|
||||
const path = await ocean.assets.consume(agreementId, ddo.id, consumer, folder)
|
||||
|
||||
assert.include(path, folder, 'The storage path is not correct.')
|
||||
|
||||
|
@ -50,30 +50,25 @@ xdescribe('Consume Asset (Large size)', () => {
|
||||
})
|
||||
|
||||
it('should order the asset', async () => {
|
||||
const accessService = ddo.findServiceByType('access')
|
||||
|
||||
try {
|
||||
await consumer.requestTokens(
|
||||
+metadata.main.price * 10 ** -(await ocean.keeper.token.decimals())
|
||||
parseInt(
|
||||
(
|
||||
+metadata.main.price *
|
||||
10 ** -(await ocean.keeper.token.decimals())
|
||||
).toString()
|
||||
)
|
||||
)
|
||||
} catch {}
|
||||
|
||||
agreementId = await ocean.assets.order(ddo.id, accessService.index, consumer)
|
||||
agreementId = await ocean.assets.order(ddo.id, consumer)
|
||||
|
||||
assert.isDefined(agreementId)
|
||||
})
|
||||
|
||||
it('should consume and store the assets', async () => {
|
||||
const accessService = ddo.findServiceByType('access')
|
||||
|
||||
const folder = '/tmp/ocean/squid-js'
|
||||
const path = await ocean.assets.consume(
|
||||
agreementId,
|
||||
ddo.id,
|
||||
accessService.index,
|
||||
consumer,
|
||||
folder
|
||||
)
|
||||
const path = await ocean.assets.consume(agreementId, ddo.id, consumer, folder)
|
||||
|
||||
assert.include(path, folder, 'The storage path is not correct.')
|
||||
|
||||
|
@ -26,7 +26,7 @@ describe('Register Escrow Compute Execution Template', () => {
|
||||
|
||||
before(async () => {
|
||||
ocean = await Ocean.getInstance(config)
|
||||
keeper = ocean.keeper
|
||||
;({ keeper } = ocean)
|
||||
|
||||
template = keeper.templates.escrowComputeExecutionTemplate
|
||||
|
||||
@ -36,9 +36,11 @@ describe('Register Escrow Compute Execution Template', () => {
|
||||
consumer = (await ocean.accounts.list())[2]
|
||||
|
||||
// Conditions
|
||||
computeExecutionCondition = keeper.conditions.computeExecutionCondition
|
||||
lockRewardCondition = keeper.conditions.lockRewardCondition
|
||||
escrowReward = keeper.conditions.escrowReward
|
||||
;({
|
||||
computeExecutionCondition,
|
||||
lockRewardCondition,
|
||||
escrowReward
|
||||
} = keeper.conditions)
|
||||
|
||||
if (!ocean.keeper.dispenser) {
|
||||
escrowAmount = 0
|
||||
@ -274,7 +276,7 @@ describe('Register Escrow Compute Execution Template', () => {
|
||||
})
|
||||
|
||||
it('should fulfill the conditions from computing side', async () => {
|
||||
await ocean.agreements.conditions.grantServiceExecution(
|
||||
await ocean.agreements.conditions.grantCompute(
|
||||
agreementId,
|
||||
did,
|
||||
consumer.getId(),
|
||||
|
@ -11,18 +11,17 @@ describe('Versions', () => {
|
||||
ocean = await Ocean.getInstance(config)
|
||||
})
|
||||
|
||||
// TODO: enable again after new versions of Brizo
|
||||
xit('should return the versions', async () => {
|
||||
it('should return the versions', async () => {
|
||||
const versions = await ocean.versions.get()
|
||||
|
||||
assert.equal(versions.aquarius.status, OceanPlatformTechStatus.Working)
|
||||
assert.equal(versions.brizo.status, OceanPlatformTechStatus.Working)
|
||||
assert.equal(versions.squid.status, OceanPlatformTechStatus.Working)
|
||||
|
||||
assert.deepEqual(versions.status, {
|
||||
ok: true,
|
||||
contracts: true,
|
||||
network: true
|
||||
})
|
||||
// assert.deepEqual(versions.status, {
|
||||
// ok: true,
|
||||
// contracts: true,
|
||||
// network: true
|
||||
// })
|
||||
})
|
||||
})
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { MetaData } from '../../../src' // @oceanprotocol/squid
|
||||
import { MetaData, MetaDataAlgorithm, Ocean, Account } from '../../../src' // @oceanprotocol/squid
|
||||
import { ServiceCompute } from '../../../src/ddo/Service'
|
||||
|
||||
const metadata: Partial<MetaData> = {
|
||||
main: {
|
||||
name: undefined,
|
||||
type: 'dataset',
|
||||
type: undefined,
|
||||
dateCreated: '2012-10-10T17:00:00Z',
|
||||
datePublished: '2012-10-10T17:00:00Z',
|
||||
author: 'Met Office',
|
||||
@ -46,16 +47,33 @@ const metadata: Partial<MetaData> = {
|
||||
}
|
||||
}
|
||||
|
||||
export const generateMetadata = (name: string, price?: number): Partial<MetaData> => ({
|
||||
...metadata,
|
||||
const algorithmMeta: MetaDataAlgorithm = {
|
||||
language: 'scala',
|
||||
format: 'docker-image',
|
||||
version: '0.1',
|
||||
container: {
|
||||
entrypoint: 'ocean-entrypoint.sh',
|
||||
image: 'node',
|
||||
tag: '10'
|
||||
}
|
||||
}
|
||||
|
||||
export const generateMetadata = (
|
||||
name: string,
|
||||
type?: 'dataset' | 'algorithm',
|
||||
price?: number
|
||||
): Partial<MetaData> => ({
|
||||
main: {
|
||||
...metadata.main,
|
||||
name,
|
||||
price: (price || 21) + '0'.repeat(18)
|
||||
type: type || 'dataset',
|
||||
price: (price || 21) + '0'.repeat(18),
|
||||
algorithm: type === 'algorithm' ? algorithmMeta : undefined
|
||||
},
|
||||
additionalInformation: {
|
||||
...metadata.additionalInformation
|
||||
}
|
||||
})
|
||||
|
||||
export const getMetadata = (price?: number) => generateMetadata('TestAsset', price)
|
||||
export const getMetadata = (price?: number, type?: 'dataset' | 'algorithm') =>
|
||||
generateMetadata('TestAsset', type, price)
|
||||
|
459
test/unit/__fixtures__/ddo.json
Normal file
459
test/unit/__fixtures__/ddo.json
Normal file
@ -0,0 +1,459 @@
|
||||
{
|
||||
"@context": "https://w3id.org/future-method/v1",
|
||||
"id": "did:op:08a429b8529856d59867503f8056903a680935a76950bb9649785cc97869a43d",
|
||||
"publicKey": [
|
||||
{
|
||||
"id": "did:op:123456789abcdefghi#keys-1",
|
||||
"type": "RsaVerificationKey2018",
|
||||
"owner": "did:op:123456789abcdefghi",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
|
||||
},
|
||||
{
|
||||
"id": "did:op:123456789abcdefghi#keys-2",
|
||||
"type": "Ed25519VerificationKey2018",
|
||||
"owner": "did:op:123456789abcdefghi",
|
||||
"publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
|
||||
},
|
||||
{
|
||||
"id": "did:op:123456789abcdefghi#keys-3",
|
||||
"type": "RsaPublicKeyExchangeKey2018",
|
||||
"owner": "did:op:123456789abcdefghi",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
|
||||
}
|
||||
],
|
||||
"authentication": [
|
||||
{
|
||||
"type": "RsaSignatureAuthentication2018",
|
||||
"publicKey": "did:op:123456789abcdefghi#keys-1"
|
||||
},
|
||||
{
|
||||
"type": "ieee2410Authentication2018",
|
||||
"publicKey": "did:op:123456789abcdefghi#keys-2"
|
||||
}
|
||||
],
|
||||
"proof": {
|
||||
"type": "UUIDSignature",
|
||||
"created": "2016-02-08T16:02:20Z",
|
||||
"creator": "did:example:8uQhQMGzWxR8vw5P3UWH1ja",
|
||||
"signatureValue": "QNB13Y7Q9...1tzjn4w=="
|
||||
},
|
||||
"service": [
|
||||
{
|
||||
"type": "access",
|
||||
"index": 0,
|
||||
"serviceEndpoint": "http://mybrizo.org/api/v1/brizo/services/consume?pubKey=${pubKey}&serviceId={serviceId}&url={url}",
|
||||
"templateId": "044852b2a670ade5407e78fb2863c51000000000000000000000000000000000",
|
||||
"attributes": {
|
||||
"main": {
|
||||
"name": "dataAssetAccessServiceAgreement",
|
||||
"creator": "0x36A7f3383A63279cDaF4DfC0F3ABc07d90252C6b",
|
||||
"datePublished": "2019-11-15T14:11:23Z",
|
||||
"price": "",
|
||||
"timeout": 36000
|
||||
},
|
||||
"serviceAgreementTemplate": {
|
||||
"contractName": "EscrowAccessSecretStoreTemplate",
|
||||
"events": [
|
||||
{
|
||||
"name": "AgreementCreated",
|
||||
"actorType": "consumer",
|
||||
"handler": {
|
||||
"moduleName": "escrowAccessSecretStoreTemplate",
|
||||
"functionName": "fulfillLockRewardCondition",
|
||||
"version": "0.1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"fulfillmentOrder": [
|
||||
"lockReward.fulfill",
|
||||
"accessSecretStore.fulfill",
|
||||
"escrowReward.fulfill"
|
||||
],
|
||||
"conditionDependency": {
|
||||
"lockReward": [],
|
||||
"accessSecretStore": [],
|
||||
"escrowReward": ["lockReward", "accessSecretStore"]
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"name": "lockReward",
|
||||
"timelock": 0,
|
||||
"timeout": 0,
|
||||
"contractName": "LockRewardCondition",
|
||||
"functionName": "fulfill",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "_rewardAddress",
|
||||
"type": "address",
|
||||
"value": "0x36A7f3383A63279cDaF4DfC0F3ABc07d90252C6b"
|
||||
},
|
||||
{
|
||||
"name": "_amount",
|
||||
"type": "uint256",
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "Fulfilled",
|
||||
"actorType": "publisher",
|
||||
"handler": {
|
||||
"moduleName": "lockRewardCondition",
|
||||
"functionName": "fulfillAccessSecretStoreCondition",
|
||||
"version": "0.1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "accessSecretStore",
|
||||
"timelock": 0,
|
||||
"timeout": 0,
|
||||
"contractName": "AccessSecretStoreCondition",
|
||||
"functionName": "fulfill",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "_documentId",
|
||||
"type": "bytes32",
|
||||
"value": "c678e7e5963d4fdc99afea49ac221d4d4177790f30204417823319d4d35f851f"
|
||||
},
|
||||
{
|
||||
"name": "_grantee",
|
||||
"type": "address",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "Fulfilled",
|
||||
"actorType": "publisher",
|
||||
"handler": {
|
||||
"moduleName": "accessSecretStore",
|
||||
"functionName": "fulfillEscrowRewardCondition",
|
||||
"version": "0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "TimedOut",
|
||||
"actorType": "consumer",
|
||||
"handler": {
|
||||
"moduleName": "accessSecretStore",
|
||||
"functionName": "refundReward",
|
||||
"version": "0.1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "escrowReward",
|
||||
"timelock": 0,
|
||||
"timeout": 0,
|
||||
"contractName": "EscrowReward",
|
||||
"functionName": "fulfill",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "_amount",
|
||||
"type": "uint256",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"name": "_receiver",
|
||||
"type": "address",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "_sender",
|
||||
"type": "address",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "_lockCondition",
|
||||
"type": "bytes32",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "_releaseCondition",
|
||||
"type": "bytes32",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "Fulfilled",
|
||||
"actorType": "publisher",
|
||||
"handler": {
|
||||
"moduleName": "escrowRewardCondition",
|
||||
"functionName": "verifyRewardTokens",
|
||||
"version": "0.1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "compute",
|
||||
"index": 1,
|
||||
"serviceEndpoint": "http://localhost:8030/api/v1/brizo/services/compute",
|
||||
"templateId": "",
|
||||
"attributes": {
|
||||
"main": {
|
||||
"name": "dataAssetComputingServiceAgreement",
|
||||
"creator": "0x36A7f3383A63279cDaF4DfC0F3ABc07d90252C6b",
|
||||
"datePublished": "2019-04-09T19:02:11Z",
|
||||
"price": "10",
|
||||
"timeout": 86400,
|
||||
"provider": {
|
||||
"type": "Azure",
|
||||
"description": "",
|
||||
"environment": {
|
||||
"cluster": {
|
||||
"type": "Kubernetes",
|
||||
"url": "http://10.0.0.17/xxx"
|
||||
},
|
||||
"supportedContainers": [
|
||||
{
|
||||
"image": "tensorflow/tensorflow",
|
||||
"tag": "latest",
|
||||
"checksum": "sha256:cb57ecfa6ebbefd8ffc7f75c0f00e57a7fa739578a429b6f72a0df19315deadc"
|
||||
},
|
||||
{
|
||||
"image": "tensorflow/tensorflow",
|
||||
"tag": "latest",
|
||||
"checksum": "sha256:cb57ecfa6ebbefd8ffc7f75c0f00e57a7fa739578a429b6f72a0df19315deadc"
|
||||
}
|
||||
],
|
||||
"supportedServers": [
|
||||
{
|
||||
"serverId": "1",
|
||||
"serverType": "xlsize",
|
||||
"price": "50",
|
||||
"cpu": "16",
|
||||
"gpu": "0",
|
||||
"memory": "128gb",
|
||||
"disk": "160gb",
|
||||
"maxExecutionTime": 86400
|
||||
},
|
||||
{
|
||||
"serverId": "2",
|
||||
"serverType": "medium",
|
||||
"price": "10",
|
||||
"cpu": "2",
|
||||
"gpu": "0",
|
||||
"memory": "8gb",
|
||||
"disk": "80gb",
|
||||
"maxExecutionTime": 86400
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalInformation": {},
|
||||
"serviceAgreementTemplate": {
|
||||
"contractName": "EscrowComputeExecutionTemplate",
|
||||
"events": [
|
||||
{
|
||||
"name": "AgreementActorAdded",
|
||||
"actorType": "provider",
|
||||
"handler": {
|
||||
"moduleName": "",
|
||||
"functionName": "fulfillLockRewardCondition",
|
||||
"version": "0.1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"fulfillmentOrder": [
|
||||
"lockReward.fulfill",
|
||||
"computeExecution.fulfill",
|
||||
"escrowReward.fulfill"
|
||||
],
|
||||
"conditionDependency": {
|
||||
"lockReward": [],
|
||||
"computeExecution": [],
|
||||
"releaseReward": ["lockReward", "computeExecution"]
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"name": "lockReward",
|
||||
"timelock": 0,
|
||||
"timeout": 0,
|
||||
"contractName": "LockRewardCondition",
|
||||
"functionName": "fulfill",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "_rewardAddress",
|
||||
"type": "address",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "_amount",
|
||||
"type": "uint256",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "Fulfilled",
|
||||
"actorType": "provider",
|
||||
"handler": {
|
||||
"moduleName": "lockRewardExecutionCondition",
|
||||
"functionName": "fulfillComputeExecutionCondition",
|
||||
"version": "0.1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "computeExecution",
|
||||
"timelock": 0,
|
||||
"timeout": 0,
|
||||
"contractName": "ComputeExecutionCondition",
|
||||
"functionName": "fulfill",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "_documentId",
|
||||
"type": "bytes32",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "_grantee",
|
||||
"type": "address",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "Fulfilled",
|
||||
"actorType": "provider",
|
||||
"handler": {
|
||||
"moduleName": "accessSecretStore",
|
||||
"functionName": "fulfillEscrowRewardCondition",
|
||||
"version": "0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "TimedOut",
|
||||
"actorType": "consumer",
|
||||
"handler": {
|
||||
"moduleName": "accessSecretStore",
|
||||
"functionName": "refundReward",
|
||||
"version": "0.1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "escrowReward",
|
||||
"timelock": 0,
|
||||
"timeout": 0,
|
||||
"contractName": "EscrowReward",
|
||||
"functionName": "fulfill",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "_amount",
|
||||
"type": "uint256",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "_receiver",
|
||||
"type": "address",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "_sender",
|
||||
"type": "address",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "_lockCondition",
|
||||
"type": "bytes32",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "_releaseCondition",
|
||||
"type": "bytes32",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "Fulfilled",
|
||||
"actorType": "provider",
|
||||
"handler": {
|
||||
"moduleName": "escrowRewardCondition",
|
||||
"functionName": "verifyRewardTokens",
|
||||
"version": "0.1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "metadata",
|
||||
"index": 2,
|
||||
"serviceEndpoint": "http://myaquarius.org/api/v1/provider/assets/metadata/{did}",
|
||||
"attributes": {
|
||||
"main": {
|
||||
"name": "UK Weather information 2011",
|
||||
"type": "dataset",
|
||||
"dateCreated": "2012-10-10T17:00:000Z",
|
||||
"author": "Met Office",
|
||||
"license": "CC-BY",
|
||||
"price": "1000000000000000000",
|
||||
"files": [
|
||||
{
|
||||
"index": 0,
|
||||
"url": "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip",
|
||||
"checksum": "085340abffh21495345af97c6b0e761",
|
||||
"contentLength": "12324"
|
||||
},
|
||||
{
|
||||
"url": "https://testocnfiles.blob.core.windows.net/testfiles/testzkp2.zip"
|
||||
}
|
||||
]
|
||||
},
|
||||
"curation": {
|
||||
"rating": 0.93,
|
||||
"numVotes": 123,
|
||||
"schema": "Binary Voting"
|
||||
},
|
||||
"additionalInformation": {
|
||||
"description": "Weather information of UK including temperature and humidity",
|
||||
"copyrightHolder": "Met Office",
|
||||
"workExample": "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68",
|
||||
"links": [
|
||||
{
|
||||
"name": "Sample of Asset Data",
|
||||
"type": "sample",
|
||||
"url": "https://foo.com/sample.csv"
|
||||
},
|
||||
{
|
||||
"name": "Data Format Definition",
|
||||
"type": "format",
|
||||
"AssetID": "4d517500da0acb0d65a716f61330969334630363ce4a6a9d39691026ac7908ea"
|
||||
}
|
||||
],
|
||||
"inLanguage": "en",
|
||||
"categories": ["Economy", "Data Science"],
|
||||
"tags": ["weather", "uk", "2011", "temperature", "humidity"],
|
||||
"updateFrequency": "yearly",
|
||||
"structuredMarkup": [
|
||||
{
|
||||
"uri": "http://skos.um.es/unescothes/C01194/jsonld",
|
||||
"mediaType": "application/ld+json"
|
||||
},
|
||||
{
|
||||
"uri": "http://skos.um.es/unescothes/C01194/turtle",
|
||||
"mediaType": "text/turtle"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import WebServiceConnector from '../../src/utils/WebServiceConnector'
|
||||
import { WebServiceConnector } from '../../src/ocean/utils/WebServiceConnector'
|
||||
|
||||
// @ts-ignore
|
||||
export default class WebServiceConnectorMock extends WebServiceConnector {
|
@ -7,7 +7,7 @@ import { Ocean } from '../../../src/ocean/Ocean'
|
||||
import config from '../config'
|
||||
import TestContractHandler from '../keeper/TestContractHandler'
|
||||
|
||||
import * as jsonDDO from '../testdata/ddo.json'
|
||||
import * as jsonDDO from '../__fixtures__/ddo.json'
|
||||
|
||||
use(spies)
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { assert } from 'chai'
|
||||
import Account from '../../../src/ocean/Account'
|
||||
import { Ocean } from '../../../src/ocean/Ocean'
|
||||
import config from '../config'
|
||||
import ContractBaseMock from '../mocks/ContractBase.Mock'
|
||||
import ContractBaseMock from '../__mocks__/ContractBase.Mock'
|
||||
import TestContractHandler from './TestContractHandler'
|
||||
|
||||
const wrappedContract = new ContractBaseMock('OceanToken')
|
||||
|
@ -7,6 +7,13 @@ import config from '../config'
|
||||
interface ContractTest extends Contract {
|
||||
testContract?: boolean
|
||||
$initialized?: boolean
|
||||
options?: {
|
||||
address: string
|
||||
}
|
||||
methods?: {
|
||||
addMinter(address: string): any
|
||||
initialize(...args: any[]): any
|
||||
}
|
||||
}
|
||||
|
||||
export default class TestContractHandler extends ContractHandler {
|
||||
|
@ -1,13 +0,0 @@
|
||||
import { Brizo } from '../../../src/brizo/Brizo'
|
||||
|
||||
export default class BrizoMock extends Brizo {
|
||||
public async initializeServiceAgreement(
|
||||
did: string,
|
||||
serviceAgreementId: string,
|
||||
index: number,
|
||||
signature: string,
|
||||
consumerPublicKey: string
|
||||
): Promise<any> {
|
||||
return true
|
||||
}
|
||||
}
|
131
test/unit/ocean/OceanCompute.test.ts
Normal file
131
test/unit/ocean/OceanCompute.test.ts
Normal file
@ -0,0 +1,131 @@
|
||||
import { assert } from 'chai'
|
||||
import sinon from 'sinon'
|
||||
|
||||
import { Ocean } from '../../../src/ocean/Ocean'
|
||||
import config from '../config'
|
||||
import { Account } from '../../../src/squid'
|
||||
import { OceanCompute, ComputeJobStatus } from '../../../src/ocean/OceanCompute'
|
||||
import TestIdGenerator from '../TestIdGenerator'
|
||||
|
||||
describe('OceanCompute', () => {
|
||||
let ocean: Ocean
|
||||
let account: Account
|
||||
let compute: OceanCompute
|
||||
let agreementId: string
|
||||
|
||||
before(async () => {
|
||||
ocean = await Ocean.getInstance(config)
|
||||
;[account] = await ocean.accounts.list()
|
||||
compute = ocean.compute // eslint-disable-line prefer-destructuring
|
||||
agreementId = TestIdGenerator.generatePrefixedId()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sinon.reset()
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
describe('#start()', () => {
|
||||
it('should start a new job', async () => {
|
||||
sinon.stub(ocean.brizo, 'compute').returns([{ jobId: 'my-job-id' }] as any)
|
||||
const response = await compute.start(account, agreementId, 'did:op:0xxx')
|
||||
assert(response.jobId === 'my-job-id')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#stop()', () => {
|
||||
it('should stop a job', async () => {
|
||||
sinon
|
||||
.stub(ocean.brizo, 'compute')
|
||||
.returns([{ status: ComputeJobStatus.Completed }] as any)
|
||||
|
||||
const response = await compute.stop(account, agreementId, 'xxx')
|
||||
assert(response.status === ComputeJobStatus.Completed)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#restart()', () => {
|
||||
it('should restart a job', async () => {
|
||||
sinon
|
||||
.stub(ocean.brizo, 'compute')
|
||||
.returns([
|
||||
{ status: ComputeJobStatus.Started, jobId: 'my-job-id' }
|
||||
] as any)
|
||||
|
||||
const response = await compute.restart(account, agreementId, 'xxx')
|
||||
assert(response.jobId === 'my-job-id')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#delete()', () => {
|
||||
it('should delete a job', async () => {
|
||||
sinon
|
||||
.stub(ocean.brizo, 'compute')
|
||||
.returns([{ status: ComputeJobStatus.Deleted }] as any)
|
||||
|
||||
const response = await compute.delete(account, agreementId, 'xxx')
|
||||
assert(response.status === ComputeJobStatus.Deleted)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#status()', () => {
|
||||
it('should get the status of one job', async () => {
|
||||
sinon
|
||||
.stub(ocean.brizo, 'compute')
|
||||
.returns([{ status: ComputeJobStatus.Started }] as any)
|
||||
|
||||
const response = await compute.status(account, agreementId, 'xxx')
|
||||
assert(response.length === 1)
|
||||
assert(response[0].status === ComputeJobStatus.Started)
|
||||
})
|
||||
|
||||
it('should get the status of multiple jobs', async () => {
|
||||
sinon
|
||||
.stub(ocean.brizo, 'compute')
|
||||
.returns([
|
||||
{ status: ComputeJobStatus.Started },
|
||||
{ status: ComputeJobStatus.Started }
|
||||
] as any)
|
||||
|
||||
const response = await compute.status(account, agreementId)
|
||||
assert(response.length === 2)
|
||||
assert(response[0].status === ComputeJobStatus.Started)
|
||||
})
|
||||
|
||||
it('should get all jobs for one owner', async () => {
|
||||
sinon
|
||||
.stub(ocean.brizo, 'compute')
|
||||
.returns([
|
||||
{ status: ComputeJobStatus.Started },
|
||||
{ status: ComputeJobStatus.Started }
|
||||
] as any)
|
||||
|
||||
const response = await compute.status(account)
|
||||
assert(response.length === 2)
|
||||
assert(response[0].status === ComputeJobStatus.Started)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#checkOutput()', () => {
|
||||
it('should return default values', async () => {
|
||||
const defaultOutput = { publishAlgorithmLog: false, publishOutput: false }
|
||||
const output = compute.checkOutput(account, undefined)
|
||||
assert.deepEqual(output, defaultOutput)
|
||||
})
|
||||
|
||||
it('should return output values', async () => {
|
||||
const newOutput = {
|
||||
publishAlgorithmLog: true,
|
||||
publishOutput: true,
|
||||
brizoAddress: 'hello',
|
||||
brizoUri: 'hello',
|
||||
metadataUri: 'hello',
|
||||
nodeUri: 'hello',
|
||||
owner: '0xhello',
|
||||
secretStoreUri: 'hello'
|
||||
}
|
||||
const output = compute.checkOutput(account, newOutput)
|
||||
assert.deepEqual(output, newOutput)
|
||||
})
|
||||
})
|
||||
})
|
215
test/unit/testdata/ddo.json
vendored
215
test/unit/testdata/ddo.json
vendored
@ -1,215 +0,0 @@
|
||||
{
|
||||
"@context": "https://w3id.org/future-method/v1",
|
||||
"id": "did:op:08a429b8529856d59867503f8056903a680935a76950bb9649785cc97869a43d",
|
||||
"publicKey": [
|
||||
{
|
||||
"id": "did:op:123456789abcdefghi#keys-1",
|
||||
"type": "RsaVerificationKey2018",
|
||||
"owner": "did:op:123456789abcdefghi",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
|
||||
},
|
||||
{
|
||||
"id": "did:op:123456789abcdefghi#keys-2",
|
||||
"type": "Ed25519VerificationKey2018",
|
||||
"owner": "did:op:123456789abcdefghi",
|
||||
"publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
|
||||
},
|
||||
{
|
||||
"id": "did:op:123456789abcdefghi#keys-3",
|
||||
"type": "RsaPublicKeyExchangeKey2018",
|
||||
"owner": "did:op:123456789abcdefghi",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
|
||||
}
|
||||
],
|
||||
"authentication": [
|
||||
{
|
||||
"type": "RsaSignatureAuthentication2018",
|
||||
"publicKey": "did:op:123456789abcdefghi#keys-1"
|
||||
},
|
||||
{
|
||||
"type": "ieee2410Authentication2018",
|
||||
"publicKey": "did:op:123456789abcdefghi#keys-2"
|
||||
}
|
||||
],
|
||||
"proof": {
|
||||
"type": "UUIDSignature",
|
||||
"created": "2016-02-08T16:02:20Z",
|
||||
"creator": "did:example:8uQhQMGzWxR8vw5P3UWH1ja",
|
||||
"signatureValue": "QNB13Y7Q9...1tzjn4w=="
|
||||
},
|
||||
"service": [
|
||||
{
|
||||
"type": "access",
|
||||
"index": 0,
|
||||
"serviceEndpoint": "http://mybrizo.org/api/v1/brizo/services/consume?pubKey=${pubKey}&serviceId={serviceId}&url={url}",
|
||||
"purchaseEndpoint": "http://mybrizo.org/api/v1/brizo/services/access/purchase?",
|
||||
"templateId": "044852b2a670ade5407e78fb2863c51000000000000000000000000000000000",
|
||||
"conditions": [
|
||||
{
|
||||
"name": "lockPayment",
|
||||
"timeout": 0,
|
||||
"conditionKey": {
|
||||
"contractAddress": "0x...",
|
||||
"fingerprint": "0x..."
|
||||
},
|
||||
"parameters": {
|
||||
"assetId": "bytes32",
|
||||
"price": "integer"
|
||||
},
|
||||
"events": {
|
||||
"PaymentLocked": {
|
||||
"actorType": ["publisher"],
|
||||
"handlers": [
|
||||
{
|
||||
"moduleName": "accessControl",
|
||||
"functionName": "grantAccess",
|
||||
"version": "0.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "releasePayment",
|
||||
"timeout": 0,
|
||||
"conditionKey": {
|
||||
"contractAddress": "0x...",
|
||||
"fingerprint": "0xXXXXXXXX"
|
||||
},
|
||||
"parameters": {
|
||||
"assetId": "bytes32",
|
||||
"price": "integer"
|
||||
},
|
||||
"events": {
|
||||
"PaymentReleased": {
|
||||
"actorType": ["publisher"],
|
||||
"handlers": [
|
||||
{
|
||||
"moduleName": "serviceAgreement",
|
||||
"functionName": "fulfillAgreement",
|
||||
"version": "0.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "grantAccess",
|
||||
"timeout": 0,
|
||||
"conditionKey": {
|
||||
"contractAddress": "0x",
|
||||
"fingerprint": "0xXXXXXXXX"
|
||||
},
|
||||
"parameters": {
|
||||
"assetId": "bytes32",
|
||||
"documentKeyId": "bytes32"
|
||||
},
|
||||
"events": {
|
||||
"AccessGranted": {
|
||||
"actorType": ["consumer"],
|
||||
"handlers": [
|
||||
{
|
||||
"moduleName": "asset",
|
||||
"functionName": "consumeService",
|
||||
"version": "0.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "refundPayment",
|
||||
"timeout": 1,
|
||||
"condition_key": {
|
||||
"contractAddress": "0x...",
|
||||
"fingerprint": "0xXXXXXXXX"
|
||||
},
|
||||
"parameters": {
|
||||
"assetId": "bytes32",
|
||||
"price": "int"
|
||||
},
|
||||
"events": {
|
||||
"PaymentRefund": {
|
||||
"actorType": ["consumer"],
|
||||
"handlers": [
|
||||
{
|
||||
"moduleName": "serviceAgreement",
|
||||
"functionName": "fulfillAgreement",
|
||||
"version": "0.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "compute",
|
||||
"index": 1,
|
||||
"serviceEndpoint": "http://mybrizo.org/api/v1/brizo/services/compute?pubKey=${pubKey}&serviceId={serviceId}&algo={algo}&container={container}",
|
||||
"templateId": "044852b2a670ade5407e78fb2863c51000000000000000000000000000000002"
|
||||
},
|
||||
{
|
||||
"type": "metadata",
|
||||
"index": 2,
|
||||
"serviceEndpoint": "http://myaquarius.org/api/v1/provider/assets/metadata/{did}",
|
||||
"attributes": {
|
||||
"main": {
|
||||
"name": "UK Weather information 2011",
|
||||
"type": "dataset",
|
||||
"dateCreated": "2012-10-10T17:00:000Z",
|
||||
"author": "Met Office",
|
||||
"license": "CC-BY",
|
||||
"price": 10,
|
||||
"files": [
|
||||
{
|
||||
"index": 0,
|
||||
"url": "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip",
|
||||
"checksum": "085340abffh21495345af97c6b0e761",
|
||||
"contentLength": "12324"
|
||||
},
|
||||
{
|
||||
"url": "https://testocnfiles.blob.core.windows.net/testfiles/testzkp2.zip"
|
||||
}
|
||||
]
|
||||
},
|
||||
"curation": {
|
||||
"rating": 0.93,
|
||||
"numVotes": 123,
|
||||
"schema": "Binary Voting"
|
||||
},
|
||||
"additionalInformation": {
|
||||
"description": "Weather information of UK including temperature and humidity",
|
||||
"copyrightHolder": "Met Office",
|
||||
"workExample": "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68",
|
||||
"links": [
|
||||
{
|
||||
"name": "Sample of Asset Data",
|
||||
"type": "sample",
|
||||
"url": "https://foo.com/sample.csv"
|
||||
},
|
||||
{
|
||||
"name": "Data Format Definition",
|
||||
"type": "format",
|
||||
"AssetID": "4d517500da0acb0d65a716f61330969334630363ce4a6a9d39691026ac7908ea"
|
||||
}
|
||||
],
|
||||
"inLanguage": "en",
|
||||
"categories": ["Economy", "Data Science"],
|
||||
"tags": ["weather", "uk", "2011", "temperature", "humidity"],
|
||||
"updateFrequency": "yearly",
|
||||
"structuredMarkup": [
|
||||
{
|
||||
"uri": "http://skos.um.es/unescothes/C01194/jsonld",
|
||||
"mediaType": "application/ld+json"
|
||||
},
|
||||
{
|
||||
"uri": "http://skos.um.es/unescothes/C01194/turtle",
|
||||
"mediaType": "text/turtle"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user