1
0
mirror of https://github.com/oceanprotocol-archive/squid-js.git synced 2024-02-02 15:31:51 +01:00

Merge remote-tracking branch 'origin/feature/secret_store' into greenkeeper/bignumber.js-8.0.0

# Conflicts:
#	package.json
This commit is contained in:
Sebastian Gerske 2018-11-01 13:34:10 +01:00
commit f6ac9fc323
57 changed files with 1583 additions and 147 deletions

View File

@ -33,7 +33,7 @@
Start by adding the package to your dependencies:
```bash
npm i @oceanprotocol/squid
npm i @oceanprotocol/squid --save
```
The package exposes `Ocean` and `Logger` which you can import in your code like this:
@ -46,10 +46,13 @@ import { Ocean, Logger } from '@oceanprotocol/squid'
const { Ocean, Logger } = require('@oceanprotocol/squid')
```
You can then connect to a running [Keeper](https://github.com/oceanprotocol/keeper-contracts) & [Provider](https://github.com/oceanprotocol/provider) instance, e.g.:
You can then connect to a running [Keeper](https://github.com/oceanprotocol/keeper-contracts) & [Aquarius](https://github.com/oceanprotocol/aquarius) instance, e.g.:
```js
const ocean = await new Ocean({nodeUri: 'http://localhost:8545', network: 'development', providerUri: 'http://localhost:5000'})
const ocean = await new Ocean({
nodeUri: 'http://localhost:8545',
aquariusUri: 'http://localhost:5000'
})
```
## Development

84
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "@oceanprotocol/squid",
"version": "0.1.0-beta.17",
"version": "0.1.0-beta.20",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -120,14 +120,22 @@
}
},
"@oceanprotocol/keeper-contracts": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@oceanprotocol/keeper-contracts/-/keeper-contracts-0.4.1.tgz",
"integrity": "sha512-UmgPsJul9ZJb5BPIa1qfMpokJWzdROni/wisd4Dnm+wwHUA7/ymsr34zVn+4v+uAcMLHAYPKbsROBT5xlbiKAQ=="
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/@oceanprotocol/keeper-contracts/-/keeper-contracts-0.3.7.tgz",
"integrity": "sha512-Yx+ucPIjLsn/Rvs0G8sPpjKWmmUQv5x9YBdO6pHutSGO82PkVBCydV4mB5Wx3Pqr3KmW0S34ve07KmUN3qtc7A=="
},
"@oceanprotocol/secret-store-client": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/@oceanprotocol/secret-store-client/-/secret-store-client-0.0.7.tgz",
"integrity": "sha512-NaqJJ0AlgIbV4WIIRbetjd6PCXux8sT2kZgw1GGmky9b7PZvG4AWm/rPN/1lmJJ2ccx3gwUpQTPrP2SLHRBTuw==",
"requires": {
"node-fetch": "^2.2.0"
}
},
"@types/chai": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.6.tgz",
"integrity": "sha512-CBk7KTZt3FhPsEkYioG6kuCIpWISw+YI8o+3op4+NXwTpvAPxE1ES8+PY8zfaK2L98b1z5oq03UHa4VYpeUxnw==",
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz",
"integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==",
"dev": true
},
"@types/events": {
@ -1969,6 +1977,11 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
},
"uuid": {
"version": "2.0.1",
"resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz",
"integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w="
}
}
},
@ -2495,13 +2508,11 @@
},
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"optional": true
"bundled": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -2514,18 +2525,15 @@
},
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"optional": true
"bundled": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"optional": true
"bundled": true
},
"core-util-is": {
"version": "1.0.2",
@ -2628,8 +2636,7 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true,
"optional": true
"bundled": true
},
"ini": {
"version": "1.3.5",
@ -2639,7 +2646,6 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -2652,20 +2658,17 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true,
"optional": true
"bundled": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@ -2682,7 +2685,6 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -2755,8 +2757,7 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"object-assign": {
"version": "4.1.1",
@ -2766,7 +2767,6 @@
"once": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -2873,7 +2873,6 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -4341,7 +4340,6 @@
"version": "0.1.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"kind-of": "^3.0.2",
"longest": "^1.0.1",
@ -4666,8 +4664,7 @@
"is-buffer": {
"version": "1.1.6",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"is-builtin-module": {
"version": "1.0.0",
@ -4751,7 +4748,6 @@
"version": "3.2.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"is-buffer": "^1.1.5"
}
@ -4798,8 +4794,7 @@
"longest": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"lru-cache": {
"version": "4.1.3",
@ -5065,8 +5060,7 @@
"repeat-string": {
"version": "1.6.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"require-directory": {
"version": "2.1.1",
@ -7365,9 +7359,9 @@
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"uuid": {
"version": "2.0.1",
"resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz",
"integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w="
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
},
"v8-compile-cache": {
"version": "2.0.2",
@ -7556,6 +7550,13 @@
"setimmediate": "1.0.4",
"uuid": "2.0.1",
"xmlhttprequest": "1.8.0"
},
"dependencies": {
"uuid": {
"version": "2.0.1",
"resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz",
"integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w="
}
}
},
"hash.js": {
@ -7595,6 +7596,11 @@
"elliptic": "^6.4.0",
"xhr-request-promise": "^0.1.2"
}
},
"uuid": {
"version": "2.0.1",
"resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz",
"integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w="
}
}
},

View File

@ -1,15 +1,16 @@
{
"name": "@oceanprotocol/squid",
"version": "0.1.0-beta.17",
"version": "0.1.0-beta.20",
"description": "JavaScript client library for Ocean Protocol",
"main": "dist/squid.js",
"scripts": {
"test": "mocha",
"test:watch": "mocha -w --watch-extensions js,ts",
"test:watch": "mocha -w --watch-extensions js,ts,json",
"test:cover": "nyc mocha",
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"start": "npm link @oceanprotocol/keeper-contracts && npm run build:watch",
"build": "npm run lint && tsc && npm run doc",
"clean": "rm -rf ./dist/ ./doc/ ./coverage ./.nyc_output",
"lint": "tslint -c tslint.json 'src/**/*.ts' 'test/**/*.ts'",
"start": "npm link @oceanprotocol/keeper-contracts @oceanprotocol/secret-store-client && npm run build:watch",
"build": "npm run clean && npm run lint && tsc && npm run doc",
"build:watch": "tsc -w",
"doc": "typedoc --mode modules --out ./doc/ src/",
"release": "./node_modules/release-it/bin/release-it.js --src.tagName='v%s' --github.release --npm.publish --non-interactive",
@ -50,17 +51,19 @@
},
"dependencies": {
"@oceanprotocol/keeper-contracts": "^0.4.1",
"@oceanprotocol/secret-store-client": "^0.0.7",
"bignumber.js": "^8.0.0",
"eth-crypto": "^1.2.4",
"eth-ecies": "^1.0.3",
"ethereumjs-util": "^6.0.0",
"jsonwebtoken": "^8.3.0",
"node-fetch": "^2.2.0",
"uuid": "^3.3.2",
"web3": "1.0.0-beta.36",
"web3-utils": "1.0.0-beta.36"
},
"devDependencies": {
"@types/chai": "^4.1.6",
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.5",
"@types/node": "^8.10.36",
"chai": "^4.2.0",

View File

@ -1,6 +1,9 @@
import {URL} from "url"
import DDO from "../ddo/DDO"
import Config from "../models/Config"
import Logger from "../utils/Logger"
import AquariusConnectorProvider from "./AquariusConnectorProvider"
import SearchQuery from "./query/SearchQuery"
export default class Aquarius {
@ -13,31 +16,30 @@ export default class Aquarius {
public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
const accessUrl = await AquariusConnectorProvider.getConnector().post(
`${accessToken.service_endpoint}/${accessToken.resource_id}`,
payload)
.then((response: any) => {
const accessUrl: string = await AquariusConnectorProvider.getConnector()
.post(`${accessToken.service_endpoint}/${accessToken.resource_id}`, payload)
.then((response: any): string => {
if (response.ok) {
return response.text()
}
Logger.log("Failed: ", response.status, response.statusText)
Logger.error("Failed: ", response.status, response.statusText)
})
.then((consumptionUrl: string) => {
.then((consumptionUrl: string): string => {
Logger.log("Success accessing consume endpoint: ", consumptionUrl)
return consumptionUrl
})
.catch((error) => {
Logger.error("Error fetching the data asset consumption url: ", error)
return null
})
return accessUrl
}
public async queryMetadata(query): Promise<any[]> {
public async queryMetadata(query: SearchQuery): Promise<any[]> {
const result = await AquariusConnectorProvider.getConnector().post(
this.url + "/api/v1/aquarius/assets/ddo/query",
JSON.stringify(query))
const result = await AquariusConnectorProvider.getConnector()
.post(this.url + "/api/v1/aquarius/assets/ddo/query", JSON.stringify(query))
.then((response: any) => {
if (response.ok) {
return response.json()
@ -51,11 +53,15 @@ export default class Aquarius {
return result
}
public async queryMetadataByText(query): Promise<any[]> {
public async queryMetadataByText(query: SearchQuery): Promise<any[]> {
const result = await AquariusConnectorProvider.getConnector().get(
this.url + "/api/v1/aquarius/assets/ddo/query",
JSON.stringify(query))
const fullUrl = new URL(this.url + "/api/v1/aquarius/assets/ddo/query")
fullUrl.searchParams.append("text", query.text)
fullUrl.searchParams.append("sort", JSON.stringify(query.sort))
fullUrl.searchParams.append("offset", query.offset.toString())
fullUrl.searchParams.append("page", query.page.toString())
const result = await AquariusConnectorProvider.getConnector()
.get(fullUrl)
.then((response: any) => {
if (response.ok) {
return response.json()
@ -68,4 +74,38 @@ export default class Aquarius {
return result
}
public async storeDDO(ddo: DDO): Promise<DDO> {
const fullUrl = this.url + `/api/v1/aquarius/assets/ddo`
const result: DDO = await AquariusConnectorProvider.getConnector()
.post(fullUrl, DDO.serialize(ddo))
.then((response: any) => {
if (response.ok) {
return response.json()
}
Logger.log("Failed:", response.status, response.statusText)
})
.catch((error) => {
Logger.error("Error fetching querying metadata: ", error)
})
return result
}
public async retrieveDDO(did: string): Promise<DDO> {
const fullUrl = this.url + `/api/v1/aquarius/assets/ddo/${did}`
const result = await AquariusConnectorProvider.getConnector()
.get(fullUrl)
.then((response: any) => {
if (response.ok) {
return response.json()
}
Logger.log("Failed:", response.status, response.statusText)
})
.catch((error) => {
Logger.error("Error fetching querying metadata: ", error)
})
return result
}
}

View File

@ -1,10 +1,9 @@
import fetch from "node-fetch"
import { URL } from "url"
export default class AquariusConnector {
public post(url, payload) {
return fetch(url, {
public async post(url, payload): Promise<any> {
return this.fetch(url, {
method: "POST",
body: payload,
headers: {
@ -13,17 +12,26 @@ export default class AquariusConnector {
})
}
public get(url, payload) {
const fullUrl = new URL(url)
for (const key of Object.keys(payload)) {
fullUrl.searchParams.append(key, payload[key])
}
return fetch(fullUrl, {
public async get(url): Promise<any> {
return this.fetch(url, {
method: "GET",
body: null,
headers: {
"Content-type": "application/json",
},
})
}
public async put(url, payload): Promise<any> {
return this.fetch(url, {
method: "PUT",
body: payload,
headers: {
"Content-type": "application/json",
},
})
}
private async fetch(url, opts): Promise<any> {
return fetch(url, opts)
}
}

View File

@ -1,21 +1,17 @@
import Logger from "../utils/Logger"
import AquariusConnector from "./AquariusConnector"
export default class AquariusConnectorProvider {
public static setConnector(connector: AquariusConnector) {
Logger.log("setting", typeof connector.constructor.name)
AquariusConnectorProvider.connector = connector
}
public static getConnector() {
public static getConnector(): AquariusConnector {
if (!AquariusConnectorProvider.connector) {
AquariusConnectorProvider.connector = new AquariusConnector()
}
Logger.log("getting", typeof AquariusConnectorProvider.connector.constructor.name)
return AquariusConnectorProvider.connector
}

View File

@ -0,0 +1,3 @@
export default class Query {
public value: number = 1
}

View File

@ -0,0 +1,14 @@
import Query from "./Query"
import Sort from "./Sort"
export default class SearchQuery {
public offset: number = 100
public page: number = 0
public query: Query = {
value: 1,
} as Query
public sort: Sort = {
value: 1,
} as Sort
public text: string = "Office"
}

View File

@ -0,0 +1,3 @@
export default class Sort {
public value: number = 1
}

View File

@ -0,0 +1,15 @@
import StructuredMarkup from "./StructuredMarkup"
export default class AdditionalInformation {
public updateFrecuency: string = "yearly"
public structuredMarkup: StructuredMarkup[] = [
{
uri: "http://skos.um.es/unescothes/C01194/jsonld",
mediaType: "application/ld+json",
} as StructuredMarkup,
{
uri: "http://skos.um.es/unescothes/C01194/turtle",
mediaType: "text/turtle",
}as StructuredMarkup,
]
}

View File

@ -0,0 +1,4 @@
export default class Authentication {
public type: string = "RsaSignatureAuthentication2018"
public publicKey: string = "did:op:123456789abcdefghi#keys-1"
}

5
src/ddo/Curation.ts Normal file
View File

@ -0,0 +1,5 @@
export default class Curation {
public rating: number = 0.93
public numVotes: number = 123
public schema: string = "Binary Votting"
}

37
src/ddo/DDO.ts Normal file
View File

@ -0,0 +1,37 @@
import Authentication from "./Authentication"
import PublicKey from "./PublicKey"
import Service from "./Service"
export default class DDO {
public static serialize(ddo: DDO): string {
return JSON.stringify(ddo, null, 2)
}
public static deserialize(ddoString: string): DDO {
const ddo = JSON.parse(ddoString)
return ddo as DDO
}
public "@context": string = "https://w3id.org/future-method/v1"
public id: string
public publicKey: PublicKey[]
public authentication: Authentication[]
public service: Service[]
// @ts-ignore
private assa: string
public constructor(ddo?: {
id?: string,
publicKey?: PublicKey[],
authentication?: Authentication[],
service?: Service[],
}) {
this.id = ddo ? ddo.id ? ddo.id : null : null
this.publicKey = ddo ? ddo.publicKey ? ddo.publicKey : [] : []
this.authentication = ddo ? ddo.authentication ? ddo.authentication : [] : []
this.service = ddo ? ddo.service ? ddo.service : [] : []
}
}

59
src/ddo/MetaData.ts Normal file
View File

@ -0,0 +1,59 @@
import AdditionalInformation from "./AdditionalInformation"
import Curation from "./Curation"
import MetaDataBase from "./MetaDataBase"
import StructuredMarkup from "./StructuredMarkup"
export default class MetaData {
public base: MetaDataBase = {
name: "UK Weather information 2011",
type: "dataset",
description: "Weather information of UK including temperature and humidity",
size: "3.1gb",
dateCreated: "2012-10-10T17:00:000Z",
author: "Met Office",
license: "CC-BY",
copyrightHolder: "Met Office",
encoding: "UTF-8",
compression: "zip",
contentType: "text/csv",
workExample: "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68",
contentUrls: [
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip",
],
links: [
{
sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/",
},
{
sample2: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/",
},
{
fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/",
},
],
inLanguage: "en",
tags: "weather, uk, 2011, temperature, humidity",
price: 10,
} as MetaDataBase
public curation: Curation = {
rating: 0.93,
numVotes: 123,
schema: "Binary Votting",
} as Curation
public additionalInformation: AdditionalInformation = {
updateFrecuency: "yearly",
structuredMarkup: [
{
uri: "http://skos.um.es/unescothes/C01194/jsonld",
mediaType: "application/ld+json",
} as StructuredMarkup,
{
uri: "http://skos.um.es/unescothes/C01194/turtle",
mediaType: "text/turtle",
} as StructuredMarkup,
],
} as AdditionalInformation
}

31
src/ddo/MetaDataBase.ts Normal file
View File

@ -0,0 +1,31 @@
export default class MetaDataBase {
public name: string = "UK Weather information 2011"
public type: string = "dataset"
public description: string = "Weather information of UK including temperature and humidity"
public size: string = "3.1gb"
public dateCreated: string = "2012-10-10T17:00:000Z"
public author: string = "Met Office"
public license: string = "CC-BY"
public copyrightHolder: string = "Met Office"
public encoding: string = "UTF-8"
public compression: string = "zip"
public contentType: string = "text/csv"
public workExample: string = "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68"
public contentUrls: string[] = [
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip",
]
public links: any[] = [
{
sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/",
},
{
sample2: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/",
},
{
fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/",
},
]
public inLanguage: string = "en"
public tags: string = "weather, uk, 2011, temperature, humidity"
public price: number = 10
}

7
src/ddo/PublicKey.ts Normal file
View File

@ -0,0 +1,7 @@
export default class PublicKey {
public id: string = "did:op:123456789abcdefghi#keys-1"
public type: string = "RsaVerificationKey2018"
public owner: string = "did:op:123456789abcdefghi"
public publicKeyPem?: string = "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
public publicKeyBase58?: string = "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
}

8
src/ddo/Service.ts Normal file
View File

@ -0,0 +1,8 @@
import MetaData from "./MetaData"
export default class Service {
public type: string = "OpenIdConnectVersion1.0Service"
public serviceEndpoint: string = "https://openid.example.com/"
public description?: string = "My public social inbox"
public metadata?: MetaData = {} as MetaData
}

View File

@ -0,0 +1,4 @@
export default class StructuredMarkup {
public uri: string = "http://skos.um.es/unescothes/C01194/jsonld"
public mediaType: string = "application/ld+json"
}

View File

@ -3,14 +3,12 @@ import Logger from "../utils/Logger"
import Keeper from "./Keeper"
import Web3Provider from "./Web3Provider"
const contracts: Map<string, Contract> = new Map<string, Contract>()
export default class ContractHandler {
public static async get(what: string): Contract {
const where = (await (await Keeper.getInstance()).getNetworkName()).toLowerCase()
try {
return contracts.get(what) || await ContractHandler.load(what, where)
return ContractHandler.contracts.get(what) || await ContractHandler.load(what, where)
} catch (err) {
Logger.error("Failed to load", what, "from", where, err)
throw err
@ -50,6 +48,20 @@ export default class ContractHandler {
const market = await ContractHandler.deployContract("OceanMarket", deployerAddress, {
args: [token.options.address],
})
const sa = await ContractHandler.deployContract("ServiceAgreement", deployerAddress, {
args: [],
})
await ContractHandler.deployContract("AccessConditions", deployerAddress, {
args: [sa.options.address],
})
await ContractHandler.deployContract("PaymentConditions", deployerAddress, {
args: [sa.options.address, token.options.address],
})
await ContractHandler.deployContract("DIDRegistry", deployerAddress, {})
/* not part of trilobite
const dispute = await ContractHandler.deployContract("OceanDispute", deployerAddress, {
args: [market.options.address, registry.options.address, plcrVoting.options.address],
@ -60,6 +72,8 @@ export default class ContractHandler {
})
}
private static contracts: Map<string, Contract> = new Map<string, Contract>()
private static async load(what: string, where: string): Promise<Contract> {
const web3 = Web3Provider.getWeb3()
// Logger.log("Loading", what, "from", where)
@ -73,8 +87,8 @@ export default class ContractHandler {
// Logger.log("Getting instance of", what, "from", where, "at", artifact.address)
const contract = new web3.eth.Contract(artifact.abi, artifact.address)
Logger.log("Loaded", what, "from", where)
contracts.set(what, contract)
return contracts.get(what)
ContractHandler.contracts.set(what, contract)
return ContractHandler.contracts.get(what)
}
// todo: reactivate for tethys
@ -94,8 +108,8 @@ export default class ContractHandler {
private static async deployContract(name: string, from: string, params?): Promise<Contract> {
// dont redeploy if there is already something loaded
if (contracts.has(name)) {
return contracts.get(name)
if (ContractHandler.contracts.has(name)) {
return ContractHandler.contracts.get(name)
}
const web3 = Web3Provider.getWeb3()
@ -116,7 +130,7 @@ export default class ContractHandler {
gas: 3000000,
gasPrice: 10000000000,
})
contracts.set(name, contractInstance)
ContractHandler.contracts.set(name, contractInstance)
// Logger.log("Deployed", name, "at", contractInstance.options.address);
} catch (err) {
Logger.error("Deployment failed for", name, "with params", JSON.stringify(params, null, 2), err.message)

View File

@ -0,0 +1,17 @@
import MethodReflection from "../models/MethodReflection"
import GenericContract from "./contracts/GenericContract"
export default class ContractReflector {
public static async reflectContractMethod(pathToMethod: string): Promise<MethodReflection> {
const parts: string[] = pathToMethod.split(".")
const contract = await GenericContract.getInstance(parts[0])
return {
contractName: parts[0],
methodName: parts[1],
address: contract.getAddress(),
signature: contract.getSignatureOfMethod(parts[1]),
} as MethodReflection
}
}

View File

@ -1,6 +1,7 @@
import OceanAuth from "./Auth"
import OceanMarket from "./Market"
import OceanToken from "./Token"
import OceanAuth from "./contracts/Auth"
import OceanMarket from "./contracts/Market"
import ServiceAgreement from "./contracts/ServiceAgreement"
import OceanToken from "./contracts/Token"
import Web3Provider from "./Web3Provider"
export default class Keeper {
@ -13,6 +14,7 @@ export default class Keeper {
Keeper.instance.market = await OceanMarket.getInstance()
Keeper.instance.auth = await OceanAuth.getInstance()
Keeper.instance.token = await OceanToken.getInstance()
Keeper.instance.serviceAgreement = await ServiceAgreement.getInstance()
}
return Keeper.instance
}
@ -22,6 +24,7 @@ export default class Keeper {
public token: OceanToken
public market: OceanMarket
public auth: OceanAuth
public serviceAgreement: ServiceAgreement
public async getNetworkName(): Promise<string> {
return Web3Provider.getWeb3().eth.net.getId()

View File

@ -1,8 +1,5 @@
import * as Web3 from "web3"
import ConfigProvider from "../ConfigProvider"
import Logger from "../utils/Logger"
Logger.log("using web3", Web3.version)
export default class Web3Provider {

View File

@ -1,7 +1,7 @@
import {Receipt} from "web3-utils"
import AccessStatus from "../models/AccessStatus"
import Asset from "../ocean/Asset"
import Order from "../ocean/Order"
import AccessStatus from "../../models/AccessStatus"
import Asset from "../../ocean/Asset"
import Order from "../../ocean/Order"
import ContractBase from "./ContractBase"
export default class OceanAuth extends ContractBase {
@ -27,13 +27,13 @@ export default class OceanAuth extends ContractBase {
public async initiateAccessRequest(asset: Asset, publicKey: string,
timeout: number, buyerAddress: string): Promise<Receipt> {
const args = [asset.getId(), asset.publisher.getId(), publicKey, timeout]
return this.sendTransaction("initiateAccessRequest", buyerAddress, args)
const args = ["0x" + asset.getId(), asset.publisher.getId(), publicKey, timeout]
return this.send("initiateAccessRequest", buyerAddress, args)
}
public async commitAccessRequest(order: Order, publisherAddress: string) {
const args = [order.getId(), true, 9999999999, "discovery", "read", "slaLink", "slaType"]
return this.sendTransaction("commitAccessRequest", publisherAddress, args)
return this.send("commitAccessRequest", publisherAddress, args)
}
public async getTempPubKey(orderId: string) {
@ -41,7 +41,7 @@ export default class OceanAuth extends ContractBase {
}
public async deliverAccessToken(orderId: string, accessToken: string, publisherAddress: string) {
return this.sendTransaction("deliverAccessToken", publisherAddress, [orderId, accessToken])
return this.send("deliverAccessToken", publisherAddress, [orderId, accessToken])
}
}

View File

@ -1,7 +1,8 @@
import Event from "web3"
import Contract from "web3-eth-contract"
import Logger from "../utils/Logger"
import ContractHandler from "./ContractHandler"
import {Receipt} from "web3-utils"
import Logger from "../../utils/Logger"
import ContractHandler from "../ContractHandler"
export default abstract class ContractBase {
@ -32,7 +33,7 @@ export default abstract class ContractBase {
public async getEventData(eventName: any, options: any): Promise<Event[]> {
if (!this.contract.events[eventName]) {
throw new Error(`Event ${eventName} not found on contract ${this.contractName}`)
throw new Error(`Event "${eventName}" not found on contract "${this.contractName}"`)
}
return this.contract.getPastEvents(eventName, options)
}
@ -41,13 +42,28 @@ export default abstract class ContractBase {
return this.contract.options.address
}
public getSignatureOfMethod(methodName: string): string {
const foundMethod = this.contract.options.jsonInterface.find((method) => {
if (method.name === methodName) {
return method
}
})
if (!foundMethod) {
throw new Error(`Method "${methodName}" is not part of contract "${this.contractName}"`)
}
return foundMethod.signature
}
protected async init() {
this.contract = await ContractHandler.get(this.contractName)
}
protected async sendTransaction(name: string, from: string, args: any[]) {
protected async send(name: string, from: string, args: any[]): Promise<Receipt> {
if (!this.contract.methods[name]) {
throw new Error(`Method ${name} is not part of contract ${this.contractName}`)
throw new Error(`Method "${name}" is not part of contract "${this.contractName}"`)
}
try {
const tx = this.contract.methods[name](...args)
@ -60,13 +76,13 @@ export default abstract class ContractBase {
})
} catch (err) {
const argString = JSON.stringify(args, null, 2)
Logger.error(`Sending transaction ${name} on contract ${this.contractName} failed.`)
Logger.error(`Sending transaction "${name}" on contract "${this.contractName}" failed.`)
Logger.error(`Args: ${argString} From: ${from}`)
throw err
}
}
protected async call(name: string, args: any[], from?: string) {
protected async call(name: string, args: any[], from?: string): Promise<any> {
if (!this.contract.methods[name]) {
throw new Error(`Method ${name} is not part of contract ${this.contractName}`)
}
@ -74,7 +90,7 @@ export default abstract class ContractBase {
const method = this.contract.methods[name](...args)
return method.call(from ? {from} : null)
} catch (err) {
Logger.error(`Calling method ${name} on contract ${this.contractName} failed. Args: ${args}`, err)
Logger.error(`Calling method "${name}" on contract "${this.contractName}" failed. Args: ${args}`, err)
throw err
}
}

View File

@ -0,0 +1,37 @@
import {Receipt} from "web3-utils"
import ValueType from "../../models/ValueType"
import ContractBase from "./ContractBase"
export default class DIDRegistry extends ContractBase {
public static async getInstance(): Promise<DIDRegistry> {
const didRegistry: DIDRegistry = new DIDRegistry("DIDRegistry")
await didRegistry.init()
return didRegistry
}
public async registerAttribute(did: string, type: ValueType, key: string,
value: string, ownerAddress: string): Promise<Receipt> {
return this.send("registerAttribute",
ownerAddress, ["0x" + did, type, key, value],
)
}
public async getOwner(did: string): Promise<string> {
return this.call("getOwner",
["0x" + did],
)
}
public async getUpdateAt(did: string): Promise<number> {
const blockNum = await this.call("getUpdateAt",
["0x" + did],
)
return parseInt(blockNum, 10)
}
}

View File

@ -0,0 +1,14 @@
import ContractBase from "./ContractBase"
export default class GenericContract extends ContractBase {
public static async getInstance(contractName: string) {
const contract: GenericContract = new GenericContract(contractName)
await contract.init()
return contract
}
private constructor(contractName: string) {
super(contractName)
}
}

View File

@ -1,6 +1,6 @@
import BigNumber from "bignumber.js"
import {Receipt} from "web3-utils"
import Order from "../ocean/Order"
import Order from "../../ocean/Order"
import ContractBase from "./ContractBase"
export default class OceanMarket extends ContractBase {
@ -13,7 +13,7 @@ export default class OceanMarket extends ContractBase {
// call functions (costs no gas)
public async isAssetActive(assetId: string): Promise<boolean> {
return this.call("checkAsset", [assetId])
return this.call("checkAsset", ["0x" + assetId])
}
public async verifyOrderPayment(orderId: string): Promise<boolean> {
@ -21,12 +21,12 @@ export default class OceanMarket extends ContractBase {
}
public async getAssetPrice(assetId: string): Promise<number> {
return this.call("getAssetPrice", [assetId])
return this.call("getAssetPrice", ["0x" + assetId])
.then((price: string) => new BigNumber(price).toNumber())
}
public async requestTokens(amount: number, receiverAddress: string): Promise<Receipt> {
return this.sendTransaction("requestTokens", receiverAddress, [amount])
return this.send("requestTokens", receiverAddress, [amount])
}
public async generateId(input: string): Promise<string> {
@ -34,13 +34,13 @@ export default class OceanMarket extends ContractBase {
}
public async register(assetId: string, price: number, publisherAddress: string): Promise<Receipt> {
return this.sendTransaction("register", publisherAddress, [assetId, price])
return this.send("register", publisherAddress, ["0x" + assetId, price])
}
public async payOrder(order: Order, publisherAddress: string,
price: number, consumerAddress: string,
timeout: number): Promise<Receipt> {
return this.sendTransaction("sendPayment", consumerAddress, [
return this.send("sendPayment", consumerAddress, [
order.getId(), publisherAddress, price, timeout,
])
}

View File

@ -0,0 +1,41 @@
import {Receipt} from "web3-utils"
import MethodReflection from "../../models/MethodReflection"
import ContractBase from "./ContractBase"
export default class ServiceAgreement extends ContractBase {
public static async getInstance(): Promise<ServiceAgreement> {
const serviceAgreement: ServiceAgreement = new ServiceAgreement("ServiceAgreement")
await serviceAgreement.init()
return serviceAgreement
}
public async setupAgreementTemplate(methodReflections: MethodReflection[], dependencyMatrix: number[], name: any,
ownerAddress: string): Promise<Receipt> {
return this.send("setupAgreementTemplate", ownerAddress, [
methodReflections.map((r) => r.address), methodReflections.map((r) => r.signature),
dependencyMatrix, name,
])
}
public async getTemplateStatus(templateId: string) {
return this.call("getTemplateStatus", [templateId])
}
public async getAgreementStatus(serviceAgreementId: string) {
return this.call("getAgreementStatus", ["0x" + serviceAgreementId])
}
public async executeAgreement(serviceAgreementTemplateId: string, serviceAgreementSignatureHash: string,
consumerAddress: string, valueHashes: string[], timeoutValues: number[],
serviceAgreementId: string, did: string, publisherAddress: string): Promise<Receipt> {
return this.send("executeAgreement", publisherAddress, [
serviceAgreementTemplateId, serviceAgreementSignatureHash, consumerAddress, valueHashes,
timeoutValues, "0x" + serviceAgreementId, "0x" + did,
])
}
}

View File

@ -11,7 +11,7 @@ export default class OceanToken extends ContractBase {
}
public async approve(marketAddress: string, price: number, buyerAddress: string): Promise<Receipt> {
return this.sendTransaction("approve", buyerAddress, [marketAddress, price])
return this.send("approve", buyerAddress, [marketAddress, price])
}
public async balanceOf(address: string): Promise<number> {

View File

@ -0,0 +1,18 @@
import {Receipt} from "web3-utils"
import ContractBase from "../ContractBase"
export default class AccessConditions extends ContractBase {
public static async getInstance(): Promise<AccessConditions> {
const accessConditions: AccessConditions = new AccessConditions("AccessConditions")
await accessConditions.init()
return accessConditions
}
public async grantAccess(serviceAgreementId: any, assetId: any, documentKeyId: any, publisherAddress: string)
: Promise<Receipt> {
return this.send("grantAccess", publisherAddress, [
"0x" + serviceAgreementId, "0x" + assetId, "0x" + documentKeyId,
])
}
}

View File

@ -0,0 +1,10 @@
import ContractBase from "../ContractBase"
export default class PaymentConditions extends ContractBase {
public static async getInstance(): Promise<PaymentConditions> {
const paymentConditions: PaymentConditions = new PaymentConditions("PaymentConditions")
await paymentConditions.init()
return paymentConditions
}
}

View File

@ -1,5 +1,23 @@
export default class Config {
/* Aquarius Config */
// the url to the aquarius
public aquariusUri: string
/* Keeper Config */
// the uri to the node we want to connect to, not need if web3Provider is set
public nodeUri: string
// from outside eg. metamask
public web3Provider: any
/* Secret Store Config */
// the uri of the secret store to connect to
public secretStoreUri: string
// the uri of the parity node to connect to
public parityUri: string
// the password of the account in the local parity node to sign the serverKeyId
public password: string
// the address of the account in the local parity node to sign the serverKeyId
public address: string
// the number of nodes in the secret store that have to agree on changes
public threshold: number
}

View File

@ -0,0 +1,6 @@
export default class MethodReflection {
public contractName: string
public methodName: string
public address: string
public signature: string
}

8
src/models/ValueType.ts Normal file
View File

@ -0,0 +1,8 @@
enum ValueType {
DID, // DID string e.g. 'did:op:xxx'
DIDRef, // hash of DID same as in parameter (bytes32 _did) in text 0x0123abc.. or 0123abc..
URL, // URL string e.g. 'http(s)://xx'
DDO, // DDO string in JSON e.g. '{ "id": "did:op:xxx"...
}
export default ValueType

8
src/ocean/IdGenerator.ts Normal file
View File

@ -0,0 +1,8 @@
import * as v4 from "uuid/v4"
export default class IdGenerator {
public static generateId(): string {
const id = `${v4()}${v4()}`
return id.replace(/-/g, "")
}
}

View File

@ -2,14 +2,17 @@ import AquariusProvider from "../aquarius/AquariusProvider"
import ConfigProvider from "../ConfigProvider"
import Keeper from "../keeper/Keeper"
import Web3Provider from "../keeper/Web3Provider"
import Config from "../models/Config"
import SecretStoreProvider from "../secretstore/SecretStoreProvider"
import Logger from "../utils/Logger"
import Account from "./Account"
import Asset from "./Asset"
import IdGenerator from "./IdGenerator"
import Order from "./Order"
export default class Ocean {
public static async getInstance(config) {
public static async getInstance(config: Config) {
if (!Ocean.instance) {
ConfigProvider.setConfig(config)
@ -37,8 +40,17 @@ export default class Ocean {
public async register(asset: Asset): Promise<string> {
const {market} = this.keeper
const secretStore = SecretStoreProvider.getSecretStore()
const assetId = IdGenerator.generateId()
const encryptedDocument = await secretStore.encryptDocument(assetId, asset)
const decryptedDocument = await secretStore.decryptDocument(assetId, encryptedDocument)
Logger.log(decryptedDocument, encryptedDocument)
// generate an id
const assetId = await market.generateId(asset.name + asset.description)
Logger.log(`Registering: ${assetId} with price ${asset.price} for ${asset.publisher.getId()}`)
asset.setId(assetId)
const isAssetActive = await market.isAssetActive(assetId)

View File

@ -0,0 +1,117 @@
import AccessConditions from "../keeper/contracts/conditions/AccessConditions"
import ServiceAgreementContract from "../keeper/contracts/ServiceAgreement"
import Web3Provider from "../keeper/Web3Provider"
import Account from "./Account"
import IdGenerator from "./IdGenerator"
import OceanBase from "./OceanBase"
import ServiceAgreementTemplate from "./ServiceAgreementTemplate"
export default class ServiceAgreement extends OceanBase {
public static async createServiceAgreement(serviceAgreementTemplate: ServiceAgreementTemplate, assetId: string,
did: string, consumer: Account, publisher: Account) {
// todo: this should come from ddo
const serviceAgreementId = IdGenerator.generateId()
const timeoutValues = [0, 0, 0, 500] // timeout 500 blocks @ condition 4
const values = [
{type: "bool", value: true},
{type: "bool", value: false},
{type: "uint", value: 120},
{type: "string", value: assetId},
]
const saHashSig = await ServiceAgreement.createSAHashSignature(serviceAgreementTemplate, serviceAgreementId,
values, timeoutValues, consumer)
const serviceAgreement: ServiceAgreement = await ServiceAgreement.signServiceAgreement(serviceAgreementTemplate,
serviceAgreementId, assetId, did, values, timeoutValues, saHashSig, consumer, publisher)
return serviceAgreement
}
private static async signServiceAgreement(serviceAgreementTemplate: ServiceAgreementTemplate,
serviceAgreementId: string, assetId: string, did: string, values: any[],
timeoutValues: number[], serviceAgreementHashSignature: string,
consumer: Account, publisher: Account):
Promise<ServiceAgreement> {
const valueHashes = ServiceAgreement.createValueHashes(values)
const serviceAgreement: ServiceAgreementContract = await ServiceAgreementContract.getInstance()
const executeAgreementReceipt = await serviceAgreement.executeAgreement(
serviceAgreementTemplate.getId(), serviceAgreementHashSignature, consumer.getId(), valueHashes,
timeoutValues, serviceAgreementId, did, publisher.getId())
if (executeAgreementReceipt.events.ExecuteAgreement.returnValues.state === false) {
throw new Error("signing service agreement failed.")
}
return new ServiceAgreement(
serviceAgreementId,
publisher,
serviceAgreementTemplate,
consumer,
executeAgreementReceipt.events.ExecuteAgreement.returnValues.state,
executeAgreementReceipt.events.ExecuteAgreement.returnValues.status,
)
}
private static createValueHashes(values: any[]): any[] {
return values.map((value) => {
return ServiceAgreement.hashSingleValue(value.type, value.value)
})
}
private static hashSingleValue(type: string, value: any): string {
const args = {type, value}
return Web3Provider.getWeb3().utils.soliditySha3(args).toString("hex")
}
private static async createSAHashSignature(serviceAgreementTemplate: ServiceAgreementTemplate,
serviceAgreementId: string, values: any[], timeoutValues: number[],
consumer: Account): Promise<string> {
const valueHashes = ServiceAgreement.createValueHashes(values)
const serviceAgreementHash = ServiceAgreement.hashServiceAgreement(serviceAgreementTemplate, valueHashes,
timeoutValues, serviceAgreementId)
const serviceAgreementHashSignature =
await Web3Provider.getWeb3().eth.sign(serviceAgreementHash, consumer.getId())
return serviceAgreementHashSignature
}
private static hashServiceAgreement(serviceAgreementTemplate: ServiceAgreementTemplate, valueHashes: string[],
timeouts: number[], serviceAgreementId: string) {
const args = [
{type: "bytes32", value: serviceAgreementTemplate.getId()},
{type: "bytes32[]", value: serviceAgreementTemplate.getConditionKeys()},
{type: "bytes32[]", value: valueHashes},
{type: "uint256[]", value: timeouts},
{type: "bytes32", value: "0x" + serviceAgreementId},
]
return Web3Provider.getWeb3().utils.soliditySha3(...args).toString("hex")
}
private constructor(id: string, private publisher: Account, serviceAgreementTemplate: ServiceAgreementTemplate,
consumer: Account, state: boolean, status: boolean) {
super(id)
}
public async grantAccess(assetId: string, documentId: string): Promise<boolean> {
const accessConditions: AccessConditions = await AccessConditions.getInstance()
const grantAccessReceipt =
await accessConditions.grantAccess(this.getId(), assetId, documentId, this.publisher.getId())
return grantAccessReceipt.status
}
public async getStatus() {
const serviceAgreement = await ServiceAgreementContract.getInstance()
return serviceAgreement.getAgreementStatus(this.getId())
}
}

View File

@ -0,0 +1,71 @@
import ContractReflector from "../keeper/ContractReflector"
import ServiceAgreement from "../keeper/contracts/ServiceAgreement"
import Web3Provider from "../keeper/Web3Provider"
import MethodReflection from "../models/MethodReflection"
import Account from "./Account"
import OceanBase from "./OceanBase"
export default class ServiceAgreementTemplate extends OceanBase {
public static async registerServiceAgreementsTemplate(serviceName: string, methods: string[],
dependencyMatrix: number[], templateOwner: Account):
Promise<ServiceAgreementTemplate> {
const methodReflections: MethodReflection[] =
await Promise.all(methods.map(async (method) => {
const methodReflection = await
ContractReflector.reflectContractMethod(method)
return methodReflection
}))
const serviceAgreement: ServiceAgreement = await ServiceAgreement.getInstance()
const receipt = await serviceAgreement.setupAgreementTemplate(
methodReflections, dependencyMatrix,
Web3Provider.getWeb3().utils.fromAscii(serviceName),
templateOwner.getId())
const id = receipt.events.SetupAgreementTemplate.returnValues.serviceTemplateId
return new ServiceAgreementTemplate(
id,
ServiceAgreementTemplate.generateConditionsKeys(id, methodReflections),
templateOwner)
}
private static generateConditionsKeys(serviceAgreementTemplateId: string, methodReflections: MethodReflection[]):
string[] {
const conditions = []
for (const methodReflection of methodReflections) {
const values = [
{type: "bytes32", value: serviceAgreementTemplateId},
{type: "address", value: methodReflection.address},
{type: "bytes4", value: methodReflection.signature},
]
conditions.push(Web3Provider.getWeb3().utils.soliditySha3(...values).toString("hex"))
}
return conditions
}
private constructor(id, private conditionKeys: string[], private owner: Account) {
super(id)
}
/**
* gets the status of a service agreement template
*/
public async getStatus(): Promise<boolean> {
const serviceAgreement: ServiceAgreement = await ServiceAgreement.getInstance()
return serviceAgreement.getTemplateStatus(this.getId())
}
public getOwner(): Account {
return this.owner
}
public getConditionKeys(): string[] {
return this.conditionKeys
}
}

View File

@ -0,0 +1,21 @@
import SecretStore from "@oceanprotocol/secret-store-client"
import ConfigProvider from "../ConfigProvider"
export default class SecretStoreProvider {
public static setSecretStore(secretStore: SecretStore) {
SecretStoreProvider.secretStore = secretStore
}
public static getSecretStore() {
if (!SecretStoreProvider.secretStore) {
SecretStoreProvider.secretStore = new SecretStore(ConfigProvider.getConfig())
}
return SecretStoreProvider.secretStore
}
private static secretStore: SecretStore
}

View File

@ -1,21 +1,20 @@
import * as assert from "assert"
import Aquarius from "../../src/aquarius/Aquarius"
import AquariusConnectorProvider from "../../src/aquarius/AquariusConnectorProvider"
import SearchQuery from "../../src/aquarius/query/SearchQuery"
import DDO from "../../src/ddo/DDO"
import IdGenerator from "../../src/ocean/IdGenerator"
import config from "../config"
import AquariusConnectorMock from "../mocks/AquariusConnector.mock"
before(() => {
AquariusConnectorProvider.setConnector(new AquariusConnectorMock())
})
// import * as jsonDDO from "../testdata/ddo.json"
describe("Aquarius", () => {
const aquarius: Aquarius = new Aquarius(config)
describe("#queryMetadata()", () => {
it("should query metadata", async () => {
const aquarius: Aquarius = new Aquarius(config)
const query = {
offset: 100,
page: 0,
@ -26,11 +25,84 @@ describe("Aquarius", () => {
value: 1,
},
text: "Office",
}
} as SearchQuery
// @ts-ignore
AquariusConnectorProvider.setConnector(new AquariusConnectorMock())
const result: any[] = await aquarius.queryMetadata(query)
assert(result)
assert(result.length !== null)
})
})
describe("#queryMetadataByText()", () => {
it("should query metadata by text", async () => {
const query = {
offset: 100,
page: 0,
query: {
value: 1,
},
sort: {
value: 1,
},
text: "Office",
} as SearchQuery
// @ts-ignore
AquariusConnectorProvider.setConnector(new AquariusConnectorMock())
const result: any[] = await aquarius.queryMetadataByText(query)
assert(result)
assert(result.length !== null)
})
})
describe("#storeDDO()", () => {
it("should store a ddo", async () => {
const did: string = `did:op:${IdGenerator.generateId()}`
const ddo: DDO = new DDO({
id: did,
})
// @ts-ignore
AquariusConnectorProvider.setConnector(new AquariusConnectorMock(ddo))
const result: DDO = await aquarius.storeDDO(ddo)
assert(result)
assert(result.id === ddo.id)
})
})
describe("#retrieveDDO()", () => {
it("should store a ddo", async () => {
const did: string = `did:op:${IdGenerator.generateId()}`
const ddo: DDO = new DDO({
id: did,
})
// @ts-ignore
AquariusConnectorProvider.setConnector(new AquariusConnectorMock(ddo))
const storageResult: DDO = await aquarius.storeDDO(ddo)
assert(storageResult)
assert(storageResult.id === did)
const restrieveResult: DDO = await aquarius.retrieveDDO(did)
assert(restrieveResult)
assert(restrieveResult.id === did)
assert(restrieveResult.id === storageResult.id)
})
})
})

View File

@ -3,5 +3,10 @@ import Config from "../src/models/Config"
export default {
aquariusUri: "http://localhost:5000",
nodeUri: "http://localhost:8545",
parityUri: "http://localhost:9545",
secretStoreUri: "https://secret-store.dev-ocean.com",
threshold: 2,
password: "unittest",
address: "0xed243adfb84a6626eba46178ccb567481c6e655d",
web3Provider: null,
} as Config

213
test/ddo/DDO.test.ts Normal file
View File

@ -0,0 +1,213 @@
import {assert} from "chai"
import AdditionalInformation from "../../src/ddo/AdditionalInformation"
import Authentication from "../../src/ddo/Authentication"
import Curation from "../../src/ddo/Curation"
import DDO from "../../src/ddo/DDO"
import MetaData from "../../src/ddo/MetaData"
import MetaDataBase from "../../src/ddo/MetaDataBase"
import PublicKey from "../../src/ddo/PublicKey"
import Service from "../../src/ddo/Service"
import StructuredMarkup from "../../src/ddo/StructuredMarkup"
import * as jsonDDO from "../testdata/ddo.json"
describe("DDO", () => {
const testDDO: DDO = new DDO({
publicKey: [
{
id: "did:op:123456789abcdefghi#keys-1",
type: "RsaVerificationKey2018",
owner: "did:op:123456789abcdefghi",
publicKeyPem: "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n",
} as PublicKey,
{
id: "did:op:123456789abcdefghi#keys-2",
type: "Ed25519VerificationKey2018",
owner: "did:op:123456789abcdefghi",
publicKeyBase58: "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV",
} as PublicKey,
{
id: "did:op:123456789abcdefghi#keys-3",
type: "RsaPublicKeyExchangeKey2018",
owner: "did:op:123456789abcdefghi",
publicKeyPem: "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n",
} as PublicKey,
],
authentication: [
{
type: "RsaSignatureAuthentication2018",
publicKey: "did:op:123456789abcdefghi#keys-1",
} as Authentication,
{
type: "ieee2410Authentication2018",
publicKey: "did:op:123456789abcdefghi#keys-2",
} as Authentication,
],
service: [
{
type: "OpenIdConnectVersion1.0Service",
serviceEndpoint: "https://openid.example.com/",
} as Service,
{
type: "CredentialRepositoryService",
serviceEndpoint: "https://repository.example.com/service/8377464",
} as Service,
{
type: "XdiService",
serviceEndpoint: "https://xdi.example.com/8377464",
} as Service,
{
type: "HubService",
serviceEndpoint: "https://hub.example.com/.identity/did:op:0123456789abcdef/",
} as Service,
{
type: "MessagingService",
serviceEndpoint: "https://example.com/messages/8377464",
} as Service,
{
type: "SocialWebInboxService",
serviceEndpoint: "https://social.example.com/83hfh37dj",
description: "My public social inbox",
spamCost: {
amount: "0.50",
currency: "USD",
},
} as Service,
{
id: "did:op:123456789abcdefghi;bops",
type: "BopsService",
serviceEndpoint: "https://bops.example.com/enterprise/",
} as Service,
{
type: "Consume",
// tslint:disable
serviceEndpoint: "http://mybrizo.org/api/v1/brizo/services/consume?pubKey=${pubKey}&serviceId={serviceId}&url={url}",
} as Service,
{
type: "Compute",
serviceEndpoint: "http://mybrizo.org/api/v1/brizo/services/compute?pubKey=${pubKey}&serviceId={serviceId}&algo={algo}&container={container}",
} as Service,
{
type: "Metadata",
serviceEndpoint: "http://myaquarius.org/api/v1/provider/assets/metadata/{did}",
metadata: {
base: {
name: "UK Weather information 2011",
type: "dataset",
description: "Weather information of UK including temperature and humidity",
size: "3.1gb",
dateCreated: "2012-10-10T17:00:000Z",
author: "Met Office",
license: "CC-BY",
copyrightHolder: "Met Office",
encoding: "UTF-8",
compression: "zip",
contentType: "text/csv",
workExample: "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68",
contentUrls: [
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip"
],
links: [
{
sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"
},
{
sample2: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/"
},
{
fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/"
}
],
inLanguage: "en",
tags: "weather, uk, 2011, temperature, humidity",
price: 10
} as MetaDataBase,
curation: {
"rating": 0.93,
"numVotes": 123,
"schema": "Binary Votting"
} as Curation,
additionalInformation: {
updateFrecuency: "yearly",
structuredMarkup: [
{
"uri": "http://skos.um.es/unescothes/C01194/jsonld",
"mediaType": "application/ld+json"
} as StructuredMarkup,
{
"uri": "http://skos.um.es/unescothes/C01194/turtle",
"mediaType": "text/turtle"
} as StructuredMarkup
]
} as AdditionalInformation
} as MetaData
}
]
})
describe("#serialize()", () => {
it("should properly serialize", async () => {
const ddoString = DDO.serialize(testDDO)
assert(ddoString)
assert(ddoString.startsWith("{"))
})
})
describe("#constructor()", () => {
it("should create an empty ddo", async () => {
const ddo = new DDO()
assert(ddo)
assert(ddo.service.length === 0)
assert(ddo.authentication.length === 0)
assert(ddo.publicKey.length === 0)
})
it("should create an predefined ddo", async () => {
const service: Service = {
serviceEndpoint: "http://",
description: "nice service"
} as Service
const ddo = new DDO({
service: [service]
})
assert(ddo)
assert(ddo.service.length === 1)
assert(ddo.service[0].description === service.description)
assert(ddo.authentication.length === 0)
assert(ddo.publicKey.length === 0)
})
})
describe("#deserialize()", () => {
it("should properly deserialize from serialized object", async () => {
const ddoString = DDO.serialize(testDDO)
assert(ddoString)
const ddo: DDO = DDO.deserialize(ddoString)
assert(ddo)
assert(ddo.id == testDDO.id)
assert(ddo.publicKey[0].publicKeyPem == testDDO.publicKey[0].publicKeyPem)
})
it("should properly deserialize from json file", async () => {
const ddo: DDO = DDO.deserialize(JSON.stringify(jsonDDO))
assert(ddo)
assert(ddo.id == jsonDDO.id)
assert(ddo.publicKey[0].publicKeyPem == jsonDDO.publicKey[0].publicKeyPem)
})
})
})

View File

@ -1,16 +1,22 @@
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import ContractHandler from "../../src/keeper/ContractHandler"
import Account from "../../src/ocean/Account"
import Ocean from "../../src/ocean/Ocean"
import config from "../config"
import ContractBaseMock from "../mocks/ContractBase.Mock"
const wrappedContract = new ContractBaseMock("OceanToken")
let accounts: Account[]
describe("ContractWrapperBase", () => {
before(async () => {
ConfigProvider.setConfig(config)
await ContractHandler.deployContracts()
wrappedContract.initMock()
await wrappedContract.initMock()
const ocean: Ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts()
})
describe("#call()", () => {
@ -52,6 +58,29 @@ describe("ContractWrapperBase", () => {
})
})
describe("#send()", () => {
it("should fail to call on an unknown contract function", (done) => {
wrappedContract.sendMock("transferxxx", accounts[0].getId(), [])
.catch(() => {
done()
})
})
})
describe("#getSignatureOfMethod()", () => {
it("should a signature of the function", async () => {
const sig = wrappedContract.getSignatureOfMethod("name")
assert(sig)
assert(typeof sig === "string")
assert(sig.startsWith("0x"))
})
})
describe("#getEventData()", () => {
it("should fail on unknown event", (done) => {

View File

@ -0,0 +1,101 @@
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import ContractHandler from "../../src/keeper/ContractHandler"
import DIDRegistry from "../../src/keeper/contracts/DIDRegistry"
import Web3Provider from "../../src/keeper/Web3Provider"
import ValueType from "../../src/models/ValueType"
import Account from "../../src/ocean/Account"
import IdGenerator from "../../src/ocean/IdGenerator"
import Ocean from "../../src/ocean/Ocean"
import Logger from "../../src/utils/Logger"
import config from "../config"
let ocean: Ocean
let didRegistry: DIDRegistry
describe("DIDRegistry", () => {
before(async () => {
ConfigProvider.setConfig(config)
await ContractHandler.deployContracts()
ocean = await Ocean.getInstance(config)
didRegistry = await DIDRegistry.getInstance()
})
describe("#registerAttribute()", () => {
it("should register an attribute in a new did", async () => {
const ownerAccount: Account = (await ocean.getAccounts())[0]
const did = IdGenerator.generateId()
const providerKey = Web3Provider.getWeb3().utils.fromAscii("provider")
const data = "my nice provider, is nice"
const receipt = await didRegistry.registerAttribute(did, ValueType.DID, providerKey,
data, ownerAccount.getId())
assert(receipt.status)
assert(receipt.events.DIDAttributeRegistered)
})
it("should register another attribute in the same did", async () => {
const ownerAccount: Account = (await ocean.getAccounts())[0]
const did = IdGenerator.generateId()
{
// register the first attribute
const providerKey = Web3Provider.getWeb3().utils.fromAscii("provider")
const data = "my nice provider, is nice"
await didRegistry.registerAttribute(did, ValueType.DID, providerKey,
data, ownerAccount.getId())
}
{
// register the second attribute with the same did
const providerKey = Web3Provider.getWeb3().utils.fromAscii("provider2")
const data = "asdsad"
const receipt = await didRegistry.registerAttribute(did, ValueType.DID, providerKey,
data, ownerAccount.getId())
assert(receipt.status)
assert(receipt.events.DIDAttributeRegistered)
}
})
})
describe("#getOwner()", () => {
it("should get the owner of a did properly", async () => {
const ownerAccount: Account = (await ocean.getAccounts())[0]
const did = IdGenerator.generateId()
const providerKey = Web3Provider.getWeb3().utils.fromAscii("provider")
const data = "my nice provider, is nice"
await didRegistry.registerAttribute(did, ValueType.DID, providerKey,
data, ownerAccount.getId())
const owner = await didRegistry.getOwner(did)
assert(owner === ownerAccount.getId(), `Got ${owner} but expected ${ownerAccount.getId()}`)
})
it("should get 0x00.. for a not registered did", async () => {
const owner = await didRegistry.getOwner("1234")
assert(owner === "0x0000000000000000000000000000000000000000")
})
})
describe("#getUpdateAt()", () => {
it("should the block number of the last update of the did attribute", async () => {
const ownerAccount: Account = (await ocean.getAccounts())[0]
const did = IdGenerator.generateId()
const providerKey = Web3Provider.getWeb3().utils.fromAscii("provider")
const data = "my nice provider, is nice"
await didRegistry.registerAttribute(did, ValueType.DID, providerKey,
data, ownerAccount.getId())
const updatedAt: number = await didRegistry.getUpdateAt(did)
assert(updatedAt > 0)
Logger.log(typeof updatedAt)
})
})
})

View File

@ -13,7 +13,7 @@ describe("Keeper", () => {
await ContractHandler.deployContracts()
keeper = await Keeper.getInstance()
})
describe("public interface", () => {
it("should have market", () => {

View File

@ -1,17 +1,25 @@
import AquariusConnector from "../../src/aquarius/AquariusConnector"
// @ts-ignore
export default class AquariusConnectorMock extends AquariusConnector {
public async post(url: string, payload: any) {
constructor(private returnData: any) {
super()
}
return {
ok: true,
json: () => {
return []
},
text: () => {
return ""
},
}
// @ts-ignore
private async fetch(url, opts): Promise<any> {
return new Promise((resolve, reject) => {
resolve({
ok: true,
json: () => {
return this.returnData ? this.returnData : []
},
text: () => {
return this.returnData ? this.returnData.toString() : ""
},
})
})
}
}

View File

@ -1,8 +1,8 @@
import ContractBase from "../../src/keeper/ContractBase"
import ContractBase from "../../src/keeper/contracts/ContractBase"
export default class ContractBaseMock extends ContractBase {
public async initMock() {
this.init()
await this.init()
}
public async callMock(name: string, args: any[], from?: string) {
@ -10,6 +10,6 @@ export default class ContractBaseMock extends ContractBase {
}
public async sendMock(name: string, from: string, args: any[]) {
return this.sendTransaction(name, from, args)
return this.send(name, from, args)
}
}

View File

@ -0,0 +1,16 @@
import SecretStore from "@oceanprotocol/secret-store-client"
export default class SecretStoreMock extends SecretStore {
public async encryptDocument(documentId, document: any) {
return "0x283asdgahd1t371t23h"
}
public async decryptDocument(documentId, encryptedDocument: any) {
return {
doc: "test",
}
}
}

View File

@ -6,8 +6,10 @@ import Account from "../../src/ocean/Account"
import Asset from "../../src/ocean/Asset"
import Ocean from "../../src/ocean/Ocean"
import Order from "../../src/ocean/Order"
import SecretStoreProvider from "../../src/secretstore/SecretStoreProvider"
import config from "../config"
import AquariusMock from "../mocks/Aquarius.mock"
import SecretStoreMock from "../mocks/SecretStore.mock"
const testName = "Test Asset 2"
const testDescription = "This asset is pure owange"
@ -24,7 +26,7 @@ describe("Asset", () => {
before(async () => {
ConfigProvider.setConfig(config)
AquariusProvider.setAquarius(new AquariusMock(config))
SecretStoreProvider.setSecretStore(new SecretStoreMock(config))
await ContractHandler.deployContracts()
ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts()

View File

@ -0,0 +1,26 @@
import * as assert from "assert"
import IdGenerator from "../../src/ocean/IdGenerator"
describe("IdGenerator", () => {
describe("#generateId()", () => {
it("should generate an id", async () => {
const id = IdGenerator.generateId()
assert(id)
})
it("should generate an id that is 64 chars long", async () => {
const id: string = IdGenerator.generateId()
assert(id.length === 64, id)
})
it("should not contain -", async () => {
const id: string = IdGenerator.generateId()
assert(id.indexOf("-") === -1)
})
})
})

View File

@ -6,8 +6,10 @@ import Account from "../../src/ocean/Account"
import Asset from "../../src/ocean/Asset"
import Ocean from "../../src/ocean/Ocean"
import Order from "../../src/ocean/Order"
import SecretStoreProvider from "../../src/secretstore/SecretStoreProvider"
import config from "../config"
import AquariusMock from "../mocks/Aquarius.mock"
import SecretStoreMock from "../mocks/SecretStore.mock"
let ocean: Ocean
let accounts: Account[]
@ -24,6 +26,7 @@ describe("Ocean", () => {
before(async () => {
ConfigProvider.setConfig(config)
AquariusProvider.setAquarius(new AquariusMock(config))
SecretStoreProvider.setSecretStore(new SecretStoreMock(config))
await ContractHandler.deployContracts()
ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts()
@ -62,10 +65,9 @@ describe("Ocean", () => {
const assetId: string = await ocean.register(testAsset)
assert(assetId.length === 66)
assert(assetId.startsWith("0x"))
assert(assetId.length === 64)
assert(!assetId.startsWith("0x"))
})
})
describe("#getOrdersByConsumer()", () => {
@ -82,7 +84,6 @@ describe("Ocean", () => {
assert(orders.length === 1)
assert(orders[0].getId() === order.getId())
})
})

View File

@ -9,12 +9,12 @@ import Ocean from "../../src/ocean/Ocean"
import Order from "../../src/ocean/Order"
import config from "../config"
import AquariusMock from "../mocks/Aquarius.mock"
import * as AccessToken from "../testdata/AccessToken.json"
const testName = "Order Test Asset"
const testDescription = "This asset is pure owange"
const testPrice = 100
const timeout = 1000000
const accessToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE1Mzk3ODcxMDEsImV4cCI6NDcyNjk5NjcwNCwiYXVkIjoiIiwic3ViIjoiIiwic2VydmljZV9lbmRwb2ludCI6Imh0dHA6Ly9hZGFzZCIsInJlc291cmNlX2lkIjoiMTIzNDUifQ.2H3TRC3CAToVE9divSckwHi_HNvgOHKrtJPo8128qrKBHTk7YYb0UNfVCuYqwhGR"
let ocean: Ocean
let testAsset: Asset
@ -44,7 +44,7 @@ describe("Order", () => {
const order: Order = await testAsset.purchase(testConsumer, timeout)
assert(order)
await order.commit(accessToken)
await order.commit(AccessToken.toString())
await testConsumer.requestTokens(testAsset.price)
const paymentId: string = await order.pay(testConsumer)
assert(paymentId)
@ -59,7 +59,7 @@ describe("Order", () => {
const order: Order = await testAsset.purchase(testConsumer, timeout)
assert(order)
await order.commit(accessToken)
await order.commit(AccessToken.toString())
})
})
@ -79,7 +79,7 @@ describe("Order", () => {
const order: Order = await testAsset.purchase(testConsumer, timeout)
assert(order)
await order.commit(accessToken)
await order.commit(AccessToken.toString())
const status: AccessStatus = await order.getStatus()
assert(status === AccessStatus.Delivered)
@ -94,7 +94,7 @@ describe("Order", () => {
// place order - consumer
const order: Order = await testAsset.purchase(consumerAccount, timeout)
// commit order - provider
await order.commit(accessToken)
await order.commit(AccessToken.toString())
// pay order - consumer
await order.pay(consumerAccount)
const url = await order.consume(consumerAccount)

View File

@ -0,0 +1,94 @@
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import ContractHandler from "../../src/keeper/ContractHandler"
import Account from "../../src/ocean/Account"
import IdGenerator from "../../src/ocean/IdGenerator"
import Ocean from "../../src/ocean/Ocean"
import ServiceAgreement from "../../src/ocean/ServiceAgreement"
import ServiceAgreementTemplate from "../../src/ocean/ServiceAgreementTemplate"
import config from "../config"
let ocean: Ocean
let accounts: Account[]
let publisherAccount: Account
let templateOwnerAccount: Account
let consumerAccount: Account
let testServiceAgreementTemplate: ServiceAgreementTemplate
describe("ServiceAgreement", () => {
before(async () => {
ConfigProvider.setConfig(config)
await ContractHandler.deployContracts()
ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts()
templateOwnerAccount = accounts[0]
publisherAccount = accounts[1]
consumerAccount = accounts[2]
const resourceName = "superb car data"
const methods: string[] = [
"PaymentConditions.lockPayment",
"AccessConditions.grantAccess",
"PaymentConditions.releasePayment",
"PaymentConditions.refundPayment",
]
// tslint:disable
const dependencyMatrix = [0, 1, 4, 1 | 2 ** 4 | 2 ** 5] // dependency bit | timeout bit
testServiceAgreementTemplate =
await ServiceAgreementTemplate.registerServiceAgreementsTemplate(resourceName, methods,
dependencyMatrix, templateOwnerAccount)
})
describe("#createServiceAgreement()", () => {
it("should execute an service agreement", async () => {
const did: string = IdGenerator.generateId()
const assetId: string = IdGenerator.generateId()
const serviceAgreement: ServiceAgreement =
await ServiceAgreement.createServiceAgreement(testServiceAgreementTemplate, assetId, did,
consumerAccount, publisherAccount)
assert(serviceAgreement)
const id = serviceAgreement.getId()
assert(id)
assert(id !== did)
})
})
describe("#getStatus()", () => {
it("should get the status of a newly created service agreement", async () => {
const did: string = IdGenerator.generateId()
const assetId: string = IdGenerator.generateId()
const serviceAgreement: ServiceAgreement =
await ServiceAgreement.createServiceAgreement(testServiceAgreementTemplate, assetId, did,
consumerAccount, publisherAccount)
assert(serviceAgreement)
const status = await serviceAgreement.getStatus()
assert(status === false)
})
})
describe("#grantAccess()", () => {
it("should grant access in that service agreement", async () => {
const did: string = IdGenerator.generateId()
const assetId: string = IdGenerator.generateId()
const serviceAgreement: ServiceAgreement =
await ServiceAgreement.createServiceAgreement(testServiceAgreementTemplate, assetId, did,
consumerAccount, publisherAccount)
assert(serviceAgreement)
const fulfilled: boolean = await serviceAgreement.grantAccess(did, IdGenerator.generateId())
assert(fulfilled)
})
})
})

View File

@ -0,0 +1,60 @@
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import ContractHandler from "../../src/keeper/ContractHandler"
import Account from "../../src/ocean/Account"
import Ocean from "../../src/ocean/Ocean"
import ServiceAgreementTemplate from "../../src/ocean/ServiceAgreementTemplate"
import config from "../config"
let ocean: Ocean
let accounts: Account[]
const methods: string[] = [
"PaymentConditions.lockPayment",
"AccessConditions.grantAccess",
"PaymentConditions.releasePayment",
"PaymentConditions.refundPayment",
]
// tslint:disable
const dependencyMatrix = [0, 1, 4, 1 | 2 ** 4 | 2 ** 5] // dependency bit | timeout bit
describe("ServiceAgreementTemplate", () => {
before(async () => {
ConfigProvider.setConfig(config)
await ContractHandler.deployContracts()
ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts()
})
describe("#registerServiceAgreementsTemplate()", () => {
it("should setup an agreement template", async () => {
const templateOwner = accounts[0]
const resourceName = "consume"
const serviceAgreementTemplate: ServiceAgreementTemplate =
await ServiceAgreementTemplate.registerServiceAgreementsTemplate(resourceName, methods,
dependencyMatrix, templateOwner)
assert(serviceAgreementTemplate)
assert(serviceAgreementTemplate.getId())
assert(serviceAgreementTemplate.getOwner().getId() === templateOwner.getId())
})
})
describe("#getStatus()", () => {
it("should get the status of a newly deployed agreement template", async () => {
const publisherAccount = accounts[0]
const resourceName = "consume"
const serviceAgreementTemplate: ServiceAgreementTemplate =
await ServiceAgreementTemplate.registerServiceAgreementsTemplate(resourceName, methods,
dependencyMatrix, publisherAccount)
assert(serviceAgreementTemplate)
const templateStatus = await serviceAgreementTemplate.getStatus()
assert(templateStatus === true)
})
})
})

1
test/testdata/AccessToken.json vendored Normal file
View File

@ -0,0 +1 @@
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE1Mzk3ODcxMDEsImV4cCI6NDcyNjk5NjcwNCwiYXVkIjoiIiwic3ViIjoiIiwic2VydmljZV9lbmRwb2ludCI6Imh0dHA6Ly9hZGFzZCIsInJlc291cmNlX2lkIjoiMTIzNDUifQ.2H3TRC3CAToVE9divSckwHi_HNvgOHKrtJPo8128qrKBHTk7YYb0UNfVCuYqwhGR"

133
test/testdata/ddo.json vendored Normal file
View File

@ -0,0 +1,133 @@
{
"@context": "https://w3id.org/future-method/v1",
"id": "did:op:123456789abcdefghi",
"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"
}
],
"service": [
{
"type": "OpenIdConnectVersion1.0Service",
"serviceEndpoint": "https://openid.example.com/"
},
{
"type": "CredentialRepositoryService",
"serviceEndpoint": "https://repository.example.com/service/8377464"
},
{
"type": "XdiService",
"serviceEndpoint": "https://xdi.example.com/8377464"
},
{
"type": "HubService",
"serviceEndpoint": "https://hub.example.com/.identity/did:op:0123456789abcdef/"
},
{
"type": "MessagingService",
"serviceEndpoint": "https://example.com/messages/8377464"
},
{
"type": "SocialWebInboxService",
"serviceEndpoint": "https://social.example.com/83hfh37dj",
"description": "My public social inbox",
"spamCost": {
"amount": "0.50",
"currency": "USD"
}
},
{
"id": "did:op:123456789abcdefghi;bops",
"type": "BopsService",
"serviceEndpoint": "https://bops.example.com/enterprise/"
},
{
"type": "Consume",
"serviceEndpoint": "http://mybrizo.org/api/v1/brizo/services/consume?pubKey=${pubKey}&serviceId={serviceId}&url={url}"
},
{
"type": "Compute",
"serviceEndpoint": "http://mybrizo.org/api/v1/brizo/services/compute?pubKey=${pubKey}&serviceId={serviceId}&algo={algo}&container={container}"
},
{
"type": "Metadata",
"serviceEndpoint": "http://myaquarius.org/api/v1/provider/assets/metadata/{did}",
"metadata": {
"base": {
"name": "UK Weather information 2011",
"type": "dataset",
"description": "Weather information of UK including temperature and humidity",
"size": "3.1gb",
"dateCreated": "2012-10-10T17:00:000Z",
"author": "Met Office",
"license": "CC-BY",
"copyrightHolder": "Met Office",
"encoding": "UTF-8",
"compression": "zip",
"contentType": "text/csv",
"workExample": "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68",
"contentUrls": [
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip"
],
"links": [
{
"sample1": "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"
},
{
"sample2": "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/"
},
{
"fieldsDescription": "http://data.ceda.ac.uk/badc/ukcp09/"
}
],
"inLanguage": "en",
"tags": "weather, uk, 2011, temperature, humidity",
"price": 10
},
"curation": {
"rating": 0.93,
"numVotes": 123,
"schema": "Binary Votting"
},
"additionalInformation": {
"updateFrecuency": "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"
}
]
}
}
}
]
}

View File

@ -1,5 +1,6 @@
{
"compilerOptions": {
"resolveJsonModule": true,
"lib": [
"es6",
"es7"