format all the things

This commit is contained in:
Matthias Kretschmann 2019-06-20 00:20:09 +02:00 committed by Pedro Gutiérrez
parent 537b5a63ad
commit b61822e30c
117 changed files with 3246 additions and 2254 deletions

View File

@ -1,6 +1,6 @@
language: node_js language: node_js
node_js: node_js:
- "10" - '10'
services: services:
- docker - docker
@ -42,9 +42,8 @@ notifications:
deploy: deploy:
- provider: npm - provider: npm
email: "devops@oceanprotocol.com" email: 'devops@oceanprotocol.com'
api_key: ${NPM_TOKEN} api_key: ${NPM_TOKEN}
skip_cleanup: true skip_cleanup: true
on: on:
tags: true tags: true

View File

@ -138,6 +138,8 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
> 8 April 2019 > 8 April 2019
* First release
- Bump version 0.5.1 -> 0.5.2 [`#183`](https://github.com/oceanprotocol/squid-js/pull/183) - Bump version 0.5.1 -> 0.5.2 [`#183`](https://github.com/oceanprotocol/squid-js/pull/183)
- Use the new Aquarius response type. [`b8fec2d`](https://github.com/oceanprotocol/squid-js/commit/b8fec2d0844009944f6492aa62049e806a4286a1) - Use the new Aquarius response type. [`b8fec2d`](https://github.com/oceanprotocol/squid-js/commit/b8fec2d0844009944f6492aa62049e806a4286a1)
- Add a integration test using the consumption of big files. [`6a98fc3`](https://github.com/oceanprotocol/squid-js/commit/6a98fc39cfc8b914c5c59f59242781fd56165856) - Add a integration test using the consumption of big files. [`6a98fc3`](https://github.com/oceanprotocol/squid-js/commit/6a98fc39cfc8b914c5c59f59242781fd56165856)

View File

@ -1,6 +1,6 @@
[![banner](https://raw.githubusercontent.com/oceanprotocol/art/master/github/repo-banner%402x.png)](https://oceanprotocol.com) [![banner](https://raw.githubusercontent.com/oceanprotocol/art/master/github/repo-banner%402x.png)](https://oceanprotocol.com)
# squid-js <h1 align="center">Squid-js</h1>
> 🦑 JavaScript client library for Ocean Protocol > 🦑 JavaScript client library for Ocean Protocol
> [oceanprotocol.com](https://oceanprotocol.com) > [oceanprotocol.com](https://oceanprotocol.com)
@ -9,7 +9,7 @@
[![Travis (.com)](https://img.shields.io/travis/com/oceanprotocol/squid-js.svg)](https://travis-ci.com/oceanprotocol/squid-js) [![Travis (.com)](https://img.shields.io/travis/com/oceanprotocol/squid-js.svg)](https://travis-ci.com/oceanprotocol/squid-js)
[![GitHub contributors](https://img.shields.io/github/contributors/oceanprotocol/squid-js.svg)](https://github.com/oceanprotocol/squid-js/graphs/contributors) [![GitHub contributors](https://img.shields.io/github/contributors/oceanprotocol/squid-js.svg)](https://github.com/oceanprotocol/squid-js/graphs/contributors)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/8508313231b44b0997ec84898cd6f9db)](https://app.codacy.com/app/ocean-protocol/squid-js?utm_source=github.com&utm_medium=referral&utm_content=oceanprotocol/squid-js&utm_campaign=Badge_Grade_Settings) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/8508313231b44b0997ec84898cd6f9db)](https://app.codacy.com/app/ocean-protocol/squid-js?utm_source=github.com&utm_medium=referral&utm_content=oceanprotocol/squid-js&utm_campaign=Badge_Grade_Settings)
[![js oceanprotocol](https://img.shields.io/badge/js-oceanprotocol-7b1173.svg)](https://github.com/oceanprotocol/eslint-config-oceanprotocol) [![js oceanprotocol](https://img.shields.io/badge/js-oceanprotocol-7b1173.svg)](https://github.com/oceanprotocol/eslint-config-oceanprotocol)
[![Greenkeeper badge](https://badges.greenkeeper.io/oceanprotocol/squid-js.svg)](https://greenkeeper.io/) [![Greenkeeper badge](https://badges.greenkeeper.io/oceanprotocol/squid-js.svg)](https://greenkeeper.io/)
--- ---
@ -54,17 +54,17 @@ You can then connect to a running [Keeper](https://github.com/oceanprotocol/keep
```js ```js
const ocean: Ocean = await Ocean.getInstance({ const ocean: Ocean = await Ocean.getInstance({
// the node of the blockchain to connect to, could also be infura // the node of the blockchain to connect to, could also be infura
nodeUri: "http://localhost:8545", nodeUri: 'http://localhost:8545',
// the uri of aquarius // the uri of aquarius
aquariusUri: "http://localhost:5000", aquariusUri: 'http://localhost:5000',
// the uri of brizo // the uri of brizo
brizoUri: "http://localhost:8030", brizoUri: 'http://localhost:8030',
// address that brizo uses // address that brizo uses
brizoAddress: "0x00bd138abd70e2f00903268f3db08f2d25677c9e" brizoAddress: '0x00bd138abd70e2f00903268f3db08f2d25677c9e'
// the uri to the parity node you want to use for encryption and decryption // the uri to the parity node you want to use for encryption and decryption
parityUri: "http://localhost:9545", parityUri: 'http://localhost:9545',
// the uri of the secret store that holds the keys // the uri of the secret store that holds the keys
secretStoreUri: "http://localhost:12001" secretStoreUri: 'http://localhost:12001'
}) })
``` ```
@ -199,4 +199,4 @@ Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.

View File

@ -1 +1 @@
this document has been moved to [here](https://github.com/oceanprotocol/dev-ocean/blob/master/doc/architecture/squid.md). this document has been moved to [here](https://github.com/oceanprotocol/dev-ocean/blob/master/doc/architecture/squid.md).

View File

@ -1,32 +1,32 @@
import * as HDWalletProvider from "truffle-hdwallet-provider" import * as HDWalletProvider from 'truffle-hdwallet-provider'
import { Config } from "../src" import { Config } from '../src'
const configJson: Config = { const configJson: Config = {
nodeUri: "http://localhost:8545", nodeUri: 'http://localhost:8545',
aquariusUri: "http://172.15.0.15:5000", aquariusUri: 'http://172.15.0.15:5000',
brizoUri: "http://localhost:8030", brizoUri: 'http://localhost:8030',
secretStoreUri: "http://localhost:12001", secretStoreUri: 'http://localhost:12001',
brizoAddress: "0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e", brizoAddress: '0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e',
verbose: false, verbose: false
} }
if (process.env.NETWORK_NAME === "nile") { if (process.env.NETWORK_NAME === 'nile') {
Object.assign(configJson, { Object.assign(configJson, {
nodeUri: "https://nile.dev-ocean.com", nodeUri: 'https://nile.dev-ocean.com',
aquariusUri: "https://nginx-aquarius.dev-ocean.com", aquariusUri: 'https://nginx-aquarius.dev-ocean.com',
brizoUri: "https://nginx-brizo.dev-ocean.com", brizoUri: 'https://nginx-brizo.dev-ocean.com',
secretStoreUri: "https://secret-store.dev-ocean.com", secretStoreUri: 'https://secret-store.dev-ocean.com',
brizoAddress: "0x413c9ba0a05b8a600899b41b0c62dd661e689354", brizoAddress: '0x413c9ba0a05b8a600899b41b0c62dd661e689354'
}) })
} }
if (process.env.NETWORK_NAME === "duero") { if (process.env.NETWORK_NAME === 'duero') {
Object.assign(configJson, { Object.assign(configJson, {
nodeUri: "https://duero.dev-ocean.com", nodeUri: 'https://duero.dev-ocean.com',
aquariusUri: "https://aquarius.duero.dev-ocean.com", aquariusUri: 'https://aquarius.duero.dev-ocean.com',
brizoUri: "https://brizo.duero.dev-ocean.com", brizoUri: 'https://brizo.duero.dev-ocean.com',
secretStoreUri: "https://secret-store.duero.dev-ocean.com", secretStoreUri: 'https://secret-store.duero.dev-ocean.com',
brizoAddress: "0x9d4ed58293f71122ad6a733c1603927a150735d0", brizoAddress: '0x9d4ed58293f71122ad6a733c1603927a150735d0'
}) })
} }
@ -38,7 +38,7 @@ if (process.env.SEED_WORDS) {
seedphrase, seedphrase,
configJson.nodeUri, configJson.nodeUri,
0, 0,
5, 5
) )
} }

View File

@ -1,12 +1,12 @@
import { assert } from "chai" import { assert } from 'chai'
import { config } from "../config" import { config } from '../config'
import { getMetadata } from "../utils" import { getMetadata } from '../utils'
import { Ocean, Account } from "../../src" // @oceanprotocol/squid import { Ocean, Account } from '../../src' // @oceanprotocol/squid
describe("Asset Owners", () => { describe('Asset Owners', () => {
let ocean: Ocean let ocean: Ocean
let account1: Account let account1: Account
@ -23,7 +23,7 @@ describe("Asset Owners", () => {
account2 = accounts[1] account2 = accounts[1]
}) })
it("should be set correctly the owner of a asset", async () => { it('should be set correctly the owner of a asset', async () => {
const ddo = await ocean.assets.create(metadata as any, account1) const ddo = await ocean.assets.create(metadata as any, account1)
const owner = await ocean.assets.owner(ddo.id) const owner = await ocean.assets.owner(ddo.id)
@ -31,33 +31,49 @@ describe("Asset Owners", () => {
assert.equal(owner, account1.getId()) assert.equal(owner, account1.getId())
}) })
it("should get the assets owned by a user", async () => { it('should get the assets owned by a user', async () => {
const {length: initialLength} = await ocean.assets.ownerAssets(account2.getId()) const { length: initialLength } = await ocean.assets.ownerAssets(
account2.getId()
)
await ocean.assets.create(metadata as any, account1) await ocean.assets.create(metadata as any, account1)
await ocean.assets.create(metadata as any, account1) await ocean.assets.create(metadata as any, account1)
await ocean.assets.create(metadata as any, account2) await ocean.assets.create(metadata as any, account2)
const {length: finalLength} = await ocean.assets.ownerAssets(account2.getId()) const { length: finalLength } = await ocean.assets.ownerAssets(
account2.getId()
)
assert.equal(finalLength - initialLength, 1) assert.equal(finalLength - initialLength, 1)
}) })
it("should get the assets that can be consumer by a user", async () => { it('should get the assets that can be consumer by a user', async () => {
const {length: initialLength} = await ocean.assets.consumerAssets(account2.getId()) const { length: initialLength } = await ocean.assets.consumerAssets(
account2.getId()
)
const ddo = await ocean.assets.create(metadata as any, account1) const ddo = await ocean.assets.create(metadata as any, account1)
const {length: finalLength1} = await ocean.assets.consumerAssets(account2.getId()) const { length: finalLength1 } = await ocean.assets.consumerAssets(
account2.getId()
)
assert.equal(finalLength1 - initialLength, 0) assert.equal(finalLength1 - initialLength, 0)
// Granting access // Granting access
await account2.requestTokens(+metadata.base.price * (10 ** -await ocean.keeper.token.decimals())) await account2.requestTokens(
await ocean.assets.order(ddo.id, ddo.findServiceByType("Access").serviceDefinitionId, account2) +metadata.base.price * 10 ** -(await ocean.keeper.token.decimals())
)
await ocean.assets.order(
ddo.id,
ddo.findServiceByType('Access').serviceDefinitionId,
account2
)
// Access granted // Access granted
const {length: finalLength2} = await ocean.assets.consumerAssets(account2.getId()) const { length: finalLength2 } = await ocean.assets.consumerAssets(
account2.getId()
)
assert.equal(finalLength2 - initialLength, 1) assert.equal(finalLength2 - initialLength, 1)
}) })
}) })

View File

@ -1,10 +1,10 @@
import { assert } from "chai" import { assert } from 'chai'
import { config } from "../config" import { config } from '../config'
import { Ocean, Account } from "../../src" // @oceanprotocol/squid import { Ocean, Account } from '../../src' // @oceanprotocol/squid
describe("Authentication Token", () => { describe('Authentication Token', () => {
let ocean: Ocean let ocean: Ocean
let account1: Account let account1: Account
@ -13,7 +13,7 @@ describe("Authentication Token", () => {
before(async () => { before(async () => {
try { try {
localStorage.clear() localStorage.clear()
} catch { } } catch {}
ocean = await Ocean.getInstance(config) ocean = await Ocean.getInstance(config)
@ -23,13 +23,13 @@ describe("Authentication Token", () => {
account2 = accounts[1] account2 = accounts[1]
}) })
it("should generate a token", async () => { it('should generate a token', async () => {
const token = await ocean.auth.get(account1) const token = await ocean.auth.get(account1)
assert.match(token, /^0x[a-f0-9]{130}-[0-9]{0,14}/i) assert.match(token, /^0x[a-f0-9]{130}-[0-9]{0,14}/i)
}) })
it("should return the account that signed the token", async () => { it('should return the account that signed the token', async () => {
const token = await ocean.auth.get(account1) const token = await ocean.auth.get(account1)
const address = await ocean.auth.check(token) const address = await ocean.auth.check(token)
@ -37,7 +37,7 @@ describe("Authentication Token", () => {
assert.equal(address, account1.getId()) assert.equal(address, account1.getId())
}) })
it("should store the token for a user", async () => { it('should store the token for a user', async () => {
assert.isUndefined(await account1.getToken()) assert.isUndefined(await account1.getToken())
await ocean.auth.store(account1) await ocean.auth.store(account1)
@ -45,19 +45,19 @@ describe("Authentication Token", () => {
assert.match(await account1.getToken(), /^0x[a-f0-9]{130}-[0-9]{0,14}/i) assert.match(await account1.getToken(), /^0x[a-f0-9]{130}-[0-9]{0,14}/i)
}) })
it("should restore the token for a user", async () => { it('should restore the token for a user', async () => {
const token = await ocean.auth.restore(account1) const token = await ocean.auth.restore(account1)
assert.match(token, /^0x[a-f0-9]{130}-[0-9]{0,14}/i) assert.match(token, /^0x[a-f0-9]{130}-[0-9]{0,14}/i)
}) })
it("should return undefined when is not stored", async () => { it('should return undefined when is not stored', async () => {
const token = await ocean.auth.restore(account2) const token = await ocean.auth.restore(account2)
assert.isUndefined(token) assert.isUndefined(token)
}) })
it("should know if the token is stored", async () => { it('should know if the token is stored', async () => {
let acc1Stored let acc1Stored
let acc2Stored let acc2Stored
acc1Stored = await ocean.auth.isStored(account1) acc1Stored = await ocean.auth.isStored(account1)

View File

@ -1,12 +1,12 @@
import { assert } from "chai" import { assert } from 'chai'
import * as fs from "fs" import * as fs from 'fs'
import { config } from "../config" import { config } from '../config'
import { getMetadata } from "../utils" import { getMetadata } from '../utils'
import { Ocean, DDO, Account, ConditionState } from "../../src" // @oceanprotocol/squid import { Ocean, DDO, Account, ConditionState } from '../../src' // @oceanprotocol/squid
describe("Consume Asset", () => { describe('Consume Asset', () => {
let ocean: Ocean let ocean: Ocean
let publisher: Account let publisher: Account
@ -15,7 +15,10 @@ describe("Consume Asset", () => {
const metadata = getMetadata() const metadata = getMetadata()
let ddo: DDO let ddo: DDO
let serviceAgreementSignatureResult: {agreementId: string, signature: string} let serviceAgreementSignatureResult: {
agreementId: string
signature: string
}
before(async () => { before(async () => {
ocean = await Ocean.getInstance(config) ocean = await Ocean.getInstance(config)
@ -25,35 +28,59 @@ describe("Consume Asset", () => {
consumer = (await ocean.accounts.list())[1] consumer = (await ocean.accounts.list())[1]
}) })
it("should regiester a asset", async () => { it('should regiester a asset', async () => {
ddo = await ocean.assets.create(metadata as any, publisher) ddo = await ocean.assets.create(metadata as any, publisher)
assert.isDefined(ddo, "Register has not returned a DDO") assert.isDefined(ddo, 'Register has not returned a DDO')
assert.match(ddo.id, /^did:op:[a-f0-9]{64}$/, "DDO id is not valid") assert.match(ddo.id, /^did:op:[a-f0-9]{64}$/, 'DDO id is not valid')
assert.isAtLeast(ddo.authentication.length, 1, "Default authentication not added") assert.isAtLeast(
assert.isDefined(ddo.findServiceByType("Access"), "DDO Access service doesn't exist") ddo.authentication.length,
1,
'Default authentication not added'
)
assert.isDefined(
ddo.findServiceByType('Access'),
"DDO Access service doesn't exist"
)
}) })
it("should be able to request tokens for consumer", async () => { it('should be able to request tokens for consumer', async () => {
const initialBalance = (await consumer.getBalance()).ocn const initialBalance = (await consumer.getBalance()).ocn
const claimedTokens = +metadata.base.price * (10 ** -await ocean.keeper.token.decimals()) const claimedTokens =
+metadata.base.price * 10 ** -(await ocean.keeper.token.decimals())
await consumer.requestTokens(claimedTokens) await consumer.requestTokens(claimedTokens)
assert.equal((await consumer.getBalance()).ocn, initialBalance + claimedTokens, "OCN Tokens not delivered") assert.equal(
(await consumer.getBalance()).ocn,
initialBalance + claimedTokens,
'OCN Tokens not delivered'
)
}) })
it("should sign the service agreement", async () => { it('should sign the service agreement', async () => {
const accessService = ddo.findServiceByType("Access") const accessService = ddo.findServiceByType('Access')
serviceAgreementSignatureResult = await ocean.agreements.prepare(ddo.id, accessService.serviceDefinitionId, consumer) serviceAgreementSignatureResult = await ocean.agreements.prepare(
ddo.id,
accessService.serviceDefinitionId,
consumer
)
const {agreementId, signature} = serviceAgreementSignatureResult const { agreementId, signature } = serviceAgreementSignatureResult
assert.match(agreementId, /^0x[a-f0-9]{64}$/, "Service agreement ID seems not valid") assert.match(
assert.match(signature, /^0x[a-f0-9]{130}$/, "Service agreement signature seems not valid") agreementId,
/^0x[a-f0-9]{64}$/,
'Service agreement ID seems not valid'
)
assert.match(
signature,
/^0x[a-f0-9]{130}$/,
'Service agreement signature seems not valid'
)
}) })
it("should execute the service agreement", async () => { it('should execute the service agreement', async () => {
const accessService = ddo.findServiceByType("Access") const accessService = ddo.findServiceByType('Access')
const success = await ocean.agreements.create( const success = await ocean.agreements.create(
ddo.id, ddo.id,
@ -61,103 +88,115 @@ describe("Consume Asset", () => {
accessService.serviceDefinitionId, accessService.serviceDefinitionId,
serviceAgreementSignatureResult.signature, serviceAgreementSignatureResult.signature,
consumer, consumer,
publisher, publisher
) )
assert.isTrue(success) assert.isTrue(success)
}) })
it("should get the agreement conditions status not fulfilled", async () => { it('should get the agreement conditions status not fulfilled', async () => {
const status = await ocean.agreements.status(serviceAgreementSignatureResult.agreementId) const status = await ocean.agreements.status(
serviceAgreementSignatureResult.agreementId
)
assert.deepEqual(status, { assert.deepEqual(status, {
lockReward: ConditionState.Unfulfilled, lockReward: ConditionState.Unfulfilled,
accessSecretStore: ConditionState.Unfulfilled, accessSecretStore: ConditionState.Unfulfilled,
escrowReward: ConditionState.Unfulfilled, escrowReward: ConditionState.Unfulfilled
}) })
}) })
it("should lock the payment by the consumer", async () => { it('should lock the payment by the consumer', async () => {
const paid = await ocean.agreements.conditions const paid = await ocean.agreements.conditions.lockReward(
.lockReward( serviceAgreementSignatureResult.agreementId,
serviceAgreementSignatureResult.agreementId, ddo.findServiceByType('Metadata').metadata.base.price,
ddo.findServiceByType("Metadata").metadata.base.price, consumer
consumer, )
)
assert.isTrue(paid, "The asset has not been paid correctly") assert.isTrue(paid, 'The asset has not been paid correctly')
}) })
// The test will fail because Brizo grants the access faster // The test will fail because Brizo grants the access faster
it("should grant the access by the publisher", async () => { it('should grant the access by the publisher', async () => {
try { try {
const granted = await ocean.agreements.conditions const granted = await ocean.agreements.conditions.grantAccess(
.grantAccess(serviceAgreementSignatureResult.agreementId, ddo.id, consumer.getId(), publisher) serviceAgreementSignatureResult.agreementId,
ddo.id,
consumer.getId(),
publisher
)
assert.isTrue(granted, "The asset has not been granted correctly") assert.isTrue(granted, 'The asset has not been granted correctly')
const accessGranted = await ocean.keeper.conditions const accessGranted = await ocean.keeper.conditions.accessSecretStoreCondition.checkPermissions(
.accessSecretStoreCondition consumer.getId(),
.checkPermissions(consumer.getId(), ddo.id) ddo.id
)
assert.isTrue(accessGranted, "Consumer has been granted.") assert.isTrue(accessGranted, 'Consumer has been granted.')
} catch { } } catch {}
}) })
it("should get the agreement conditions status fulfilled", async () => { it('should get the agreement conditions status fulfilled', async () => {
const status = await ocean.agreements.status(serviceAgreementSignatureResult.agreementId) const status = await ocean.agreements.status(
serviceAgreementSignatureResult.agreementId
)
assert.deepEqual(status, { assert.deepEqual(status, {
lockReward: ConditionState.Fulfilled, lockReward: ConditionState.Fulfilled,
accessSecretStore: ConditionState.Fulfilled, accessSecretStore: ConditionState.Fulfilled,
escrowReward: ConditionState.Unfulfilled, escrowReward: ConditionState.Unfulfilled
}) })
}) })
it("should consume and store the assets", async () => { it('should consume and store the assets', async () => {
const accessService = ddo.findServiceByType("Access") const accessService = ddo.findServiceByType('Access')
const folder = "/tmp/ocean/squid-js-1" const folder = '/tmp/ocean/squid-js-1'
const path = await ocean.assets.consume(
serviceAgreementSignatureResult.agreementId,
ddo.id,
accessService.serviceDefinitionId,
consumer,
folder
)
assert.include(path, folder, 'The storage path is not correct.')
const files = await new Promise<string[]>(resolve => {
fs.readdir(path, (err, fileList) => {
resolve(fileList)
})
})
assert.deepEqual(
files,
['README.md', 'package.json'],
'Stored files are not correct.'
)
})
it('should consume and store one assets', async () => {
const accessService = ddo.findServiceByType('Access')
const folder = '/tmp/ocean/squid-js-2'
const path = await ocean.assets.consume( const path = await ocean.assets.consume(
serviceAgreementSignatureResult.agreementId, serviceAgreementSignatureResult.agreementId,
ddo.id, ddo.id,
accessService.serviceDefinitionId, accessService.serviceDefinitionId,
consumer, consumer,
folder, folder,
1
) )
assert.include(path, folder, "The storage path is not correct.") assert.include(path, folder, 'The storage path is not correct.')
const files = await new Promise<string[]>((resolve) => { const files = await new Promise<string[]>(resolve => {
fs.readdir(path, (err, fileList) => { fs.readdir(path, (err, fileList) => {
resolve(fileList) resolve(fileList)
}) })
}) })
assert.deepEqual(files, ["README.md", "package.json"], "Stored files are not correct.") assert.deepEqual(files, ['README.md'], 'Stored files are not correct.')
})
it("should consume and store one assets", async () => {
const accessService = ddo.findServiceByType("Access")
const folder = "/tmp/ocean/squid-js-2"
const path = await ocean.assets.consume(
serviceAgreementSignatureResult.agreementId,
ddo.id,
accessService.serviceDefinitionId,
consumer,
folder,
1,
)
assert.include(path, folder, "The storage path is not correct.")
const files = await new Promise<string[]>((resolve) => {
fs.readdir(path, (err, fileList) => {
resolve(fileList)
})
})
assert.deepEqual(files, ["README.md"], "Stored files are not correct.")
}) })
}) })

View File

@ -1,12 +1,12 @@
import { assert } from "chai" import { assert } from 'chai'
import * as fs from "fs" import * as fs from 'fs'
import { config } from "../config" import { config } from '../config'
import { getMetadata } from "../utils" import { getMetadata } from '../utils'
import { Ocean, Account, DDO } from "../../src" // @oceanprotocol/squid import { Ocean, Account, DDO } from '../../src' // @oceanprotocol/squid
describe("Consume Asset (Brizo)", () => { describe('Consume Asset (Brizo)', () => {
let ocean: Ocean let ocean: Ocean
let publisher: Account let publisher: Account
@ -28,50 +28,64 @@ describe("Consume Asset (Brizo)", () => {
after(() => { after(() => {
try { try {
localStorage.clear() localStorage.clear()
} catch { } } catch {}
}) })
it("should authenticate the accounts", async () => { it('should authenticate the accounts', async () => {
await publisher.authenticate() await publisher.authenticate()
await consumer.authenticate() await consumer.authenticate()
}) })
it("should regiester an asset", async () => { it('should regiester an asset', async () => {
const steps = [] const steps = []
ddo = await ocean.assets.create(metadata as any, publisher) ddo = await ocean.assets
.next((step) => steps.push(step)) .create(metadata as any, publisher)
.next(step => steps.push(step))
assert.instanceOf(ddo, DDO) assert.instanceOf(ddo, DDO)
assert.deepEqual(steps, [0, 1, 2, 3, 4, 5, 6, 7]) assert.deepEqual(steps, [0, 1, 2, 3, 4, 5, 6, 7])
}) })
it("should order the asset", async () => { it('should order the asset', async () => {
const accessService = ddo.findServiceByType("Access") const accessService = ddo.findServiceByType('Access')
await consumer.requestTokens(+metadata.base.price * (10 ** -await ocean.keeper.token.decimals())) await consumer.requestTokens(
+metadata.base.price * 10 ** -(await ocean.keeper.token.decimals())
)
const steps = [] const steps = []
agreementId = await ocean.assets.order(ddo.id, accessService.serviceDefinitionId, consumer) agreementId = await ocean.assets
.next((step) => steps.push(step)) .order(ddo.id, accessService.serviceDefinitionId, consumer)
.next(step => steps.push(step))
assert.isDefined(agreementId) assert.isDefined(agreementId)
assert.deepEqual(steps, [0, 1, 2, 3]) assert.deepEqual(steps, [0, 1, 2, 3])
}) })
it("should consume and store the assets", async () => { it('should consume and store the assets', async () => {
const accessService = ddo.findServiceByType("Access") const accessService = ddo.findServiceByType('Access')
const folder = "/tmp/ocean/squid-js" const folder = '/tmp/ocean/squid-js'
const path = await ocean.assets.consume(agreementId, ddo.id, accessService.serviceDefinitionId, consumer, folder) const path = await ocean.assets.consume(
agreementId,
ddo.id,
accessService.serviceDefinitionId,
consumer,
folder
)
assert.include(path, folder, "The storage path is not correct.") assert.include(path, folder, 'The storage path is not correct.')
const files = await new Promise<string[]>((resolve) => { const files = await new Promise<string[]>(resolve => {
fs.readdir(path, (err, fileList) => { fs.readdir(path, (err, fileList) => {
resolve(fileList) resolve(fileList)
}) })
}) })
assert.deepEqual(files, ["README.md", "package.json"], "Stored files are not correct.") assert.deepEqual(
files,
['README.md', 'package.json'],
'Stored files are not correct.'
)
}) })
}) })

View File

@ -1,13 +1,13 @@
import { assert } from "chai" import { assert } from 'chai'
import * as fs from "fs" import * as fs from 'fs'
import { config } from "../config" import { config } from '../config'
import { getMetadata } from "../utils" import { getMetadata } from '../utils'
import { Ocean, Account, DDO } from "../../src" // @oceanprotocol/squid import { Ocean, Account, DDO } from '../../src' // @oceanprotocol/squid
// Ensure that your network is fast enought and you have some free ram before run it. // Ensure that your network is fast enought and you have some free ram before run it.
xdescribe("Consume Asset (Large size)", () => { xdescribe('Consume Asset (Large size)', () => {
let ocean: Ocean let ocean: Ocean
let publisher: Account let publisher: Account
@ -21,10 +21,12 @@ xdescribe("Consume Asset (Large size)", () => {
...baseMetadata, ...baseMetadata,
base: { base: {
...baseMetadata.base, ...baseMetadata.base,
files: [{ files: [
url: "https://speed.hetzner.de/1GB.bin", {
}], url: 'https://speed.hetzner.de/1GB.bin'
}, }
]
}
} }
before(async () => { before(async () => {
@ -35,36 +37,46 @@ xdescribe("Consume Asset (Large size)", () => {
consumer = (await ocean.accounts.list())[1] consumer = (await ocean.accounts.list())[1]
}) })
it("should regiester an asset", async () => { it('should regiester an asset', async () => {
ddo = await ocean.assets.create(metadata as any, publisher) ddo = await ocean.assets.create(metadata as any, publisher)
assert.instanceOf(ddo, DDO) assert.instanceOf(ddo, DDO)
}) })
it("should order the asset", async () => { it('should order the asset', async () => {
const accessService = ddo.findServiceByType("Access") const accessService = ddo.findServiceByType('Access')
await consumer.requestTokens(metadata.base.price) await consumer.requestTokens(metadata.base.price)
agreementId = await ocean.assets.order(ddo.id, accessService.serviceDefinitionId, consumer) agreementId = await ocean.assets.order(
ddo.id,
accessService.serviceDefinitionId,
consumer
)
assert.isDefined(agreementId) assert.isDefined(agreementId)
}) })
it("should consume and store the assets", async () => { it('should consume and store the assets', async () => {
const accessService = ddo.findServiceByType("Access") const accessService = ddo.findServiceByType('Access')
const folder = "/tmp/ocean/squid-js" const folder = '/tmp/ocean/squid-js'
const path = await ocean.assets.consume(agreementId, ddo.id, accessService.serviceDefinitionId, consumer, folder) const path = await ocean.assets.consume(
agreementId,
ddo.id,
accessService.serviceDefinitionId,
consumer,
folder
)
assert.include(path, folder, "The storage path is not correct.") assert.include(path, folder, 'The storage path is not correct.')
const files = await new Promise<string[]>((resolve) => { const files = await new Promise<string[]>(resolve => {
fs.readdir(path, (err, fileList) => { fs.readdir(path, (err, fileList) => {
resolve(fileList) resolve(fileList)
}) })
}) })
assert.deepEqual(files, ["1GB.bin"], "Stored files are not correct.") assert.deepEqual(files, ['1GB.bin'], 'Stored files are not correct.')
}) })
}) })

View File

@ -1,19 +1,23 @@
import { assert } from "chai" import { assert } from 'chai'
import { config } from "../config" import { config } from '../config'
import { Ocean, templates, conditions, utils, Account, Keeper } from "../../src" // @oceanprotocol/squid import { Ocean, templates, conditions, utils, Account, Keeper } from '../../src' // @oceanprotocol/squid
const { LockRewardCondition, EscrowReward, AccessSecretStoreCondition } = conditions const {
LockRewardCondition,
EscrowReward,
AccessSecretStoreCondition
} = conditions
describe("Register Escrow Access Secret Store Template", () => { describe('Register Escrow Access Secret Store Template', () => {
let ocean: Ocean let ocean: Ocean
let keeper: Keeper let keeper: Keeper
let template: templates.EscrowAccessSecretStoreTemplate let template: templates.EscrowAccessSecretStoreTemplate
const url = "https://example.com/did/ocean/test-attr-example.txt" const url = 'https://example.com/did/ocean/test-attr-example.txt'
const checksum = "b".repeat(32) const checksum = 'b'.repeat(32)
const escrowAmount = 12 const escrowAmount = 12
let templateManagerOwner: Account let templateManagerOwner: Account
@ -36,26 +40,35 @@ describe("Register Escrow Access Secret Store Template", () => {
consumer = (await ocean.accounts.list())[2] consumer = (await ocean.accounts.list())[2]
// Conditions // Conditions
accessSecretStoreCondition = keeper.conditions.accessSecretStoreCondition accessSecretStoreCondition =
keeper.conditions.accessSecretStoreCondition
lockRewardCondition = keeper.conditions.lockRewardCondition lockRewardCondition = keeper.conditions.lockRewardCondition
escrowReward = keeper.conditions.escrowReward escrowReward = keeper.conditions.escrowReward
}) })
describe("Propose and approve template", () => { describe('Propose and approve template', () => {
it("should propose the template", async () => { it('should propose the template', async () => {
await keeper.templateStoreManager.proposeTemplate(template.getAddress(), consumer.getId(), true) await keeper.templateStoreManager.proposeTemplate(
template.getAddress(),
consumer.getId(),
true
)
// TODO: Use a event to detect template mined // TODO: Use a event to detect template mined
await new Promise((_) => setTimeout(_, 2 * 1000)) await new Promise(_ => setTimeout(_, 2 * 1000))
}) })
it("should approve the template", async () => { it('should approve the template', async () => {
await keeper.templateStoreManager.approveTemplate(template.getAddress(), templateManagerOwner.getId(), true) await keeper.templateStoreManager.approveTemplate(
template.getAddress(),
templateManagerOwner.getId(),
true
)
// TODO: Use a event to detect template mined // TODO: Use a event to detect template mined
await new Promise((_) => setTimeout(_, 2 * 1000)) await new Promise(_ => setTimeout(_, 2 * 1000))
}) })
}) })
describe("Full flow", () => { describe('Full flow', () => {
const agreementId = `0x${utils.generateId()}` const agreementId = `0x${utils.generateId()}`
const did = `0x${utils.generateId()}` const did = `0x${utils.generateId()}`
@ -63,49 +76,76 @@ describe("Register Escrow Access Secret Store Template", () => {
let conditionIdLock: string let conditionIdLock: string
let conditionIdEscrow: string let conditionIdEscrow: string
it("should register a DID", async () => { it('should register a DID', async () => {
await keeper.didRegistry.registerAttribute(did, checksum, [], url, publisher.getId()) await keeper.didRegistry.registerAttribute(
did,
checksum,
[],
url,
publisher.getId()
)
}) })
it("should generate the condition IDs", async () => { it('should generate the condition IDs', async () => {
conditionIdAccess = await accessSecretStoreCondition.generateIdHash(agreementId, did, consumer.getId()) conditionIdAccess = await accessSecretStoreCondition.generateIdHash(
conditionIdLock = await lockRewardCondition.generateIdHash(agreementId, await escrowReward.getAddress(), escrowAmount) agreementId,
did,
consumer.getId()
)
conditionIdLock = await lockRewardCondition.generateIdHash(
agreementId,
await escrowReward.getAddress(),
escrowAmount
)
conditionIdEscrow = await escrowReward.generateIdHash( conditionIdEscrow = await escrowReward.generateIdHash(
agreementId, agreementId,
escrowAmount, escrowAmount,
publisher.getId(), publisher.getId(),
consumer.getId(), consumer.getId(),
conditionIdLock, conditionIdLock,
conditionIdAccess, conditionIdAccess
) )
}) })
it("should have conditions types", async () => { it('should have conditions types', async () => {
const conditionTypes = await template.getConditionTypes() const conditionTypes = await template.getConditionTypes()
assert.equal(conditionTypes.length, 3, "Expected 3 conditions.") assert.equal(conditionTypes.length, 3, 'Expected 3 conditions.')
assert.deepEqual( assert.deepEqual(
[...conditionTypes].sort(), [...conditionTypes].sort(),
[accessSecretStoreCondition.getAddress(), escrowReward.getAddress(), lockRewardCondition.getAddress()].sort(), [
"The conditions doesn't match", accessSecretStoreCondition.getAddress(),
escrowReward.getAddress(),
lockRewardCondition.getAddress()
].sort(),
"The conditions doesn't match"
) )
}) })
it("should have condition instances asociated", async () => { it('should have condition instances asociated', async () => {
const conditionInstances = await template.getConditions() const conditionInstances = await template.getConditions()
assert.equal(conditionInstances.length, 3, "Expected 3 conditions.") assert.equal(conditionInstances.length, 3, 'Expected 3 conditions.')
const conditionClasses = [AccessSecretStoreCondition, EscrowReward, LockRewardCondition] const conditionClasses = [
conditionClasses AccessSecretStoreCondition,
.forEach((conditionClass) => { EscrowReward,
if (!conditionInstances.find((condition) => condition instanceof conditionClass)) { LockRewardCondition
throw new Error(`${conditionClass.name} is not part of the conditions.`) ]
} conditionClasses.forEach(conditionClass => {
}) if (
!conditionInstances.find(
condition => condition instanceof conditionClass
)
) {
throw new Error(
`${conditionClass.name} is not part of the conditions.`
)
}
})
}) })
it("should create a new agreement", async () => { it('should create a new agreement', async () => {
const agreement = await template.createAgreement( const agreement = await template.createAgreement(
agreementId, agreementId,
did, did,
@ -113,35 +153,52 @@ describe("Register Escrow Access Secret Store Template", () => {
[0, 0, 0], [0, 0, 0],
[0, 0, 0], [0, 0, 0],
consumer.getId(), consumer.getId(),
publisher.getId(), publisher.getId()
) )
assert.isTrue(agreement.status) assert.isTrue(agreement.status)
}) })
it("should not grant the access to the consumer", async () => { it('should not grant the access to the consumer', async () => {
const accessGranted = await accessSecretStoreCondition.checkPermissions(consumer.getId(), did) const accessGranted = await accessSecretStoreCondition.checkPermissions(
consumer.getId(),
did
)
assert.isFalse(accessGranted, "Consumer has been granted.") assert.isFalse(accessGranted, 'Consumer has been granted.')
}) })
it("should fulfill LockRewardCondition", async () => { it('should fulfill LockRewardCondition', async () => {
await consumer.requestTokens(escrowAmount) await consumer.requestTokens(escrowAmount)
await keeper.token.approve(lockRewardCondition.getAddress(), escrowAmount, consumer.getId()) await keeper.token.approve(
lockRewardCondition.getAddress(),
escrowAmount,
consumer.getId()
)
const fulfill = await lockRewardCondition.fulfill(agreementId, escrowReward.getAddress(), escrowAmount, consumer.getId()) const fulfill = await lockRewardCondition.fulfill(
agreementId,
escrowReward.getAddress(),
escrowAmount,
consumer.getId()
)
assert.isDefined(fulfill.events.Fulfilled, "Not Fulfilled event.") assert.isDefined(fulfill.events.Fulfilled, 'Not Fulfilled event.')
}) })
it("should fulfill AccessSecretStoreCondition", async () => { it('should fulfill AccessSecretStoreCondition', async () => {
const fulfill = await accessSecretStoreCondition.fulfill(agreementId, did, consumer.getId(), publisher.getId()) const fulfill = await accessSecretStoreCondition.fulfill(
agreementId,
did,
consumer.getId(),
publisher.getId()
)
assert.isDefined(fulfill.events.Fulfilled, "Not Fulfilled event.") assert.isDefined(fulfill.events.Fulfilled, 'Not Fulfilled event.')
}) })
it("should fulfill EscrowReward", async () => { it('should fulfill EscrowReward', async () => {
const fulfill = await escrowReward.fulfill( const fulfill = await escrowReward.fulfill(
agreementId, agreementId,
escrowAmount, escrowAmount,
@ -149,56 +206,92 @@ describe("Register Escrow Access Secret Store Template", () => {
consumer.getId(), consumer.getId(),
conditionIdLock, conditionIdLock,
conditionIdAccess, conditionIdAccess,
consumer.getId(), consumer.getId()
) )
assert.isDefined(fulfill.events.Fulfilled, "Not Fulfilled event.") assert.isDefined(fulfill.events.Fulfilled, 'Not Fulfilled event.')
}) })
it("should grant the access to the consumer", async () => { it('should grant the access to the consumer', async () => {
const accessGranted = await accessSecretStoreCondition.checkPermissions(consumer.getId(), did) const accessGranted = await accessSecretStoreCondition.checkPermissions(
consumer.getId(),
did
)
assert.isTrue(accessGranted, "Consumer has not been granted.") assert.isTrue(accessGranted, 'Consumer has not been granted.')
}) })
}) })
describe("Short flow", () => { describe('Short flow', () => {
const did = utils.generateId() const did = utils.generateId()
let agreementId let agreementId
it("should register a DID", async () => { it('should register a DID', async () => {
// This part is executed inside Ocean.assets.create() // This part is executed inside Ocean.assets.create()
await keeper.didRegistry.registerAttribute(did, checksum, [], url, publisher.getId()) await keeper.didRegistry.registerAttribute(
did,
checksum,
[],
url,
publisher.getId()
)
}) })
it("should create a new agreement (short way)", async () => { it('should create a new agreement (short way)', async () => {
agreementId = await template.createFullAgreement(did, escrowAmount, consumer.getId(), publisher.getId()) agreementId = await template.createFullAgreement(
did,
escrowAmount,
consumer.getId(),
publisher.getId()
)
assert.match(agreementId, /^0x[a-f0-9]{64}$/i) assert.match(agreementId, /^0x[a-f0-9]{64}$/i)
}) })
it("should not grant the access to the consumer", async () => { it('should not grant the access to the consumer', async () => {
const accessGranted = await accessSecretStoreCondition.checkPermissions(consumer.getId(), did) const accessGranted = await accessSecretStoreCondition.checkPermissions(
consumer.getId(),
did
)
assert.isFalse(accessGranted, "Consumer has been granted.") assert.isFalse(accessGranted, 'Consumer has been granted.')
}) })
it("should fulfill the conditions from consumer side", async () => { it('should fulfill the conditions from consumer side', async () => {
await consumer.requestTokens(escrowAmount) await consumer.requestTokens(escrowAmount)
await ocean.agreements.conditions.lockReward(agreementId, escrowAmount, consumer) await ocean.agreements.conditions.lockReward(
agreementId,
escrowAmount,
consumer
)
}) })
it("should fulfill the conditions from publisher side", async () => { it('should fulfill the conditions from publisher side', async () => {
await ocean.agreements.conditions.grantAccess(agreementId, did, consumer.getId(), publisher) await ocean.agreements.conditions.grantAccess(
await ocean.agreements.conditions.releaseReward(agreementId, escrowAmount, did, consumer.getId(), publisher.getId(), publisher) agreementId,
did,
consumer.getId(),
publisher
)
await ocean.agreements.conditions.releaseReward(
agreementId,
escrowAmount,
did,
consumer.getId(),
publisher.getId(),
publisher
)
}) })
it("should grant the access to the consumer", async () => { it('should grant the access to the consumer', async () => {
const accessGranted = await accessSecretStoreCondition.checkPermissions(consumer.getId(), did) const accessGranted = await accessSecretStoreCondition.checkPermissions(
consumer.getId(),
did
)
assert.isTrue(accessGranted, "Consumer has not been granted.") assert.isTrue(accessGranted, 'Consumer has not been granted.')
}) })
}) })
}) })

View File

@ -1,18 +1,21 @@
import { assert } from "chai" import { assert } from 'chai'
import { config } from "../config" import { config } from '../config'
import { generateMetadata } from "../utils" import { generateMetadata } from '../utils'
import { Ocean, Account, DDO } from "../../src" // @oceanprotocol/squid import { Ocean, Account, DDO } from '../../src' // @oceanprotocol/squid
describe("Search Asset", () => { describe('Search Asset', () => {
let ocean: Ocean let ocean: Ocean
let publisher: Account let publisher: Account
const testHash = Math.random().toString(36).substr(2) const testHash = Math.random()
const metadataGenerator = (name: string) => generateMetadata(`${name}${testHash}`) .toString(36)
.substr(2)
const metadataGenerator = (name: string) =>
generateMetadata(`${name}${testHash}`)
let test1length let test1length
let test2length let test2length
@ -26,56 +29,92 @@ describe("Search Asset", () => {
publisher.setPassword(process.env.ACCOUNT_PASSWORD) publisher.setPassword(process.env.ACCOUNT_PASSWORD)
}) })
it("should be able to search the assets", async () => { it('should be able to search the assets', async () => {
const {results: ddos} = await ocean.assets.search(`Test1${testHash}`) const { results: ddos } = await ocean.assets.search(`Test1${testHash}`)
assert.isArray(ddos, "A search should return an array") assert.isArray(ddos, 'A search should return an array')
test1length = ddos.length test1length = ddos.length
test2length = (await ocean.assets.search(`Test2${testHash}`)).results.length test2length = (await ocean.assets.search(`Test2${testHash}`)).results
test3length = (await ocean.assets.search(`Test3${testHash}`)).results.length .length
test3length = (await ocean.assets.search(`Test3${testHash}`)).results
.length
}) })
it("should regiester some a asset", async () => { it('should regiester some a asset', async () => {
assert.instanceOf(await ocean.assets.create(metadataGenerator("Test1") as any, publisher), DDO) assert.instanceOf(
assert.instanceOf(await ocean.assets.create(metadataGenerator("Test2") as any, publisher), DDO) await ocean.assets.create(
assert.instanceOf(await ocean.assets.create(metadataGenerator("Test2") as any, publisher), DDO) metadataGenerator('Test1') as any,
assert.instanceOf(await ocean.assets.create(metadataGenerator("Test3") as any, publisher), DDO) publisher
),
DDO
)
assert.instanceOf(
await ocean.assets.create(
metadataGenerator('Test2') as any,
publisher
),
DDO
)
assert.instanceOf(
await ocean.assets.create(
metadataGenerator('Test2') as any,
publisher
),
DDO
)
assert.instanceOf(
await ocean.assets.create(
metadataGenerator('Test3') as any,
publisher
),
DDO
)
}) })
it("should search by text and see the increment of DDOs", async () => { it('should search by text and see the increment of DDOs', async () => {
assert.equal( assert.equal(
(await ocean.assets.search(`Test2${testHash}`)).results.length - test2length, (await ocean.assets.search(`Test2${testHash}`)).results.length -
test2length,
2, 2,
"Something was wrong searching the assets", 'Something was wrong searching the assets'
) )
assert.equal( assert.equal(
(await ocean.assets.search(`Test3${testHash}`)).results.length - test3length, (await ocean.assets.search(`Test3${testHash}`)).results.length -
test3length,
1, 1,
"Something was wrong searching the assets", 'Something was wrong searching the assets'
) )
}) })
it("should return a list of DDOs", async () => { it('should return a list of DDOs', async () => {
const {results: ddos} = await ocean.assets.search(`Test1${testHash}`) const { results: ddos } = await ocean.assets.search(`Test1${testHash}`)
assert.equal(ddos.length - test1length, 1, "Something was wrong searching the assets") assert.equal(
ddos.map((ddo) => assert.instanceOf(ddo, DDO, "The DDO is not an instance of a DDO")) ddos.length - test1length,
1,
'Something was wrong searching the assets'
)
ddos.map(ddo =>
assert.instanceOf(ddo, DDO, 'The DDO is not an instance of a DDO')
)
}) })
it("should be able to do a query to get a list of DDOs", async () => { it('should be able to do a query to get a list of DDOs', async () => {
const {results: ddos} = await ocean.assets.query({ const { results: ddos } = await ocean.assets.query({
page: 1, page: 1,
offset: 1, offset: 1,
query: { query: {
text: [`Test2${testHash}`], text: [`Test2${testHash}`]
}, },
sort: { sort: {
text: 1, text: 1
}, }
}) })
assert.equal(ddos.length, 1, "Something was wrong searching the assets") assert.equal(ddos.length, 1, 'Something was wrong searching the assets')
ddos.map((ddo) => assert.instanceOf(ddo, DDO, "The DDO is not an instance of a DDO")) ddos.map(ddo =>
assert.instanceOf(ddo, DDO, 'The DDO is not an instance of a DDO')
)
}) })
}) })

View File

@ -1,16 +1,16 @@
import { assert } from "chai" import { assert } from 'chai'
import { config } from "../config" import { config } from '../config'
import { Ocean, Account, DID } from "../../src" // @oceanprotocol/squid import { Ocean, Account, DID } from '../../src' // @oceanprotocol/squid
describe("Secret Store", () => { describe('Secret Store', () => {
let ocean: Ocean let ocean: Ocean
let account: Account let account: Account
const did: DID = DID.generate() const did: DID = DID.generate()
const content = {content: "Test 123"} const content = { content: 'Test 123' }
let encryptedContent let encryptedContent
before(async () => { before(async () => {
@ -20,8 +20,12 @@ describe("Secret Store", () => {
account = (await ocean.accounts.list())[0] account = (await ocean.accounts.list())[0]
}) })
it("should encrypt a text", async () => { it('should encrypt a text', async () => {
encryptedContent = await ocean.secretStore.encrypt(did.getId(), content, account) encryptedContent = await ocean.secretStore.encrypt(
did.getId(),
content,
account
)
assert.isDefined(encryptedContent) assert.isDefined(encryptedContent)
assert.match(encryptedContent, /^0x[a-f0-9]{76}$/i) assert.match(encryptedContent, /^0x[a-f0-9]{76}$/i)

View File

@ -1,13 +1,12 @@
import { assert } from "chai" import { assert } from 'chai'
import { config } from "../config" import { config } from '../config'
import { Ocean, Account, DDO } from "../../src" // @oceanprotocol/squid import { Ocean, Account, DDO } from '../../src' // @oceanprotocol/squid
// WARN: not integration test. It has been done here because constant values // WARN: not integration test. It has been done here because constant values
// depends on the first account on spree (only accessible from integration test) // depends on the first account on spree (only accessible from integration test)
describe("Signature", () => { describe('Signature', () => {
let ocean: Ocean let ocean: Ocean
let consumer: Account let consumer: Account
@ -18,32 +17,36 @@ describe("Signature", () => {
consumer = (await ocean.accounts.list())[0] consumer = (await ocean.accounts.list())[0]
}) })
it("should generate the correct signature", async () => { it('should generate the correct signature', async () => {
const templateId = `0x${"f".repeat(40)}` const templateId = `0x${'f'.repeat(40)}`
const agreementId = `0x${"e".repeat(64)}` const agreementId = `0x${'e'.repeat(64)}`
const accessId = `0x${"a".repeat(64)}` const accessId = `0x${'a'.repeat(64)}`
const lockId = `0x${"b".repeat(64)}` const lockId = `0x${'b'.repeat(64)}`
const escrowId = `0x${"c".repeat(64)}` const escrowId = `0x${'c'.repeat(64)}`
const hash = await ocean.utils.agreements.hashServiceAgreement( const hash = await ocean.utils.agreements.hashServiceAgreement(
templateId, templateId,
agreementId, agreementId,
[accessId, lockId, escrowId], [accessId, lockId, escrowId],
[0, 0, 0], [0, 0, 0],
[0, 0, 0], [0, 0, 0]
) )
assert.equal(hash, "0x67901517c18a3d23e05806fff7f04235cc8ae3b1f82345b8bfb3e4b02b5800c7", "The signatuere is not correct.") assert.equal(
hash,
'0x67901517c18a3d23e05806fff7f04235cc8ae3b1f82345b8bfb3e4b02b5800c7',
'The signatuere is not correct.'
)
}) })
it("should generate the correct signature", async () => { it('should generate the correct signature', async () => {
const templates = ocean.keeper.templates const { templates } = ocean.keeper
const did = `did:op:${"c".repeat(64)}` const did = `did:op:${'c'.repeat(64)}`
const templateId = `0x${"f".repeat(40)}` const templateId = `0x${'f'.repeat(40)}`
const agreementId = `0x${"e".repeat(64)}` const agreementId = `0x${'e'.repeat(64)}`
const serviceDefinitionId = "0" const serviceDefinitionId = '0'
const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate() const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate()
@ -51,37 +54,41 @@ describe("Signature", () => {
id: did, id: did,
service: [ service: [
{ {
type: "Access", type: 'Access',
purchaseEndpoint: undefined, purchaseEndpoint: undefined,
serviceEndpoint: undefined, serviceEndpoint: undefined,
serviceDefinitionId, serviceDefinitionId,
templateId, templateId,
serviceAgreementTemplate, serviceAgreementTemplate
} as any, } as any,
{ {
type: "Metadata", type: 'Metadata',
metadata: { metadata: {
base: { base: {
price: 10, price: 10
}, }
}, }
} as any, } as any
], ]
}) })
const signature = await ocean.utils.agreements.signServiceAgreement( const signature = await ocean.utils.agreements.signServiceAgreement(
ddo, ddo,
serviceDefinitionId, serviceDefinitionId,
agreementId, agreementId,
[`0x${"1".repeat(64)}`, `0x${"2".repeat(64)}`, `0x${"3".repeat(64)}`], [
consumer, `0x${'1'.repeat(64)}`,
`0x${'2'.repeat(64)}`,
`0x${'3'.repeat(64)}`
],
consumer
) )
assert.equal( assert.equal(
signature, signature,
// tslint:disable-next-line // tslint:disable-next-line
"0x3aa8a1c48b8e582d694bbd4ba3a29fde573b78da9720dc48baeb831b2163e1fa6e10e983882ebf8a00f4124de2505136354fd146934053f0d58bba4eced5f8d000", '0x3aa8a1c48b8e582d694bbd4ba3a29fde573b78da9720dc48baeb831b2163e1fa6e10e983882ebf8a00f4124de2505136354fd146934053f0d58bba4eced5f8d000',
"The signatuere is not correct.", 'The signatuere is not correct.'
) )
}) })
}) })

View File

@ -1,24 +1,27 @@
import { assert } from "chai" import { assert } from 'chai'
import { config } from "../config" import { config } from '../config'
import { Ocean, OceanPlatformTechStatus } from "../../src" // @oceanprotocol/squid import { Ocean, OceanPlatformTechStatus } from '../../src' // @oceanprotocol/squid
describe("Versions", () => {
describe('Versions', () => {
let ocean: Ocean let ocean: Ocean
before(async () => { before(async () => {
ocean = await Ocean.getInstance(config) ocean = await Ocean.getInstance(config)
}) })
it("should returns the versions", async () => { it('should returns the versions', async () => {
const versions = await ocean.versions.get() const versions = await ocean.versions.get()
assert.equal(versions.aquarius.status, OceanPlatformTechStatus.Working) assert.equal(versions.aquarius.status, OceanPlatformTechStatus.Working)
assert.equal(versions.brizo.status, OceanPlatformTechStatus.Working) assert.equal(versions.brizo.status, OceanPlatformTechStatus.Working)
assert.equal(versions.squid.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
})
}) })
}) })

View File

@ -1,11 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"resolveJsonModule": true, "resolveJsonModule": true,
"lib": [ "lib": ["es6", "es7", "dom"],
"es6",
"es7",
"dom"
],
"noUnusedLocals": true "noUnusedLocals": true
} }
} }

View File

@ -1,51 +1,55 @@
import { MetaData } from "../../src" // @oceanprotocol/squid import { MetaData } from '../../src' // @oceanprotocol/squid
const metadata: Partial<MetaData> = { const metadata: Partial<MetaData> = {
base: { base: {
name: undefined, name: undefined,
type: "dataset", type: 'dataset',
description: "Weather information of UK including temperature and humidity", description:
dateCreated: "2012-10-10T17:00:00Z", 'Weather information of UK including temperature and humidity',
datePublished: "2012-10-10T17:00:00Z", dateCreated: '2012-10-10T17:00:00Z',
author: "Met Office", datePublished: '2012-10-10T17:00:00Z',
license: "CC-BY", author: 'Met Office',
copyrightHolder: "Met Office", license: 'CC-BY',
workExample: "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68", copyrightHolder: 'Met Office',
workExample:
'423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68',
links: [ links: [
{ {
name: "Sample of Asset Data", name: 'Sample of Asset Data',
type: "sample", type: 'sample',
url: "https://foo.com/sample.csv", url: 'https://foo.com/sample.csv'
}, },
{ {
name: "Data Format Definition", name: 'Data Format Definition',
type: "format", type: 'format',
url: "https://foo.com/sample.csv", url: 'https://foo.com/sample.csv'
}, }
], ],
inLanguage: "en", inLanguage: 'en',
categories: ["Economy", "Data Science"], categories: ['Economy', 'Data Science'],
tags: ["weather", "uk", "2011", "temperature", "humidity"], tags: ['weather', 'uk', '2011', 'temperature', 'humidity'],
price: "21" + "0".repeat(18), price: '21' + '0'.repeat(18),
files: [ files: [
{ {
index: 0, index: 0,
url: "https://raw.githubusercontent.com/oceanprotocol/squid-js/develop/package.json", url:
'https://raw.githubusercontent.com/oceanprotocol/squid-js/develop/package.json'
}, },
{ {
index: 1, index: 1,
url: "https://raw.githubusercontent.com/oceanprotocol/squid-js/develop/README.md", url:
}, 'https://raw.githubusercontent.com/oceanprotocol/squid-js/develop/README.md'
], }
}, ]
}
} }
export const generateMetadata = (name: string): Partial<MetaData> => ({ export const generateMetadata = (name: string): Partial<MetaData> => ({
...metadata, ...metadata,
base: { base: {
...metadata.base, ...metadata.base,
name, name
}, }
}) })
export const getMetadata = () => generateMetadata("TestAsset") export const getMetadata = () => generateMetadata('TestAsset')

View File

@ -1 +1 @@
export * from "./ddo-metadata-generator" export * from './ddo-metadata-generator'

View File

@ -1,14 +1,19 @@
#!/usr/bin/env node #!/usr/bin/env node
'use strict'; 'use strict'
const packageInfo = require('../package.json'); const packageInfo = require('../package.json')
const execSync = require('child_process').execSync; const execSync = require('child_process').execSync
process.stdout.write( process.stdout.write(
JSON JSON.stringify(
.stringify({ {
version: require('../package.json').version, version: require('../package.json').version,
commit: execSync(`git rev-parse HEAD`).toString().trim(), commit: execSync(`git rev-parse HEAD`)
}, null, ' ') .toString()
); .trim()
},
null,
' '
)
)

View File

@ -1,8 +1,8 @@
import * as Web3 from "web3" import * as Web3 from 'web3'
import Config from "./models/Config" import Config from './models/Config'
import { Logger, LoggerInstance, LogLevel } from "./utils" import { Logger, LoggerInstance, LogLevel } from './utils'
import Web3Provider from "./keeper/Web3Provider" import Web3Provider from './keeper/Web3Provider'
import { Ocean } from "./ocean/Ocean" import { Ocean } from './ocean/Ocean'
export interface InstantiableConfig { export interface InstantiableConfig {
ocean: Ocean ocean: Ocean
@ -11,30 +11,34 @@ export interface InstantiableConfig {
logger?: Logger logger?: Logger
} }
export function generateIntantiableConfigFromConfig(config: Config): Partial<InstantiableConfig> { export function generateIntantiableConfigFromConfig(
const logLevel = typeof config.verbose !== "number" config: Config
? (config.verbose ? LogLevel.Log : LogLevel.None) ): Partial<InstantiableConfig> {
: config.verbose as LogLevel const logLevel =
typeof config.verbose !== 'number'
? config.verbose
? LogLevel.Log
: LogLevel.None
: (config.verbose as LogLevel)
return { return {
config, config,
web3: Web3Provider.getWeb3(config), web3: Web3Provider.getWeb3(config),
logger: new Logger(logLevel), logger: new Logger(logLevel)
} }
} }
export abstract class Instantiable { export abstract class Instantiable {
protected get ocean() { protected get ocean() {
if (!this._ocean) { if (!this._ocean) {
this.logger.error("Ocean instance is not defined.") this.logger.error('Ocean instance is not defined.')
} }
return this._ocean return this._ocean
} }
protected get web3() { protected get web3() {
if (!this._web3) { if (!this._web3) {
this.logger.error("Web3 instance is not defined.") this.logger.error('Web3 instance is not defined.')
this.logger.error("Using default instance.") this.logger.error('Using default instance.')
return Web3Provider.getWeb3() return Web3Provider.getWeb3()
} }
return this._web3 return this._web3
@ -42,31 +46,36 @@ export abstract class Instantiable {
protected get config() { protected get config() {
if (!this._config) { if (!this._config) {
this.logger.error("Config instance is not defined.") this.logger.error('Config instance is not defined.')
} }
return this._config return this._config
} }
protected get logger() { protected get logger() {
if (!this._logger) { if (!this._logger) {
LoggerInstance.error("Logger instance is not defined.") LoggerInstance.error('Logger instance is not defined.')
LoggerInstance.error("Using default instance.") LoggerInstance.error('Using default instance.')
return LoggerInstance return LoggerInstance
} }
return this._logger return this._logger
} }
protected get instanceConfig(): InstantiableConfig { protected get instanceConfig(): InstantiableConfig {
const {ocean, web3, config, logger} = this const { ocean, web3, config, logger } = this
return {ocean, web3, config, logger} return { ocean, web3, config, logger }
} }
public static async getInstance(...args: any[]): Promise<any> public static async getInstance(...args: any[]): Promise<any>
public static async getInstance(config: InstantiableConfig): Promise<any> { public static async getInstance(config: InstantiableConfig): Promise<any> {
LoggerInstance.warn("getInstance() methods has needs to be added to child class.") LoggerInstance.warn(
'getInstance() methods has needs to be added to child class.'
)
} }
protected static setInstanceConfig<T extends Instantiable>(instance: T, {ocean, config, web3, logger}: InstantiableConfig) { protected static setInstanceConfig<T extends Instantiable>(
instance: T,
{ ocean, config, web3, logger }: InstantiableConfig
) {
instance._ocean = ocean instance._ocean = ocean
instance._config = config instance._config = config
instance._web3 = web3 instance._web3 = web3

View File

@ -1,9 +1,9 @@
import { URL } from "whatwg-url" import { URL } from 'whatwg-url'
import { DDO } from "../ddo/DDO" import { DDO } from '../ddo/DDO'
import DID from "../ocean/DID" import DID from '../ocean/DID'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
const apiPath = "/api/v1/aquarius/assets/ddo" const apiPath = '/api/v1/aquarius/assets/ddo'
export interface QueryResult { export interface QueryResult {
results: DDO[] results: DDO[]
@ -16,8 +16,8 @@ export interface SearchQuery {
text?: string text?: string
offset?: number offset?: number
page?: number page?: number
query: {[property: string]: string | number | string[] | number[]} query: { [property: string]: string | number | string[] | number[] }
sort?: {[jsonPath: string]: number} sort?: { [jsonPath: string]: number }
} }
/** /**
@ -40,20 +40,33 @@ export class Aquarius extends Instantiable {
public async getAccessUrl(accessToken: any, payload: any): Promise<string> { public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
const accessUrl: string = await this.ocean.utils.fetch const accessUrl: string = await this.ocean.utils.fetch
.post(`${accessToken.service_endpoint}/${accessToken.resource_id}`, payload) .post(
`${accessToken.service_endpoint}/${accessToken.resource_id}`,
payload
)
.then((response: any): string => { .then((response: any): string => {
if (response.ok) { if (response.ok) {
return response.text() return response.text()
} }
this.logger.error("Failed: ", response.status, response.statusText) this.logger.error(
'Failed: ',
response.status,
response.statusText
)
return null return null
}) })
.then((consumptionUrl: string): string => { .then((consumptionUrl: string): string => {
this.logger.error("Success accessing consume endpoint: ", consumptionUrl) this.logger.error(
'Success accessing consume endpoint: ',
consumptionUrl
)
return consumptionUrl return consumptionUrl
}) })
.catch((error) => { .catch(error => {
this.logger.error("Error fetching the data asset consumption url: ", error) this.logger.error(
'Error fetching the data asset consumption url: ',
error
)
return null return null
}) })
@ -72,14 +85,18 @@ export class Aquarius extends Instantiable {
if (response.ok) { if (response.ok) {
return response.json() as DDO[] return response.json() as DDO[]
} }
this.logger.error("queryMetadata failed:", response.status, response.statusText) this.logger.error(
'queryMetadata failed:',
response.status,
response.statusText
)
return this.transformResult() return this.transformResult()
}) })
.then((results) => { .then(results => {
return this.transformResult(results) return this.transformResult(results)
}) })
.catch((error) => { .catch(error => {
this.logger.error("Error fetching querying metadata: ", error) this.logger.error('Error fetching querying metadata: ', error)
return this.transformResult() return this.transformResult()
}) })
@ -93,24 +110,34 @@ export class Aquarius extends Instantiable {
*/ */
public async queryMetadataByText(query: SearchQuery): Promise<QueryResult> { public async queryMetadataByText(query: SearchQuery): Promise<QueryResult> {
const fullUrl = new URL(`${this.url}${apiPath}/query`) const fullUrl = new URL(`${this.url}${apiPath}/query`)
fullUrl.searchParams.append("text", query.text) fullUrl.searchParams.append('text', query.text)
fullUrl.searchParams.append("sort", decodeURIComponent(JSON.stringify(query.sort))) fullUrl.searchParams.append(
fullUrl.searchParams.append("offset", query.offset.toString()) 'sort',
fullUrl.searchParams.append("page", query.page.toString()) decodeURIComponent(JSON.stringify(query.sort))
)
fullUrl.searchParams.append('offset', query.offset.toString())
fullUrl.searchParams.append('page', query.page.toString())
const result: QueryResult = await this.ocean.utils.fetch const result: QueryResult = await this.ocean.utils.fetch
.get(fullUrl) .get(fullUrl)
.then((response: any) => { .then((response: any) => {
if (response.ok) { if (response.ok) {
return response.json() as DDO[] return response.json() as DDO[]
} }
this.logger.log("queryMetadataByText failed:", response.status, response.statusText) this.logger.log(
'queryMetadataByText failed:',
response.status,
response.statusText
)
return this.transformResult() return this.transformResult()
}) })
.then((results) => { .then(results => {
return this.transformResult(results) return this.transformResult(results)
}) })
.catch((error) => { .catch(error => {
this.logger.error("Error fetching querying metadata by text: ", error) this.logger.error(
'Error fetching querying metadata by text: ',
error
)
return this.transformResult() return this.transformResult()
}) })
@ -130,14 +157,19 @@ export class Aquarius extends Instantiable {
if (response.ok) { if (response.ok) {
return response.json() return response.json()
} }
this.logger.error("storeDDO failed:", response.status, response.statusText, ddo) this.logger.error(
'storeDDO failed:',
response.status,
response.statusText,
ddo
)
return null as DDO return null as DDO
}) })
.then((response: DDO) => { .then((response: DDO) => {
return new DDO(response) as DDO return new DDO(response) as DDO
}) })
.catch((error) => { .catch(error => {
this.logger.error("Error fetching querying metadata: ", error) this.logger.error('Error fetching querying metadata: ', error)
return null as DDO return null as DDO
}) })
@ -157,14 +189,19 @@ export class Aquarius extends Instantiable {
if (response.ok) { if (response.ok) {
return response.json() return response.json()
} }
this.logger.log("retrieveDDO failed:", response.status, response.statusText, did) this.logger.log(
'retrieveDDO failed:',
response.status,
response.statusText,
did
)
return null as DDO return null as DDO
}) })
.then((response: DDO) => { .then((response: DDO) => {
return new DDO(response) as DDO return new DDO(response) as DDO
}) })
.catch((error) => { .catch(error => {
this.logger.error("Error fetching querying metadata: ", error) this.logger.error('Error fetching querying metadata: ', error)
return null as DDO return null as DDO
}) })
@ -176,14 +213,18 @@ export class Aquarius extends Instantiable {
} }
private transformResult( private transformResult(
{results, page, total_pages, total_results}: any = {result: [], page: 0, total_pages: 0, total_results: 0}, { results, page, total_pages, total_results }: any = {
result: [],
page: 0,
total_pages: 0,
total_results: 0
}
): QueryResult { ): QueryResult {
return { return {
results: (results || []).map((ddo) => new DDO(ddo as DDO)), results: (results || []).map(ddo => new DDO(ddo as DDO)),
page, page,
totalPages: total_pages, totalPages: total_pages,
totalResults: total_results, totalResults: total_results
} }
} }
} }

View File

@ -1,18 +1,18 @@
import * as fs from "fs" import * as fs from 'fs'
import save = require("save-file")
import { File } from "../ddo/MetaData" import { File } from '../ddo/MetaData'
import Account from "../ocean/Account" import Account from '../ocean/Account'
import { noZeroX } from "../utils" import { noZeroX } from '../utils'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import save = require('save-file')
const apiPath = "/api/v1/brizo/services" const apiPath = '/api/v1/brizo/services'
/** /**
* Provides a interface with Brizo. * Provides a interface with Brizo.
* Brizo is the technical component executed by the Publishers allowing to them to provide extended data services. * Brizo is the technical component executed by the Publishers allowing to them to provide extended data services.
*/ */
export class Brizo extends Instantiable { export class Brizo extends Instantiable {
private get url() { private get url() {
return this.config.brizoUri return this.config.brizoUri
} }
@ -38,7 +38,12 @@ export class Brizo extends Instantiable {
return `${this.url}${apiPath}/publish` return `${this.url}${apiPath}/publish`
} }
public getComputeEndpoint(pubKey: string, serviceId: string, algo: string, container: string) { public getComputeEndpoint(
pubKey: string,
serviceId: string,
algo: string,
container: string
) {
// tslint:disable-next-line // tslint:disable-next-line
return `${this.url}${apiPath}/compute` return `${this.url}${apiPath}/compute`
} }
@ -48,26 +53,24 @@ export class Brizo extends Instantiable {
serviceAgreementId: string, serviceAgreementId: string,
serviceDefinitionId: string, serviceDefinitionId: string,
signature: string, signature: string,
consumerAddress: string, consumerAddress: string
): Promise<any> { ): Promise<any> {
const args = { const args = {
did, did,
serviceAgreementId, serviceAgreementId,
serviceDefinitionId, serviceDefinitionId,
signature, signature,
consumerAddress, consumerAddress
} }
try { try {
return await this.ocean.utils.fetch return await this.ocean.utils.fetch.post(
.post( this.getPurchaseEndpoint(),
this.getPurchaseEndpoint(), decodeURI(JSON.stringify(args))
decodeURI(JSON.stringify(args)), )
)
} catch (e) { } catch (e) {
this.logger.error(e) this.logger.error(e)
throw new Error("HTTP request failed") throw new Error('HTTP request failed')
} }
} }
@ -77,12 +80,17 @@ export class Brizo extends Instantiable {
account: Account, account: Account,
files: File[], files: File[],
destination: string, destination: string,
index: number = -1, index: number = -1
): Promise<string> { ): Promise<string> {
const signature = await account.getToken() || await this.ocean.utils.signature.signText(noZeroX(agreementId), account.getId()) const signature =
(await account.getToken()) ||
(await this.ocean.utils.signature.signText(
noZeroX(agreementId),
account.getId()
))
const filesPromises = files const filesPromises = files
.filter(({}, i) => index === -1 || i === index) .filter(({}, i) => index === -1 || i === index)
.map(async ({index: i}) => { .map(async ({ index: i }) => {
let consumeUrl = serviceEndpoint let consumeUrl = serviceEndpoint
consumeUrl += `?index=${i}` consumeUrl += `?index=${i}`
consumeUrl += `&serviceAgreementId=${noZeroX(agreementId)}` consumeUrl += `&serviceAgreementId=${noZeroX(agreementId)}`
@ -90,12 +98,9 @@ export class Brizo extends Instantiable {
consumeUrl += `&signature=${signature}` consumeUrl += `&signature=${signature}`
try { try {
await this.downloadFile( await this.downloadFile(consumeUrl, destination)
consumeUrl,
destination,
)
} catch (e) { } catch (e) {
this.logger.error("Error consuming assets") this.logger.error('Error consuming assets')
this.logger.error(e) this.logger.error(e)
throw e throw e
} }
@ -108,52 +113,56 @@ export class Brizo extends Instantiable {
did: string, did: string,
signature: string, signature: string,
document: any, document: any,
publisher: string, publisher: string
): Promise<string> { ): Promise<string> {
const args = { const args = {
documentId: did, documentId: did,
signature, signature,
document: JSON.stringify(document), document: JSON.stringify(document),
publisherAddress: publisher, publisherAddress: publisher
} }
try { try {
const response = await this.ocean.utils.fetch const response = await this.ocean.utils.fetch.post(
.post( this.getEncryptEndpoint(),
this.getEncryptEndpoint(), decodeURI(JSON.stringify(args))
decodeURI(JSON.stringify(args)), )
)
if (!response.ok) { if (!response.ok) {
throw new Error("HTTP request failed") throw new Error('HTTP request failed')
} }
return await response.text() return await response.text()
} catch (e) { } catch (e) {
this.logger.error(e) this.logger.error(e)
throw new Error("HTTP request failed") throw new Error('HTTP request failed')
} }
} }
private async downloadFile(url: string, destination?: string): Promise<string> { private async downloadFile(
const response = await this.ocean.utils.fetch url: string,
.get(url) destination?: string
): Promise<string> {
const response = await this.ocean.utils.fetch.get(url)
if (!response.ok) { if (!response.ok) {
throw new Error("Response error.") throw new Error('Response error.')
} }
let filename let filename
try { try {
filename = response.headers.get("content-disposition").match(/attachment;filename=(.+)/)[1] filename = response.headers
.get('content-disposition')
.match(/attachment;filename=(.+)/)[1]
} catch { } catch {
throw new Error("Response is not containing file name.") throw new Error('Response is not containing file name.')
} }
if (destination) { if (destination) {
await new Promise(async (resolve, reject) => { await new Promise(async (resolve, reject) => {
fs.mkdirSync(destination, {recursive: true}) fs.mkdirSync(destination, { recursive: true })
const fileStream = fs.createWriteStream(`${destination}${filename}`) const fileStream = fs.createWriteStream(
`${destination}${filename}`
)
response.body.pipe(fileStream) response.body.pipe(fileStream)
response.body.on("error", reject) response.body.on('error', reject)
fileStream.on("finish", resolve) fileStream.on('finish', resolve)
}) })
return destination return destination

View File

@ -1,18 +1,17 @@
import * as Web3 from "web3" import * as Web3 from 'web3'
import Web3Provider from "../keeper/Web3Provider" import Web3Provider from '../keeper/Web3Provider'
import LoggerInstance from "../utils/Logger" import LoggerInstance from '../utils/Logger'
import { Ocean } from "../ocean/Ocean" import { Ocean } from '../ocean/Ocean'
import { Authentication } from "./Authentication" import { Authentication } from './Authentication'
import { Proof } from "./Proof" import { Proof } from './Proof'
import { PublicKey } from "./PublicKey" import { PublicKey } from './PublicKey'
import { Service, ServiceType } from "./Service" import { Service, ServiceType } from './Service'
/** /**
* DID Descriptor Object. * DID Descriptor Object.
* Contains all the data related to an asset. * Contains all the data related to an asset.
*/ */
export class DDO { export class DDO {
/** /**
* Serializes the DDO object. * Serializes the DDO object.
* @param {DDO} DDO to be serialized. * @param {DDO} DDO to be serialized.
@ -33,7 +32,7 @@ export class DDO {
return new DDO(ddo) return new DDO(ddo)
} }
public "@context": string = "https://w3id.org/did/v1" public '@context': string = 'https://w3id.org/did/v1'
/** /**
* DID, descentralized ID. * DID, descentralized ID.
@ -48,12 +47,14 @@ export class DDO {
public constructor(ddo: Partial<DDO> = {}) { public constructor(ddo: Partial<DDO> = {}) {
Object.assign(this, ddo, { Object.assign(this, ddo, {
created: (ddo && ddo.created) || new Date().toISOString().replace(/\.[0-9]{3}/, ""), created:
(ddo && ddo.created) ||
new Date().toISOString().replace(/\.[0-9]{3}/, '')
}) })
} }
public shortId(): string { public shortId(): string {
return this.id.replace("did:op:", "") return this.id.replace('did:op:', '')
} }
/** /**
@ -61,12 +62,16 @@ export class DDO {
* @param {string} serviceDefinitionId Service ID. * @param {string} serviceDefinitionId Service ID.
* @return {Service} Service. * @return {Service} Service.
*/ */
public findServiceById<T extends ServiceType>(serviceDefinitionId: string): Service<T> { public findServiceById<T extends ServiceType>(
serviceDefinitionId: string
): Service<T> {
if (!serviceDefinitionId) { if (!serviceDefinitionId) {
throw new Error("serviceDefinitionId not set") throw new Error('serviceDefinitionId not set')
} }
const service = this.service.find((s) => s.serviceDefinitionId === serviceDefinitionId) const service = this.service.find(
s => s.serviceDefinitionId === serviceDefinitionId
)
return service as Service<T> return service as Service<T>
} }
@ -76,12 +81,14 @@ export class DDO {
* @param {string} serviceType Service type. * @param {string} serviceType Service type.
* @return {Service} Service. * @return {Service} Service.
*/ */
public findServiceByType<T extends ServiceType>(serviceType: T): Service<T> { public findServiceByType<T extends ServiceType>(
serviceType: T
): Service<T> {
if (!serviceType) { if (!serviceType) {
throw new Error("serviceType not set") throw new Error('serviceType not set')
} }
return this.service.find((s) => s.type === serviceType) as Service<T> return this.service.find(s => s.type === serviceType) as Service<T>
} }
/** /**
@ -89,20 +96,20 @@ export class DDO {
* @return {string[]} DDO checksum. * @return {string[]} DDO checksum.
*/ */
public getChecksum(): string { public getChecksum(): string {
const {metadata} = this.findServiceByType("Metadata") const { metadata } = this.findServiceByType('Metadata')
const {files, name, author, license} = metadata.base const { files, name, author, license } = metadata.base
const values = [ const values = [
...(files || []) ...(files || []).map(({ checksum }) => checksum).filter(_ => !!_),
.map(({checksum}) => checksum)
.filter((_) => !!_),
name, name,
author, author,
license, license,
this.id, this.id
] ]
return Web3Provider.getWeb3().utils.sha3(values.join("")).replace(/^0x([a-f0-9]{64})(:!.+)?$/i, "0x$1") return Web3Provider.getWeb3()
.utils.sha3(values.join(''))
.replace(/^0x([a-f0-9]{64})(:!.+)?$/i, '0x$1')
} }
/** /**
@ -112,16 +119,24 @@ export class DDO {
* @param {string} password Password if it's requirted. * @param {string} password Password if it's requirted.
* @return {Promise<Proof>} Proof object. * @return {Promise<Proof>} Proof object.
*/ */
public async generateProof(ocean: Ocean, publicKey: string, password?: string): Promise<Proof> { public async generateProof(
ocean: Ocean,
publicKey: string,
password?: string
): Promise<Proof> {
const checksum = this.getChecksum() const checksum = this.getChecksum()
const signature = await ocean.utils.signature.signText(checksum, publicKey, password) const signature = await ocean.utils.signature.signText(
checksum,
publicKey,
password
)
return { return {
created: new Date().toISOString().replace(/\.[0-9]{3}/, ""), created: new Date().toISOString().replace(/\.[0-9]{3}/, ''),
creator: publicKey, creator: publicKey,
type: "DDOIntegritySignature", type: 'DDOIntegritySignature',
signatureValue: signature, signatureValue: signature
} }
} }
@ -129,9 +144,9 @@ export class DDO {
* Generated and adds the checksum. * Generated and adds the checksum.
*/ */
public addChecksum(): void { public addChecksum(): void {
const metadataService = this.findServiceByType("Metadata") const metadataService = this.findServiceByType('Metadata')
if (metadataService.metadata.base.checksum) { if (metadataService.metadata.base.checksum) {
LoggerInstance.log("Checksum already exists") LoggerInstance.log('Checksum already exists')
return return
} }
metadataService.metadata.base.checksum = this.getChecksum() metadataService.metadata.base.checksum = this.getChecksum()
@ -144,9 +159,13 @@ export class DDO {
* @param {string} password Password if it's requirted. * @param {string} password Password if it's requirted.
* @return {Promise<Proof>} Proof object. * @return {Promise<Proof>} Proof object.
*/ */
public async addProof(web3: Web3, publicKey: string, password?: string): Promise<void> { public async addProof(
web3: Web3,
publicKey: string,
password?: string
): Promise<void> {
if (this.proof) { if (this.proof) {
throw new Error("Proof already exists") throw new Error('Proof already exists')
} }
this.proof = await this.generateProof(web3, publicKey, password) this.proof = await this.generateProof(web3, publicKey, password)
} }

View File

@ -62,7 +62,6 @@ export interface File {
* @see https://github.com/oceanprotocol/OEPs/tree/master/8#base-attributes * @see https://github.com/oceanprotocol/OEPs/tree/master/8#base-attributes
*/ */
export interface MetaDataBase { export interface MetaDataBase {
/** /**
* Descriptive name of the Asset. * Descriptive name of the Asset.
* @type {string} * @type {string}
@ -76,7 +75,7 @@ export interface MetaDataBase {
* @type {string} * @type {string}
* @example "dataset" * @example "dataset"
*/ */
type: "dataset" | "algorithm" | "container" | "workflow" | "other" type: 'dataset' | 'algorithm' | 'container' | 'workflow' | 'other'
/** /**
* Details of what the resource is. For a dataset, this attribute * Details of what the resource is. For a dataset, this attribute
@ -150,7 +149,7 @@ export interface MetaDataBase {
* }, * },
* ] * ]
*/ */
links?: Array<{[name: string]: string}> links?: Array<{ [name: string]: string }>
/** /**
* The language of the content. Please use one of the language * The language of the content. Please use one of the language
@ -244,7 +243,7 @@ export interface AdditionalInformation {
*/ */
structuredMarkup: Array<{ structuredMarkup: Array<{
uri: string uri: string
mediaType: string, mediaType: string
}> }>
/** /**

View File

@ -13,7 +13,11 @@ export interface PublicKey {
* Type of key. * Type of key.
* @type {string} * @type {string}
*/ */
type: "Ed25519VerificationKey2018" | "RsaVerificationKey2018" | "EdDsaSAPublicKeySecp256k1" | "EthereumECDSAKey" type:
| 'Ed25519VerificationKey2018'
| 'RsaVerificationKey2018'
| 'EdDsaSAPublicKeySecp256k1'
| 'EthereumECDSAKey'
/** /**
* Key owner. * Key owner.

View File

@ -1,7 +1,12 @@
import { MetaData } from "./MetaData" import { MetaData } from './MetaData'
import { ServiceAgreementTemplate } from "./ServiceAgreementTemplate" import { ServiceAgreementTemplate } from './ServiceAgreementTemplate'
export type ServiceType = "Authorization" | "Metadata" | "Access" | "Compute" | "FitchainCompute" export type ServiceType =
| 'Authorization'
| 'Metadata'
| 'Access'
| 'Compute'
| 'FitchainCompute'
export interface ServiceCommon { export interface ServiceCommon {
type: ServiceType type: ServiceType
@ -10,18 +15,18 @@ export interface ServiceCommon {
} }
export interface ServiceAuthorization extends ServiceCommon { export interface ServiceAuthorization extends ServiceCommon {
type: "Authorization" type: 'Authorization'
service: "SecretStore" | "None" | "RSAES-OAEP" service: 'SecretStore' | 'None' | 'RSAES-OAEP'
} }
export interface ServiceMetadata extends ServiceCommon { export interface ServiceMetadata extends ServiceCommon {
type: "Metadata" type: 'Metadata'
metadata: MetaData metadata: MetaData
} }
export interface ServiceAccess extends ServiceCommon { export interface ServiceAccess extends ServiceCommon {
type: "Access" type: 'Access'
name?: string, name?: string
description?: string description?: string
creator?: string creator?: string
templateId?: string templateId?: string
@ -33,10 +38,16 @@ export interface ServiceCompute extends ServiceCommon {
templateId?: string templateId?: string
} }
export type Service<T extends ServiceType | "default" = "default"> = export type Service<
T extends "Authorization" ? ServiceAuthorization : T extends ServiceType | 'default' = 'default'
T extends "Metadata" ? ServiceMetadata : > = T extends 'Authorization'
T extends "Access" ? ServiceAccess : ? ServiceAuthorization
T extends "Compute" ? ServiceCompute : : T extends 'Metadata'
T extends "default" ? ServiceCommon : ? ServiceMetadata
ServiceCommon : T extends 'Access'
? ServiceAccess
: T extends 'Compute'
? ServiceCompute
: T extends 'default'
? ServiceCommon
: ServiceCommon

View File

@ -10,7 +10,7 @@ export interface ServiceAgreementTemplateEvent {
handler: { handler: {
moduleName: string moduleName: string
functionName: string functionName: string
version: string, version: string
} }
} }
@ -28,6 +28,6 @@ export interface ServiceAgreementTemplate {
contractName: string contractName: string
events: ServiceAgreementTemplateEvent[] events: ServiceAgreementTemplateEvent[]
fulfillmentOrder: string[] fulfillmentOrder: string[]
conditionDependency: {[condition: string]: string[]} conditionDependency: { [condition: string]: string[] }
conditions: ServiceAgreementTemplateCondition[] conditions: ServiceAgreementTemplateCondition[]
} }

View File

@ -1 +1 @@
export * from "./squid" export * from './squid'

View File

@ -1,4 +1,4 @@
import ContractBase from "./contracts/ContractBase" import ContractBase from './contracts/ContractBase'
interface EventEmitter { interface EventEmitter {
// tslint:disable-next-line // tslint:disable-next-line
@ -16,15 +16,17 @@ export class ContractEvent {
private eventEmitter: EventEmitter, private eventEmitter: EventEmitter,
private contract: ContractBase, private contract: ContractBase,
private eventName: string, private eventName: string,
private filter: {[key: string]: any}, private filter: { [key: string]: any }
) { } ) {}
public subscribe(callback: (events: any[]) => void): ContractEventSubscription { public subscribe(
const onEvent = async (blockNumber) => { callback: (events: any[]) => void
): ContractEventSubscription {
const onEvent = async blockNumber => {
const events = await this.contract.getEventData(this.eventName, { const events = await this.contract.getEventData(this.eventName, {
filter: this.filter, filter: this.filter,
fromBlock: blockNumber, fromBlock: blockNumber,
toBlock: "latest", toBlock: 'latest'
}) })
if (events.length) { if (events.length) {
callback(events) callback(events)
@ -33,13 +35,13 @@ export class ContractEvent {
this.eventEmitter.subscribe(onEvent) this.eventEmitter.subscribe(onEvent)
return { return {
unsubscribe: () => this.eventEmitter.unsubscribe(onEvent), unsubscribe: () => this.eventEmitter.unsubscribe(onEvent)
} }
} }
public once(callback?: (events: any[]) => void) { public once(callback?: (events: any[]) => void) {
return new Promise((resolve) => { return new Promise(resolve => {
const subscription = this.subscribe((events) => { const subscription = this.subscribe(events => {
subscription.unsubscribe() subscription.unsubscribe()
if (callback) { if (callback) {
callback(events) callback(events)

View File

@ -1,21 +1,30 @@
import { Contract } from "web3-eth-contract" import { Contract } from 'web3-eth-contract'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
export default class ContractHandler extends Instantiable { export default class ContractHandler extends Instantiable {
protected static getContract(what: string, networkId: number) { protected static getContract(what: string, networkId: number) {
return ContractHandler.contracts.get(this.getHash(what, networkId)) return ContractHandler.contracts.get(this.getHash(what, networkId))
} }
protected static setContract(what: string, networkId: number, contractInstance: Contract) { protected static setContract(
ContractHandler.contracts.set(this.getHash(what, networkId), contractInstance) what: string,
networkId: number,
contractInstance: Contract
) {
ContractHandler.contracts.set(
this.getHash(what, networkId),
contractInstance
)
} }
protected static hasContract(what: string, networkId: number): boolean { protected static hasContract(what: string, networkId: number): boolean {
return ContractHandler.contracts.has(this.getHash(what, networkId)) return ContractHandler.contracts.has(this.getHash(what, networkId))
} }
private static contracts: Map<string, Contract> = new Map<string, Contract>() private static contracts: Map<string, Contract> = new Map<
string,
Contract
>()
private static getHash(what: string, networkId: number): string { private static getHash(what: string, networkId: number): string {
return `${what}/#${networkId}` return `${what}/#${networkId}`
@ -30,25 +39,44 @@ export default class ContractHandler extends Instantiable {
const where = (await this.ocean.keeper.getNetworkName()).toLowerCase() const where = (await this.ocean.keeper.getNetworkName()).toLowerCase()
const networkId = await this.ocean.keeper.getNetworkId() const networkId = await this.ocean.keeper.getNetworkId()
try { try {
return ContractHandler.getContract(what, networkId) || await this.load(what, where, networkId) return (
ContractHandler.getContract(what, networkId) ||
(await this.load(what, where, networkId))
)
} catch (err) { } catch (err) {
this.logger.error("Failed to load", what, "from", where, err) this.logger.error('Failed to load', what, 'from', where, err)
throw err throw err
} }
} }
private async load(what: string, where: string, networkId: number): Promise<Contract> { private async load(
this.logger.debug("Loading", what, "from", where) what: string,
where: string,
networkId: number
): Promise<Contract> {
this.logger.debug('Loading', what, 'from', where)
const artifact = require(`@oceanprotocol/keeper-contracts/artifacts/${what}.${where}.json`) const artifact = require(`@oceanprotocol/keeper-contracts/artifacts/${what}.${where}.json`)
// Logger.log('Loaded artifact', artifact) // Logger.log('Loaded artifact', artifact)
const code = await this.web3.eth.getCode(artifact.address) const code = await this.web3.eth.getCode(artifact.address)
if (code === "0x0") { if (code === '0x0') {
// no code in the blockchain dude // no code in the blockchain dude
throw new Error(`No code deployed at address ${artifact.address}, sorry.`) throw new Error(
`No code deployed at address ${artifact.address}, sorry.`
)
} }
const contract = new this.web3.eth.Contract(artifact.abi, artifact.address) const contract = new this.web3.eth.Contract(
artifact.abi,
artifact.address
)
this.logger.debug("Getting instance of", what, "from", where, "at address", artifact.address) this.logger.debug(
'Getting instance of',
what,
'from',
where,
'at address',
artifact.address
)
ContractHandler.setContract(what, networkId, contract) ContractHandler.setContract(what, networkId, contract)
return ContractHandler.getContract(what, networkId) return ContractHandler.getContract(what, networkId)
} }

View File

@ -1,10 +1,9 @@
import { ContractEvent } from "./ContractEvent" import { ContractEvent } from './ContractEvent'
import ContractBase from "./contracts/ContractBase" import ContractBase from './contracts/ContractBase'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
export class EventHandler extends Instantiable { export class EventHandler extends Instantiable {
get count() { get count() {
return this.events.size return this.events.size
} }
@ -24,7 +23,7 @@ export class EventHandler extends Instantiable {
this.checkBlock() this.checkBlock()
return { return {
unsubscribe: () => this.unsubscribe(callback), unsubscribe: () => this.unsubscribe(callback)
} }
} }
@ -37,7 +36,11 @@ export class EventHandler extends Instantiable {
} }
} }
public getEvent(contract: ContractBase, eventName: string, filter: {[key: string]: any}) { public getEvent(
contract: ContractBase,
eventName: string,
filter: { [key: string]: any }
) {
return new ContractEvent(this, contract, eventName, filter) return new ContractEvent(this, contract, eventName, filter)
} }
@ -54,9 +57,12 @@ export class EventHandler extends Instantiable {
} }
if (this.lastBlock !== blockNumber) { if (this.lastBlock !== blockNumber) {
this.events.forEach((fn) => fn(this.lastBlock + 1)) this.events.forEach(fn => fn(this.lastBlock + 1))
this.lastBlock = blockNumber this.lastBlock = blockNumber
} }
this.lastTimeout = global.setTimeout(() => this.checkBlock(true, n++), this.interval) this.lastTimeout = global.setTimeout(
() => this.checkBlock(true, n++),
this.interval
)
} }
} }

View File

@ -1,16 +1,28 @@
import { ContractBase } from "./contracts/ContractBase" import { ContractBase } from './contracts/ContractBase'
import DIDRegistry from "./contracts/DIDRegistry" import DIDRegistry from './contracts/DIDRegistry'
import Dispenser from "./contracts/Dispenser" import Dispenser from './contracts/Dispenser'
import OceanToken from "./contracts/Token" import OceanToken from './contracts/Token'
import { Condition, LockRewardCondition, EscrowReward, AccessSecretStoreCondition } from "./contracts/conditions" import {
import { AgreementTemplate, EscrowAccessSecretStoreTemplate } from "./contracts/templates" Condition,
import { TemplateStoreManager, AgreementStoreManager, ConditionStoreManager } from "./contracts/managers" LockRewardCondition,
EscrowReward,
AccessSecretStoreCondition
} from './contracts/conditions'
import {
AgreementTemplate,
EscrowAccessSecretStoreTemplate
} from './contracts/templates'
import {
TemplateStoreManager,
AgreementStoreManager,
ConditionStoreManager
} from './contracts/managers'
import { objectPromiseAll } from "../utils" import { objectPromiseAll } from '../utils'
import { EventHandler } from "./EventHandler" import { EventHandler } from './EventHandler'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
/** /**
* Interface with Ocean Keeper contracts. * Interface with Ocean Keeper contracts.
@ -20,12 +32,13 @@ import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
* - Marketplace: the core marketplace where people can transact with each other with Ocean tokens. * - Marketplace: the core marketplace where people can transact with each other with Ocean tokens.
*/ */
export class Keeper extends Instantiable { export class Keeper extends Instantiable {
/** /**
* Returns Keeper instance. * Returns Keeper instance.
* @return {Promise<Keeper>} * @return {Promise<Keeper>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<Keeper> { public static async getInstance(
config: InstantiableConfig
): Promise<Keeper> {
const keeper = new Keeper() const keeper = new Keeper()
keeper.setInstanceConfig(config) keeper.setInstanceConfig(config)
@ -41,14 +54,22 @@ export class Keeper extends Instantiable {
didRegistry: DIDRegistry.getInstance(config), didRegistry: DIDRegistry.getInstance(config),
// Managers // Managers
templateStoreManager: TemplateStoreManager.getInstance(config), templateStoreManager: TemplateStoreManager.getInstance(config),
agreementStoreManager: AgreementStoreManager.getInstance(config), agreementStoreManager: AgreementStoreManager.getInstance(
conditionStoreManager: ConditionStoreManager.getInstance(config), config
),
conditionStoreManager: ConditionStoreManager.getInstance(
config
),
// Conditions // Conditions
lockRewardCondition: LockRewardCondition.getInstance(config), lockRewardCondition: LockRewardCondition.getInstance(config),
escrowReward: EscrowReward.getInstance(config), escrowReward: EscrowReward.getInstance(config),
accessSecretStoreCondition: AccessSecretStoreCondition.getInstance(config), accessSecretStoreCondition: AccessSecretStoreCondition.getInstance(
config
),
// Templates // Templates
escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate.getInstance(config), escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate.getInstance(
config
)
}) })
keeper.connected = true keeper.connected = true
@ -69,16 +90,18 @@ export class Keeper extends Instantiable {
keeper.conditions = { keeper.conditions = {
lockRewardCondition: keeper.instances.lockRewardCondition, lockRewardCondition: keeper.instances.lockRewardCondition,
escrowReward: keeper.instances.escrowReward, escrowReward: keeper.instances.escrowReward,
accessSecretStoreCondition: keeper.instances.accessSecretStoreCondition, accessSecretStoreCondition:
keeper.instances.accessSecretStoreCondition
} }
// Conditions // Conditions
keeper.templates = { keeper.templates = {
escrowAccessSecretStoreTemplate: keeper.instances.escrowAccessSecretStoreTemplate, escrowAccessSecretStoreTemplate:
keeper.instances.escrowAccessSecretStoreTemplate
} }
// Utils // Utils
keeper.utils = { keeper.utils = {
eventHandler: new EventHandler(config), eventHandler: new EventHandler(config)
} }
return keeper return keeper
@ -130,26 +153,26 @@ export class Keeper extends Instantiable {
* Conditions instances. * Conditions instances.
*/ */
public conditions: { public conditions: {
lockRewardCondition: LockRewardCondition, lockRewardCondition: LockRewardCondition
escrowReward: EscrowReward, escrowReward: EscrowReward
accessSecretStoreCondition: AccessSecretStoreCondition, accessSecretStoreCondition: AccessSecretStoreCondition
} }
/** /**
* Templates instances. * Templates instances.
*/ */
public templates: { public templates: {
escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate, escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate
} }
/** /**
* Helpers for contracts. * Helpers for contracts.
*/ */
public utils: { public utils: {
eventHandler: EventHandler, eventHandler: EventHandler
} }
private instances: {[contractRef: string]: ContractBase & any} private instances: { [contractRef: string]: ContractBase & any }
/** /**
* Returns a condition by address. * Returns a condition by address.
@ -157,8 +180,9 @@ export class Keeper extends Instantiable {
* @return {Condition} Condition instance. * @return {Condition} Condition instance.
*/ */
public getConditionByAddress(address: string): Condition { public getConditionByAddress(address: string): Condition {
return Object.values(this.conditions) return Object.values(this.conditions).find(
.find((condition) => condition.getAddress() === address) condition => condition.getAddress() === address
)
} }
/** /**
@ -167,8 +191,9 @@ export class Keeper extends Instantiable {
* @return {AgreementTemplate} Agreement template instance. * @return {AgreementTemplate} Agreement template instance.
*/ */
public getTemplateByName(name: string): AgreementTemplate { public getTemplateByName(name: string): AgreementTemplate {
return Object.values(this.templates) return Object.values(this.templates).find(
.find((template) => template.contractName === name) template => template.contractName === name
)
} }
/** /**
@ -177,8 +202,9 @@ export class Keeper extends Instantiable {
* @return {AgreementTemplate} Agreement template instance. * @return {AgreementTemplate} Agreement template instance.
*/ */
public getTemplateByAddress(address: string): AgreementTemplate { public getTemplateByAddress(address: string): AgreementTemplate {
return Object.values(this.templates) return Object.values(this.templates).find(
.find((template) => template.getAddress() === address) template => template.getAddress() === address
)
} }
/** /**
@ -194,22 +220,32 @@ export class Keeper extends Instantiable {
* @return {Promise<string>} Network name. * @return {Promise<string>} Network name.
*/ */
public getNetworkName(): Promise<string> { public getNetworkName(): Promise<string> {
return this.web3.eth.net.getId() return this.web3.eth.net.getId().then(networkId => {
.then((networkId) => { switch (networkId) {
switch (networkId) { case 1:
case 1: return "Main" return 'Main'
case 2: return "Morden" case 2:
case 3: return "Ropsten" return 'Morden'
case 4: return "Rinkeby" case 3:
case 77: return "POA_Sokol" return 'Ropsten'
case 99: return "POA_Core" case 4:
case 42: return "Kovan" return 'Rinkeby'
case 2199: return "Duero" case 77:
case 8996: return "Spree" return 'POA_Sokol'
case 8995: return "Nile" case 99:
default: return "Development" return 'POA_Core'
} case 42:
}) return 'Kovan'
case 2199:
return 'Duero'
case 8996:
return 'Spree'
case 8995:
return 'Nile'
default:
return 'Development'
}
})
} }
public getAllInstances() { public getAllInstances() {

View File

@ -1,17 +1,16 @@
import * as Web3 from "web3" import * as Web3 from 'web3'
import Config from "../models/Config" import Config from '../models/Config'
export default class Web3Provider { export default class Web3Provider {
/** /**
* Returns Web3 instance. * Returns Web3 instance.
* @return {Web3} * @return {Web3}
*/ */
public static getWeb3(config: Partial<Config> = {}): Web3 { public static getWeb3(config: Partial<Config> = {}): Web3 {
return new Web3( return new Web3(
config.web3Provider config.web3Provider ||
|| Web3.givenProvider Web3.givenProvider ||
|| new Web3.providers.HttpProvider(config.nodeUri), new Web3.providers.HttpProvider(config.nodeUri)
) )
} }
} }

View File

@ -1,11 +1,10 @@
import { Contract } from "web3-eth-contract" import { Contract } from 'web3-eth-contract'
import { TransactionReceipt } from "web3-core" import { TransactionReceipt } from 'web3-core'
import ContractHandler from "../ContractHandler" import ContractHandler from '../ContractHandler'
import { Instantiable, InstantiableConfig } from "../../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
export abstract class ContractBase extends Instantiable { export abstract class ContractBase extends Instantiable {
protected static instance = null protected static instance = null
public contractName: string public contractName: string
@ -22,16 +21,18 @@ export abstract class ContractBase extends Instantiable {
public async getEventData(eventName: string, options: any) { public async getEventData(eventName: string, options: any) {
if (!this.contract.events[eventName]) { 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) return this.contract.getPastEvents(eventName, options)
} }
public getPastEvents(eventName: string, filter: {[key: string]: any}) { public getPastEvents(eventName: string, filter: { [key: string]: any }) {
return this.getEventData(eventName, { return this.getEventData(eventName, {
filter, filter,
fromBlock: 0, fromBlock: 0,
toBlock: "latest", toBlock: 'latest'
}) })
} }
@ -62,72 +63,110 @@ export abstract class ContractBase extends Instantiable {
return from return from
} }
protected async sendFrom(name: string, args: any[], from?: string): Promise<TransactionReceipt> { protected async sendFrom(
name: string,
args: any[],
from?: string
): Promise<TransactionReceipt> {
from = await this.getFromAddress(from) from = await this.getFromAddress(from)
return this.send(name, from, args) return this.send(name, from, args)
} }
protected async send(name: string, from: string, args: any[]): Promise<TransactionReceipt> { protected async send(
name: string,
from: string,
args: any[]
): Promise<TransactionReceipt> {
if (!this.contract.methods[name]) { 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}"`
)
} }
// Logger.log(name, args) // Logger.log(name, args)
const method = this.contract.methods[name] const method = this.contract.methods[name]
try { try {
const methodInstance = method(...args) const methodInstance = method(...args)
const estimatedGas = await methodInstance.estimateGas(args, { const estimatedGas = await methodInstance.estimateGas(args, {
from, from
}) })
const tx = methodInstance.send({ const tx = methodInstance.send({
from, from,
gas: estimatedGas, gas: estimatedGas
}) })
return tx return tx
} catch (err) { } catch (err) {
const mappedArgs = this.searchMethod(name, args).inputs.map((input, i) => { const mappedArgs = this.searchMethod(name, args).inputs.map(
return { (input, i) => {
name: input.name, return {
value: args[i], name: input.name,
value: args[i]
}
} }
}) )
this.logger.error("-".repeat(40)) this.logger.error('-'.repeat(40))
this.logger.error(`Sending transaction "${name}" on contract "${this.contractName}" failed.`) this.logger.error(
`Sending transaction "${name}" on contract "${this.contractName}" failed.`
)
this.logger.error(`Error: ${err.message}`) this.logger.error(`Error: ${err.message}`)
this.logger.error(`From: ${from}`) this.logger.error(`From: ${from}`)
this.logger.error(`Parameters: ${JSON.stringify(mappedArgs, null, 2)}`) this.logger.error(
this.logger.error("-".repeat(40)) `Parameters: ${JSON.stringify(mappedArgs, null, 2)}`
)
this.logger.error('-'.repeat(40))
throw err throw err
} }
} }
protected async call<T extends any>(name: string, args: any[], from?: string): Promise<T> { protected async call<T extends any>(
name: string,
args: any[],
from?: string
): Promise<T> {
if (!this.contract.methods[name]) { 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}`
)
} }
// Logger.log(name) // Logger.log(name)
try { try {
const method = this.contract.methods[name](...args) const method = this.contract.methods[name](...args)
return method.call(from ? {from} : null) return method.call(from ? { from } : null)
} catch (err) { } catch (err) {
this.logger.error(`Calling method "${name}" on contract "${this.contractName}" failed. Args: ${args}`, err) this.logger.error(
`Calling method "${name}" on contract "${this.contractName}" failed. Args: ${args}`,
err
)
throw err throw err
} }
} }
protected getEvent(eventName: string, filter: {[key: string]: any}) { protected getEvent(eventName: string, filter: { [key: string]: any }) {
if (!this.contract.events[eventName]) { if (!this.contract.events[eventName]) {
throw new Error(`Event ${eventName} is not part of contract ${this.contractName}`) throw new Error(
`Event ${eventName} is not part of contract ${this.contractName}`
)
} }
return this.ocean.keeper.utils.eventHandler.getEvent(this, eventName, filter) return this.ocean.keeper.utils.eventHandler.getEvent(
this,
eventName,
filter
)
} }
private searchMethod(methodName: string, args: any[] = []) { private searchMethod(methodName: string, args: any[] = []) {
const methods = this.contract.options.jsonInterface const methods = this.contract.options.jsonInterface
.map((method) => ({...method, signature: (method as any).signature})) .map(method => ({
...method,
signature: (method as any).signature
}))
.filter((method: any) => method.name === methodName) .filter((method: any) => method.name === methodName)
const foundMethod = methods.find(({inputs}) => inputs.length === args.length) || methods[0] const foundMethod =
methods.find(({ inputs }) => inputs.length === args.length) ||
methods[0]
if (!foundMethod) { if (!foundMethod) {
throw new Error(`Method "${methodName}" is not part of contract "${this.contractName}"`) throw new Error(
`Method "${methodName}" is not part of contract "${this.contractName}"`
)
} }
return foundMethod return foundMethod
} }

View File

@ -1,35 +1,45 @@
import Web3Provider from "../Web3Provider" import Web3Provider from '../Web3Provider'
import ContractBase from "./ContractBase" import ContractBase from './ContractBase'
import { zeroX, didPrefixed } from "../../utils" import { zeroX, didPrefixed } from '../../utils'
import { InstantiableConfig } from "../../Instantiable.abstract" import { InstantiableConfig } from '../../Instantiable.abstract'
export default class DIDRegistry extends ContractBase { export default class DIDRegistry extends ContractBase {
public static async getInstance(
public static async getInstance(config: InstantiableConfig): Promise<DIDRegistry> { config: InstantiableConfig
const didRegistry: DIDRegistry = new DIDRegistry("DIDRegistry") ): Promise<DIDRegistry> {
const didRegistry: DIDRegistry = new DIDRegistry('DIDRegistry')
await didRegistry.init(config) await didRegistry.init(config)
return didRegistry return didRegistry
} }
public async registerAttribute(did: string, checksum: string, providers: string[], value: string, ownerAddress: string) { public async registerAttribute(
return this.send( did: string,
"registerAttribute", checksum: string,
ownerAddress, providers: string[],
[zeroX(did), zeroX(checksum), providers.map(zeroX), value], value: string,
) ownerAddress: string
) {
return this.send('registerAttribute', ownerAddress, [
zeroX(did),
zeroX(checksum),
providers.map(zeroX),
value
])
} }
public async getDIDOwner(did: string): Promise<string> { public async getDIDOwner(did: string): Promise<string> {
return this.call("getDIDOwner", [zeroX(did)]) return this.call('getDIDOwner', [zeroX(did)])
} }
public async getBlockNumberUpdated(did: string): Promise<number> { public async getBlockNumberUpdated(did: string): Promise<number> {
return +await this.call("getBlockNumberUpdated", [zeroX(did)]) return +(await this.call('getBlockNumberUpdated', [zeroX(did)]))
} }
public async getAttributesByOwner(owner: string): Promise<string[]> { public async getAttributesByOwner(owner: string): Promise<string[]> {
return (await this.getPastEvents("DIDAttributeRegistered", {_owner: zeroX(owner)})) return (await this.getPastEvents('DIDAttributeRegistered', {
.map(({returnValues}) => returnValues._did) _owner: zeroX(owner)
}))
.map(({ returnValues }) => returnValues._did)
.map(didPrefixed) .map(didPrefixed)
} }
} }

View File

@ -1,15 +1,19 @@
import ContractBase from "./ContractBase" import ContractBase from './ContractBase'
import { InstantiableConfig } from "../../Instantiable.abstract" import { InstantiableConfig } from '../../Instantiable.abstract'
export default class Dispenser extends ContractBase { export default class Dispenser extends ContractBase {
public static async getInstance(
public static async getInstance(config: InstantiableConfig): Promise<Dispenser> { config: InstantiableConfig
const dispenser: Dispenser = new Dispenser("Dispenser") ): Promise<Dispenser> {
const dispenser: Dispenser = new Dispenser('Dispenser')
await dispenser.init(config) await dispenser.init(config)
return dispenser return dispenser
} }
public async requestTokens(amount: number | string, receiverAddress: string) { public async requestTokens(
return this.send("requestTokens", receiverAddress, [String(amount)]) amount: number | string,
receiverAddress: string
) {
return this.send('requestTokens', receiverAddress, [String(amount)])
} }
} }

View File

@ -1,9 +1,11 @@
import ContractBase from "./ContractBase" import ContractBase from './ContractBase'
import { InstantiableConfig } from "../../Instantiable.abstract" import { InstantiableConfig } from '../../Instantiable.abstract'
export default class GenericContract extends ContractBase { export default class GenericContract extends ContractBase {
public static async getInstance(
public static async getInstance(config: InstantiableConfig, contractName: string): Promise<ContractBase> { config: InstantiableConfig,
contractName: string
): Promise<ContractBase> {
const contract: GenericContract = new GenericContract(contractName) const contract: GenericContract = new GenericContract(contractName)
await contract.init(config) await contract.init(config)
return contract return contract

View File

@ -1,29 +1,31 @@
import BigNumber from "bignumber.js" import BigNumber from 'bignumber.js'
import ContractBase from "./ContractBase" import ContractBase from './ContractBase'
import { InstantiableConfig } from "../../Instantiable.abstract" import { InstantiableConfig } from '../../Instantiable.abstract'
export default class OceanToken extends ContractBase { export default class OceanToken extends ContractBase {
public static async getInstance(
public static async getInstance(config: InstantiableConfig): Promise<OceanToken> { config: InstantiableConfig
const token: OceanToken = new OceanToken("OceanToken") ): Promise<OceanToken> {
const token: OceanToken = new OceanToken('OceanToken')
await token.init(config) await token.init(config)
return token return token
} }
public async approve(to: string, price: number | string, from?: string) { public async approve(to: string, price: number | string, from?: string) {
return this.sendFrom("approve", [to, String(price)], from) return this.sendFrom('approve', [to, String(price)], from)
} }
public async decimals(): Promise<number> { public async decimals(): Promise<number> {
return this.call("decimals", []) return this.call('decimals', [])
} }
public async balanceOf(address: string): Promise<number> { public async balanceOf(address: string): Promise<number> {
return this.call("balanceOf", [address]) return this.call('balanceOf', [address]).then((balance: string) =>
.then((balance: string) => new BigNumber(balance).toNumber()) new BigNumber(balance).toNumber()
)
} }
public async transfer(to: string, amount: number, from: string) { public async transfer(to: string, amount: number, from: string) {
return this.send("transfer", from, [to, amount]) return this.send('transfer', from, [to, amount])
} }
} }

View File

@ -1,30 +1,51 @@
import { Condition } from "./Condition.abstract" import { Condition } from './Condition.abstract'
import { zeroX, didZeroX, didPrefixed } from "../../../utils" import { zeroX, didZeroX, didPrefixed } from '../../../utils'
import { InstantiableConfig } from "../../../Instantiable.abstract" import { InstantiableConfig } from '../../../Instantiable.abstract'
export class AccessSecretStoreCondition extends Condition { export class AccessSecretStoreCondition extends Condition {
public static async getInstance(
public static async getInstance(config: InstantiableConfig): Promise<AccessSecretStoreCondition> { config: InstantiableConfig
return Condition.getInstance(config, "AccessSecretStoreCondition", AccessSecretStoreCondition) ): Promise<AccessSecretStoreCondition> {
return Condition.getInstance(
config,
'AccessSecretStoreCondition',
AccessSecretStoreCondition
)
} }
public hashValues(did: string, grantee: string) { public hashValues(did: string, grantee: string) {
return super.hashValues(didZeroX(did), zeroX(grantee)) return super.hashValues(didZeroX(did), zeroX(grantee))
} }
public fulfill(agreementId: string, did: string, grantee: string, from?: string) { public fulfill(
return super.fulfill(agreementId, [didZeroX(did), grantee].map(zeroX), from) agreementId: string,
did: string,
grantee: string,
from?: string
) {
return super.fulfill(
agreementId,
[didZeroX(did), grantee].map(zeroX),
from
)
} }
public checkPermissions(grantee: string, did: string, from?: string) { public checkPermissions(grantee: string, did: string, from?: string) {
return this.call<boolean>("checkPermissions", [grantee, didZeroX(did)].map(zeroX), from) return this.call<boolean>(
'checkPermissions',
[grantee, didZeroX(did)].map(zeroX),
from
)
} }
public async getGrantedDidByConsumer(consumer: string): Promise<Array<{did: string, agreementId: string}>> { public async getGrantedDidByConsumer(
return (await this.getPastEvents("Fulfilled", {_grantee: zeroX(consumer)})) consumer: string
.map(({returnValues}) => ({ ): Promise<Array<{ did: string; agreementId: string }>> {
did: didPrefixed(returnValues._documentId), return (await this.getPastEvents('Fulfilled', {
agreementId: zeroX(returnValues._agreementId), _grantee: zeroX(consumer)
})) })).map(({ returnValues }) => ({
did: didPrefixed(returnValues._documentId),
agreementId: zeroX(returnValues._agreementId)
}))
} }
} }

View File

@ -1,19 +1,27 @@
import ContractBase from "../ContractBase" import ContractBase from '../ContractBase'
import { zeroX } from "../../../utils" import { zeroX } from '../../../utils'
import { InstantiableConfig } from "../../../Instantiable.abstract" import { InstantiableConfig } from '../../../Instantiable.abstract'
export enum ConditionState { export enum ConditionState {
Uninitialized = 0, Uninitialized = 0,
Unfulfilled = 1, Unfulfilled = 1,
Fulfilled = 2, Fulfilled = 2,
Aborted = 3, Aborted = 3
} }
export const conditionStateNames = ["Uninitialized", "Unfulfilled", "Fulfilled", "Aborted"] export const conditionStateNames = [
'Uninitialized',
'Unfulfilled',
'Fulfilled',
'Aborted'
]
export abstract class Condition extends ContractBase { export abstract class Condition extends ContractBase {
public static async getInstance(
public static async getInstance(config: InstantiableConfig, conditionName: string, conditionsClass: any): Promise<Condition & any> { config: InstantiableConfig,
conditionName: string,
conditionsClass: any
): Promise<Condition & any> {
const condition: Condition = new (conditionsClass as any)(conditionName) const condition: Condition = new (conditionsClass as any)(conditionName)
await condition.init(config) await condition.init(config)
return condition return condition
@ -24,12 +32,12 @@ export abstract class Condition extends ContractBase {
} }
public hashValues(...args: any[]): Promise<string> { public hashValues(...args: any[]): Promise<string> {
return this.call("hashValues", args) return this.call('hashValues', args)
} }
public fulfill(agreementId: string, ...args: any[]) public fulfill(agreementId: string, ...args: any[])
public fulfill(agreementId: string, args: any[], from?: string) { public fulfill(agreementId: string, args: any[], from?: string) {
return this.sendFrom("fulfill", [zeroX(agreementId), ...args], from) return this.sendFrom('fulfill', [zeroX(agreementId), ...args], from)
} }
public async generateIdHash(agreementId: string, ...values: any[]) { public async generateIdHash(agreementId: string, ...values: any[]) {
@ -37,14 +45,14 @@ export abstract class Condition extends ContractBase {
} }
public generateId(agreementId: string, valueHash: string) { public generateId(agreementId: string, valueHash: string) {
return this.call<string>("generateId", [zeroX(agreementId), valueHash]) return this.call<string>('generateId', [zeroX(agreementId), valueHash])
} }
public abortByTimeOut(agreementId: string, from?: string) { public abortByTimeOut(agreementId: string, from?: string) {
return this.sendFrom("abortByTimeOut", [zeroX(agreementId)], from) return this.sendFrom('abortByTimeOut', [zeroX(agreementId)], from)
} }
public getConditionFulfilledEvent(agreementId: string) { public getConditionFulfilledEvent(agreementId: string) {
return this.getEvent("Fulfilled", {agreementId: zeroX(agreementId)}) return this.getEvent('Fulfilled', { agreementId: zeroX(agreementId) })
} }
} }

View File

@ -1,15 +1,25 @@
import { Condition } from "./Condition.abstract" import { Condition } from './Condition.abstract'
import { zeroX } from "../../../utils" import { zeroX } from '../../../utils'
import { InstantiableConfig } from "../../../Instantiable.abstract" import { InstantiableConfig } from '../../../Instantiable.abstract'
export class EscrowReward extends Condition { export class EscrowReward extends Condition {
public static async getInstance(
public static async getInstance(config: InstantiableConfig): Promise<EscrowReward> { config: InstantiableConfig
return Condition.getInstance(config, "EscrowReward", EscrowReward) ): Promise<EscrowReward> {
return Condition.getInstance(config, 'EscrowReward', EscrowReward)
} }
public hashValues(amount: number, receiver: string, sender: string, lockCondition: string, releaseCondition: string) { public hashValues(
return super.hashValues(amount, ...[receiver, sender, lockCondition, releaseCondition].map(zeroX)) amount: number,
receiver: string,
sender: string,
lockCondition: string,
releaseCondition: string
) {
return super.hashValues(
amount,
...[receiver, sender, lockCondition, releaseCondition].map(zeroX)
)
} }
public fulfill( public fulfill(
@ -19,8 +29,17 @@ export class EscrowReward extends Condition {
sender: string, sender: string,
lockCondition: string, lockCondition: string,
releaseCondition: string, releaseCondition: string,
from?: string, from?: string
) { ) {
return super.fulfill(agreementId, [amount, ...[receiver, sender, lockCondition, releaseCondition].map(zeroX)], from) return super.fulfill(
agreementId,
[
amount,
...[receiver, sender, lockCondition, releaseCondition].map(
zeroX
)
],
from
)
} }
} }

View File

@ -1,18 +1,32 @@
import { Condition } from "./Condition.abstract" import { Condition } from './Condition.abstract'
import { zeroX } from "../../../utils" import { zeroX } from '../../../utils'
import { InstantiableConfig } from "../../../Instantiable.abstract" import { InstantiableConfig } from '../../../Instantiable.abstract'
export class LockRewardCondition extends Condition { export class LockRewardCondition extends Condition {
public static async getInstance(
public static async getInstance(config: InstantiableConfig): Promise<LockRewardCondition> { config: InstantiableConfig
return Condition.getInstance(config, "LockRewardCondition", LockRewardCondition) ): Promise<LockRewardCondition> {
return Condition.getInstance(
config,
'LockRewardCondition',
LockRewardCondition
)
} }
public hashValues(rewardAddress: string, amount: number | string) { public hashValues(rewardAddress: string, amount: number | string) {
return super.hashValues(zeroX(rewardAddress), String(amount)) return super.hashValues(zeroX(rewardAddress), String(amount))
} }
public fulfill(agreementId: string, rewardAddress: string, amount: number | string, from?: string) { public fulfill(
return super.fulfill(agreementId, [zeroX(rewardAddress), String(amount)], from) agreementId: string,
rewardAddress: string,
amount: number | string,
from?: string
) {
return super.fulfill(
agreementId,
[zeroX(rewardAddress), String(amount)],
from
)
} }
} }

View File

@ -1,4 +1,4 @@
export * from "./Condition.abstract" export * from './Condition.abstract'
export { AccessSecretStoreCondition } from "./AccessSecretStoreCondition" export { AccessSecretStoreCondition } from './AccessSecretStoreCondition'
export { EscrowReward } from "./EscrowReward" export { EscrowReward } from './EscrowReward'
export { LockRewardCondition } from "./LockRewardCondition" export { LockRewardCondition } from './LockRewardCondition'

View File

@ -1,6 +1,6 @@
import ContractBase from "../ContractBase" import ContractBase from '../ContractBase'
import { zeroX } from "../../../utils" import { zeroX } from '../../../utils'
import { InstantiableConfig } from "../../../Instantiable.abstract" import { InstantiableConfig } from '../../../Instantiable.abstract'
export interface AgreementData { export interface AgreementData {
did: string did: string
@ -12,20 +12,36 @@ export interface AgreementData {
} }
export class AgreementStoreManager extends ContractBase { export class AgreementStoreManager extends ContractBase {
public static async getInstance(
public static async getInstance(config: InstantiableConfig): Promise<AgreementStoreManager> { config: InstantiableConfig
const templateStoreManeger: AgreementStoreManager = new AgreementStoreManager("AgreementStoreManager") ): Promise<AgreementStoreManager> {
const templateStoreManeger: AgreementStoreManager = new AgreementStoreManager(
'AgreementStoreManager'
)
await templateStoreManeger.init(config) await templateStoreManeger.init(config)
return templateStoreManeger return templateStoreManeger
} }
public getOwner(): Promise<string> { public getOwner(): Promise<string> {
return this.call("owner", []) return this.call('owner', [])
} }
public async getAgreement(agreementId: string) { public async getAgreement(agreementId: string) {
const {did, didOwner, templateId, conditionIds, lastUpdatedBy, blockNumberUpdated} = const {
await this.call("getAgreement", [zeroX(agreementId)]) did,
return {did, didOwner, templateId, conditionIds, lastUpdatedBy, blockNumberUpdated: +blockNumberUpdated} as AgreementData didOwner,
templateId,
conditionIds,
lastUpdatedBy,
blockNumberUpdated
} = await this.call('getAgreement', [zeroX(agreementId)])
return {
did,
didOwner,
templateId,
conditionIds,
lastUpdatedBy,
blockNumberUpdated: +blockNumberUpdated
} as AgreementData
} }
} }

View File

@ -1,7 +1,7 @@
import ContractBase from "../ContractBase" import ContractBase from '../ContractBase'
import { ConditionState } from "../conditions/Condition.abstract" import { ConditionState } from '../conditions/Condition.abstract'
import { zeroX } from "../../../utils" import { zeroX } from '../../../utils'
import { InstantiableConfig } from "../../../Instantiable.abstract" import { InstantiableConfig } from '../../../Instantiable.abstract'
export interface ConditionData { export interface ConditionData {
typeRef: string typeRef: string
@ -14,20 +14,30 @@ export interface ConditionData {
} }
export class ConditionStoreManager extends ContractBase { export class ConditionStoreManager extends ContractBase {
public static async getInstance(
public static async getInstance(config: InstantiableConfig): Promise<ConditionStoreManager> { config: InstantiableConfig
const templateStoreManeger: ConditionStoreManager = new ConditionStoreManager("ConditionStoreManager") ): Promise<ConditionStoreManager> {
const templateStoreManeger: ConditionStoreManager = new ConditionStoreManager(
'ConditionStoreManager'
)
await templateStoreManeger.init(config) await templateStoreManeger.init(config)
return templateStoreManeger return templateStoreManeger
} }
public getOwner(): Promise<string> { public getOwner(): Promise<string> {
return this.call("owner", []) return this.call('owner', [])
} }
public async getCondition(conditionId: string) { public async getCondition(conditionId: string) {
const {typeRef, state, timeLock, timeOut, blockNumber, lastUpdatedBy, blockNumberUpdated} = const {
await this.call("getCondition", [zeroX(conditionId)]) typeRef,
state,
timeLock,
timeOut,
blockNumber,
lastUpdatedBy,
blockNumberUpdated
} = await this.call('getCondition', [zeroX(conditionId)])
return { return {
typeRef, typeRef,
state: +state, state: +state,
@ -35,7 +45,7 @@ export class ConditionStoreManager extends ContractBase {
timeOut: +timeOut, timeOut: +timeOut,
blockNumber: +blockNumber, blockNumber: +blockNumber,
lastUpdatedBy, lastUpdatedBy,
blockNumberUpdated: +blockNumberUpdated, blockNumberUpdated: +blockNumberUpdated
} as ConditionData } as ConditionData
} }
} }

View File

@ -1,63 +1,86 @@
import ContractBase from "../ContractBase" import ContractBase from '../ContractBase'
import { zeroX } from "../../../utils" import { zeroX } from '../../../utils'
import { InstantiableConfig } from "../../../Instantiable.abstract" import { InstantiableConfig } from '../../../Instantiable.abstract'
export enum TemplateState { export enum TemplateState {
Uninitialized = 0, Uninitialized = 0,
Proposed = 1, Proposed = 1,
Approved = 2, Approved = 2,
Revoked = 3, Revoked = 3
} }
export interface TemplateMetadata { export interface TemplateMetadata {
state: TemplateState, state: TemplateState
owner: string, owner: string
lastUpdatedBy: string, lastUpdatedBy: string
blockNumberUpdated: number blockNumberUpdated: number
} }
export class TemplateStoreManager extends ContractBase { export class TemplateStoreManager extends ContractBase {
public static async getInstance(
public static async getInstance(config: InstantiableConfig): Promise<TemplateStoreManager> { config: InstantiableConfig
const templateStoreManeger: TemplateStoreManager = new TemplateStoreManager("TemplateStoreManager") ): Promise<TemplateStoreManager> {
const templateStoreManeger: TemplateStoreManager = new TemplateStoreManager(
'TemplateStoreManager'
)
await templateStoreManeger.init(config) await templateStoreManeger.init(config)
return templateStoreManeger return templateStoreManeger
} }
public getOwner(): Promise<string> { public getOwner(): Promise<string> {
return this.call("owner", []) return this.call('owner', [])
} }
public async proposeTemplate(address: string, from?: string, ignoreExists?: boolean) { public async proposeTemplate(
address: string,
from?: string,
ignoreExists?: boolean
) {
const template = await this.getTemplate(address) const template = await this.getTemplate(address)
if (template.blockNumberUpdated !== 0) { if (template.blockNumberUpdated !== 0) {
this.logger.warn(`Template "${address}" already exist.`) this.logger.warn(`Template "${address}" already exist.`)
if (!ignoreExists) { if (!ignoreExists) {
throw new Error("Template already exist.") throw new Error('Template already exist.')
} }
} else { } else {
return this.sendFrom("proposeTemplate", [zeroX(address)], from) return this.sendFrom('proposeTemplate', [zeroX(address)], from)
} }
} }
public async approveTemplate(address: string, from?: string, ignoreApproved?: boolean) { public async approveTemplate(
address: string,
from?: string,
ignoreApproved?: boolean
) {
const template = await this.getTemplate(address) const template = await this.getTemplate(address)
if (template.state !== TemplateState.Proposed) { if (template.state !== TemplateState.Proposed) {
this.logger.warn(`Template "${address}" is not in "proposed" state.`) this.logger.warn(
`Template "${address}" is not in "proposed" state.`
)
if (!ignoreApproved) { if (!ignoreApproved) {
throw new Error(`Template not in "proposed" state.`) throw new Error(`Template not in "proposed" state.`)
} }
} else { } else {
return this.sendFrom("approveTemplate", [zeroX(address)], from) return this.sendFrom('approveTemplate', [zeroX(address)], from)
} }
} }
public revokeTemplate(address: string, from?: string) { public revokeTemplate(address: string, from?: string) {
return this.sendFrom("revokeTemplate", [zeroX(address)], from) return this.sendFrom('revokeTemplate', [zeroX(address)], from)
} }
public async getTemplate(address: string) { public async getTemplate(address: string) {
const {state, owner, lastUpdatedBy, blockNumberUpdated} = await this.call("getTemplate", [zeroX(address)]) const {
return {state: +state, owner, lastUpdatedBy, blockNumberUpdated: +blockNumberUpdated} as TemplateMetadata state,
owner,
lastUpdatedBy,
blockNumberUpdated
} = await this.call('getTemplate', [zeroX(address)])
return {
state: +state,
owner,
lastUpdatedBy,
blockNumberUpdated: +blockNumberUpdated
} as TemplateMetadata
} }
} }

View File

@ -1,3 +1,3 @@
export * from "./AgreementStoreManager" export * from './AgreementStoreManager'
export * from "./ConditionStoreManager" export * from './ConditionStoreManager'
export * from "./TemplateStoreManager" export * from './TemplateStoreManager'

View File

@ -1,28 +1,33 @@
import ContractBase from "../ContractBase" import ContractBase from '../ContractBase'
import { Condition, ConditionState, conditionStateNames } from "../conditions/Condition.abstract" import {
import { DDO } from "../../../ddo/DDO" Condition,
import { ServiceAgreementTemplate } from "../../../ddo/ServiceAgreementTemplate" ConditionState,
import { zeroX } from "../../../utils" conditionStateNames
import { InstantiableConfig } from "../../../Instantiable.abstract" } from '../conditions/Condition.abstract'
import { DDO } from '../../../ddo/DDO'
import { ServiceAgreementTemplate } from '../../../ddo/ServiceAgreementTemplate'
import { zeroX } from '../../../utils'
import { InstantiableConfig } from '../../../Instantiable.abstract'
export interface AgreementConditionsStatus { export interface AgreementConditionsStatus {
[condition: string]: { [condition: string]: {
condition: string, condition: string
contractName: string, contractName: string
state: ConditionState, state: ConditionState
blocked: boolean, blocked: boolean
blockedBy: string[], blockedBy: string[]
}, }
} }
export abstract class AgreementTemplate extends ContractBase { export abstract class AgreementTemplate extends ContractBase {
public static async getInstance( public static async getInstance(
config: InstantiableConfig, config: InstantiableConfig,
conditionName: string, conditionName: string,
templateClass: any, templateClass: any
): Promise<AgreementTemplate & any> { ): Promise<AgreementTemplate & any> {
const condition: AgreementTemplate = new (templateClass as any)(conditionName) const condition: AgreementTemplate = new (templateClass as any)(
conditionName
)
await condition.init(config) await condition.init(config)
return condition return condition
} }
@ -32,7 +37,14 @@ export abstract class AgreementTemplate extends ContractBase {
} }
// tslint:disable-next-line // tslint:disable-next-line
public createAgreement(agreementId: string, did: string, conditionIds: string[], timeLocks: number[], timeOuts: number[], ...args: any[]) public createAgreement(
agreementId: string,
did: string,
conditionIds: string[],
timeLocks: number[],
timeOuts: number[],
...args: any[]
)
public createAgreement( public createAgreement(
agreementId: string, agreementId: string,
did: string, did: string,
@ -40,19 +52,19 @@ export abstract class AgreementTemplate extends ContractBase {
timeLocks: number[], timeLocks: number[],
timeOuts: number[], timeOuts: number[],
extraArgs: any[], extraArgs: any[],
from?: string, from?: string
) { ) {
return this.sendFrom( return this.sendFrom(
"createAgreement", 'createAgreement',
[ [
zeroX(agreementId), zeroX(agreementId),
zeroX(did), zeroX(did),
conditionIds.map(zeroX), conditionIds.map(zeroX),
timeLocks, timeLocks,
timeOuts, timeOuts,
...extraArgs, ...extraArgs
], ],
from, from
) )
} }
@ -61,7 +73,7 @@ export abstract class AgreementTemplate extends ContractBase {
* @return {Promise<string[]>} Conditions address. * @return {Promise<string[]>} Conditions address.
*/ */
public getConditionTypes(): Promise<string[]> { public getConditionTypes(): Promise<string[]> {
return this.call("getConditionTypes", []) return this.call('getConditionTypes', [])
} }
/** /**
@ -69,8 +81,9 @@ export abstract class AgreementTemplate extends ContractBase {
* @return {Promise<Condition[]>} Conditions contracts. * @return {Promise<Condition[]>} Conditions contracts.
*/ */
public async getConditions(): Promise<Condition[]> { public async getConditions(): Promise<Condition[]> {
return (await this.getConditionTypes()) return (await this.getConditionTypes()).map(address =>
.map((address) => this.ocean.keeper.getConditionByAddress(address)) this.ocean.keeper.getConditionByAddress(address)
)
} }
/** /**
@ -80,7 +93,12 @@ export abstract class AgreementTemplate extends ContractBase {
* @param {string} from Consumer address. * @param {string} from Consumer address.
* @return {Promise<string[]>} Condition IDs. * @return {Promise<string[]>} Condition IDs.
*/ */
public abstract getAgreementIdsFromDDO(agreementId: string, ddo: DDO, consumer: string, from?: string): Promise<string[]> public abstract getAgreementIdsFromDDO(
agreementId: string,
ddo: DDO,
consumer: string,
from?: string
): Promise<string[]>
/** /**
* Create a new agreement using the data of a DDO. * Create a new agreement using the data of a DDO.
@ -89,9 +107,16 @@ export abstract class AgreementTemplate extends ContractBase {
* @param {string} from Creator address. * @param {string} from Creator address.
* @return {Promise<boolean>} Success. * @return {Promise<boolean>} Success.
*/ */
public abstract createAgreementFromDDO(agreementId: string, ddo: DDO, consumer: string, from?: string): Promise<boolean> public abstract createAgreementFromDDO(
agreementId: string,
ddo: DDO,
consumer: string,
from?: string
): Promise<boolean>
public abstract async getServiceAgreementTemplate(): Promise<ServiceAgreementTemplate> public abstract async getServiceAgreementTemplate(): Promise<
ServiceAgreementTemplate
>
public async getServiceAgreementTemplateConditions() { public async getServiceAgreementTemplateConditions() {
const serviceAgreementTemplate = await this.getServiceAgreementTemplate() const serviceAgreementTemplate = await this.getServiceAgreementTemplate()
@ -99,11 +124,12 @@ export abstract class AgreementTemplate extends ContractBase {
} }
public async getServiceAgreementTemplateConditionByRef(ref: string) { public async getServiceAgreementTemplateConditionByRef(ref: string) {
const name = (await this.getServiceAgreementTemplateConditions()) const name = (await this.getServiceAgreementTemplateConditions()).find(
.find(({name: conditionRef}) => conditionRef === ref) ({ name: conditionRef }) => conditionRef === ref
.contractName ).contractName
return (await this.getConditions()) return (await this.getConditions()).find(
.find((condition) => condition.contractName === name) condition => condition.contractName === name
)
} }
public async getServiceAgreementTemplateDependencies() { public async getServiceAgreementTemplateDependencies() {
@ -117,49 +143,58 @@ export abstract class AgreementTemplate extends ContractBase {
* @return {Promise} Conditions status. * @return {Promise} Conditions status.
*/ */
public async getAgreementStatus( public async getAgreementStatus(
agreementId: string, agreementId: string
): Promise<AgreementConditionsStatus | false> { ): Promise<AgreementConditionsStatus | false> {
const agreementStore = this.ocean.keeper.agreementStoreManager const agreementStore = this.ocean.keeper.agreementStoreManager
const conditionStore = this.ocean.keeper.conditionStoreManager const conditionStore = this.ocean.keeper.conditionStoreManager
const dependencies = await this.getServiceAgreementTemplateDependencies() const dependencies = await this.getServiceAgreementTemplateDependencies()
const {conditionIds} = await agreementStore.getAgreement(agreementId) const { conditionIds } = await agreementStore.getAgreement(agreementId)
if (!conditionIds.length) { if (!conditionIds.length) {
this.logger.error(`Agreement not creeated yet: "${agreementId}"`) this.logger.error(`Agreement not creeated yet: "${agreementId}"`)
return false return false
} }
const conditionIdByConddition = (await this.getConditions()) const conditionIdByConddition = (await this.getConditions()).reduce(
.reduce((acc, {contractName}, i) => ({...acc, [contractName]: conditionIds[i]}), {}) (acc, { contractName }, i) => ({
...acc,
[contractName]: conditionIds[i]
}),
{}
)
const statesPromises = Object.keys(dependencies) const statesPromises = Object.keys(dependencies).map(async (ref, i) => {
.map(async (ref, i) => { const {
const {contractName} = await this.getServiceAgreementTemplateConditionByRef(ref) contractName
return { } = await this.getServiceAgreementTemplateConditionByRef(ref)
ref, return {
contractName, ref,
state: (await conditionStore.getCondition(conditionIdByConddition[contractName])).state, contractName,
} state: (await conditionStore.getCondition(
}) conditionIdByConddition[contractName]
)).state
}
})
const states = await Promise.all(statesPromises) const states = await Promise.all(statesPromises)
return states return states.reduce((acc, { contractName, ref, state }) => {
.reduce((acc, {contractName, ref, state}) => { const blockers = dependencies[ref]
const blockers = dependencies[ref] .map(dependency => states.find(_ => _.ref === dependency))
.map((dependency) => states.find((_) => _.ref === dependency)) .filter(
.filter((condition) => condition.state !== ConditionState.Fulfilled) condition => condition.state !== ConditionState.Fulfilled
return { )
...acc, return {
[ref]: { ...acc,
condition: ref, [ref]: {
contractName, condition: ref,
state, contractName,
blocked: !!blockers.length, state,
blockedBy: blockers.map((_) => _.ref), blocked: !!blockers.length,
}, blockedBy: blockers.map(_ => _.ref)
} }
}, {}) }
}, {})
} }
/** /**
@ -169,25 +204,30 @@ export abstract class AgreementTemplate extends ContractBase {
public async printAgreementStatus(agreementId: string) { public async printAgreementStatus(agreementId: string) {
const status = await this.getAgreementStatus(agreementId) const status = await this.getAgreementStatus(agreementId)
this.logger.bypass("-".repeat(80)) this.logger.bypass('-'.repeat(80))
this.logger.bypass("Template:", this.contractName) this.logger.bypass('Template:', this.contractName)
this.logger.bypass("Agreement ID:", agreementId) this.logger.bypass('Agreement ID:', agreementId)
this.logger.bypass("-".repeat(40)) this.logger.bypass('-'.repeat(40))
if (!status) { if (!status) {
this.logger.bypass("Agreement not created yet!") this.logger.bypass('Agreement not created yet!')
} }
Object.values(status || []) Object.values(status || []).forEach(
.forEach(({condition, contractName, state, blocked, blockedBy}, i) => { ({ condition, contractName, state, blocked, blockedBy }, i) => {
if (i) { if (i) {
this.logger.bypass("-".repeat(20)) this.logger.bypass('-'.repeat(20))
} }
this.logger.bypass(`${condition} (${contractName})`) this.logger.bypass(`${condition} (${contractName})`)
this.logger.bypass(" Status:", state, `(${conditionStateNames[state]})`) this.logger.bypass(
' Status:',
state,
`(${conditionStateNames[state]})`
)
if (blocked) { if (blocked) {
this.logger.bypass(" Blocked by:", blockedBy) this.logger.bypass(' Blocked by:', blockedBy)
} }
}) }
this.logger.bypass("-".repeat(80)) )
this.logger.bypass('-'.repeat(80))
} }
/** /**
@ -196,6 +236,8 @@ export abstract class AgreementTemplate extends ContractBase {
* @return {Event} Agreement created event. * @return {Event} Agreement created event.
*/ */
public getAgreementCreatedEvent(agreementId: string) { public getAgreementCreatedEvent(agreementId: string) {
return this.getEvent("AgreementCreated", {agreementId: zeroX(agreementId)}) return this.getEvent('AgreementCreated', {
agreementId: zeroX(agreementId)
})
} }
} }

View File

@ -1,145 +1,142 @@
import { ServiceAgreementTemplate } from "../../../ddo/ServiceAgreementTemplate" import { ServiceAgreementTemplate } from '../../../ddo/ServiceAgreementTemplate'
export const escrowAccessSecretStoreTemplateServiceAgreementTemplate: ServiceAgreementTemplate = { export const escrowAccessSecretStoreTemplateServiceAgreementTemplate: ServiceAgreementTemplate = {
contractName: "EscrowAccessSecretStoreTemplate", contractName: 'EscrowAccessSecretStoreTemplate',
events: [ events: [
{ {
name: "AgreementCreated", name: 'AgreementCreated',
actorType: "consumer", actorType: 'consumer',
handler: { handler: {
moduleName: "escrowAccessSecretStoreTemplate", moduleName: 'escrowAccessSecretStoreTemplate',
functionName: "fulfillLockRewardCondition", functionName: 'fulfillLockRewardCondition',
version: "0.1", version: '0.1'
}, }
}, }
], ],
fulfillmentOrder: [ fulfillmentOrder: [
"lockReward.fulfill", 'lockReward.fulfill',
"accessSecretStore.fulfill", 'accessSecretStore.fulfill',
"escrowReward.fulfill", 'escrowReward.fulfill'
], ],
conditionDependency: { conditionDependency: {
lockReward: [], lockReward: [],
accessSecretStore: [], accessSecretStore: [],
escrowReward: [ escrowReward: ['lockReward', 'accessSecretStore']
"lockReward",
"accessSecretStore",
],
}, },
conditions: [ conditions: [
{ {
name: "lockReward", name: 'lockReward',
timelock: 0, timelock: 0,
timeout: 0, timeout: 0,
contractName: "LockRewardCondition", contractName: 'LockRewardCondition',
functionName: "fulfill", functionName: 'fulfill',
parameters: [ parameters: [
{ {
name: "_rewardAddress", name: '_rewardAddress',
type: "address", type: 'address',
value: "", value: ''
}, },
{ {
name: "_amount", name: '_amount',
type: "uint256", type: 'uint256',
value: "", value: ''
}, }
], ],
events: [ events: [
{ {
name: "Fulfilled", name: 'Fulfilled',
actorType: "publisher", actorType: 'publisher',
handler: { handler: {
moduleName: "lockRewardCondition", moduleName: 'lockRewardCondition',
functionName: "fulfillAccessSecretStoreCondition", functionName: 'fulfillAccessSecretStoreCondition',
version: "0.1", version: '0.1'
}, }
}, }
], ]
}, },
{ {
name: "accessSecretStore", name: 'accessSecretStore',
timelock: 0, timelock: 0,
timeout: 0, timeout: 0,
contractName: "AccessSecretStoreCondition", contractName: 'AccessSecretStoreCondition',
functionName: "fulfill", functionName: 'fulfill',
parameters: [ parameters: [
{ {
name: "_documentId", name: '_documentId',
type: "bytes32", type: 'bytes32',
value: "", value: ''
}, },
{ {
name: "_grantee", name: '_grantee',
type: "address", type: 'address',
value: "", value: ''
}, }
], ],
events: [ events: [
{ {
name: "Fulfilled", name: 'Fulfilled',
actorType: "publisher", actorType: 'publisher',
handler: { handler: {
moduleName: "accessSecretStore", moduleName: 'accessSecretStore',
functionName: "fulfillEscrowRewardCondition", functionName: 'fulfillEscrowRewardCondition',
version: "0.1", version: '0.1'
}, }
}, },
{ {
name: "TimedOut", name: 'TimedOut',
actorType: "consumer", actorType: 'consumer',
handler: { handler: {
moduleName: "accessSecretStore", moduleName: 'accessSecretStore',
functionName: "fulfillEscrowRewardCondition", functionName: 'fulfillEscrowRewardCondition',
version: "0.1", version: '0.1'
}, }
}, }
], ]
}, },
{ {
name: "escrowReward", name: 'escrowReward',
timelock: 0, timelock: 0,
timeout: 0, timeout: 0,
contractName: "EscrowReward", contractName: 'EscrowReward',
functionName: "fulfill", functionName: 'fulfill',
parameters: [ parameters: [
{ {
name: "_amount", name: '_amount',
type: "uint256", type: 'uint256',
value: "", value: ''
}, },
{ {
name: "_receiver", name: '_receiver',
type: "address", type: 'address',
value: "", value: ''
}, },
{ {
name: "_sender", name: '_sender',
type: "address", type: 'address',
value: "", value: ''
}, },
{ {
name: "_lockCondition", name: '_lockCondition',
type: "bytes32", type: 'bytes32',
value: "", value: ''
}, },
{ {
name: "_releaseCondition", name: '_releaseCondition',
type: "bytes32", type: 'bytes32',
value: "", value: ''
}, }
], ],
events: [ events: [
{ {
name: "Fulfilled", name: 'Fulfilled',
actorType: "publisher", actorType: 'publisher',
handler: { handler: {
moduleName: "escrowRewardCondition", moduleName: 'escrowRewardCondition',
functionName: "verifyRewardTokens", functionName: 'verifyRewardTokens',
version: "0.1", version: '0.1'
}, }
}, }
], ]
}, }
], ]
} }

View File

@ -1,14 +1,19 @@
import { AgreementTemplate } from "./AgreementTemplate.abstract" import { AgreementTemplate } from './AgreementTemplate.abstract'
import { DDO } from "../../../ddo/DDO" import { DDO } from '../../../ddo/DDO'
import { generateId, zeroX } from "../../../utils" import { generateId, zeroX } from '../../../utils'
import { InstantiableConfig } from "../../../Instantiable.abstract" import { InstantiableConfig } from '../../../Instantiable.abstract'
import { escrowAccessSecretStoreTemplateServiceAgreementTemplate } from "./EscrowAccessSecretStoreTemplate.serviceAgreementTemplate" import { escrowAccessSecretStoreTemplateServiceAgreementTemplate } from './EscrowAccessSecretStoreTemplate.serviceAgreementTemplate'
export class EscrowAccessSecretStoreTemplate extends AgreementTemplate { export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
public static async getInstance(
public static async getInstance(config: InstantiableConfig): Promise<EscrowAccessSecretStoreTemplate> { config: InstantiableConfig
return AgreementTemplate.getInstance(config, "EscrowAccessSecretStoreTemplate", EscrowAccessSecretStoreTemplate) ): Promise<EscrowAccessSecretStoreTemplate> {
return AgreementTemplate.getInstance(
config,
'EscrowAccessSecretStoreTemplate',
EscrowAccessSecretStoreTemplate
)
} }
public async getServiceAgreementTemplate() { public async getServiceAgreementTemplate() {
@ -33,7 +38,7 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
timeLocks: number[], timeLocks: number[],
timeOuts: number[], timeOuts: number[],
accessConsumer: string, accessConsumer: string,
from?: string, from?: string
) { ) {
return super.createAgreement( return super.createAgreement(
agreementId, agreementId,
@ -42,24 +47,46 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
timeLocks, timeLocks,
timeOuts, timeOuts,
[accessConsumer], [accessConsumer],
from, from
) )
} }
public async createAgreementFromDDO(agreementId: string, ddo: DDO, consumer: string, from?: string) { public async createAgreementFromDDO(
return !!await this.createFullAgreement( agreementId: string,
ddo: DDO,
consumer: string,
from?: string
) {
return !!(await this.createFullAgreement(
ddo.shortId(), ddo.shortId(),
ddo.findServiceByType("Metadata").metadata.base.price, ddo.findServiceByType('Metadata').metadata.base.price,
consumer, consumer,
from, from,
agreementId, agreementId
) ))
} }
public async getAgreementIdsFromDDO(agreementId: string, ddo: DDO, consumer: string, from?: string) { public async getAgreementIdsFromDDO(
const {accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId} = agreementId: string,
await this.createFullAgreementData(agreementId, ddo.shortId(), ddo.findServiceByType("Metadata").metadata.base.price, consumer) ddo: DDO,
return [accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId] consumer: string,
from?: string
) {
const {
accessSecretStoreConditionId,
lockRewardConditionId,
escrowRewardId
} = await this.createFullAgreementData(
agreementId,
ddo.shortId(),
ddo.findServiceByType('Metadata').metadata.base.price,
consumer
)
return [
accessSecretStoreConditionId,
lockRewardConditionId,
escrowRewardId
]
} }
/** /**
@ -74,47 +101,75 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
amount: number | string, amount: number | string,
consumer: string, consumer: string,
from?: string, from?: string,
agreementId: string = generateId(), agreementId: string = generateId()
): Promise<string> { ): Promise<string> {
const {
const {accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId} = accessSecretStoreConditionId,
await this.createFullAgreementData(agreementId, did, amount, consumer) lockRewardConditionId,
escrowRewardId
} = await this.createFullAgreementData(
agreementId,
did,
amount,
consumer
)
await this.createAgreement( await this.createAgreement(
agreementId, agreementId,
did, did,
[accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId], [
accessSecretStoreConditionId,
lockRewardConditionId,
escrowRewardId
],
[0, 0, 0], [0, 0, 0],
[0, 0, 0], [0, 0, 0],
consumer, consumer,
from, from
) )
return zeroX(agreementId) return zeroX(agreementId)
} }
private async createFullAgreementData(agreementId: string, did: string, amount: number | string, consumer: string) { private async createFullAgreementData(
const {didRegistry, conditions} = this.ocean.keeper agreementId: string,
did: string,
amount: number | string,
consumer: string
) {
const { didRegistry, conditions } = this.ocean.keeper
const {accessSecretStoreCondition, lockRewardCondition, escrowReward} = conditions const {
accessSecretStoreCondition,
lockRewardCondition,
escrowReward
} = conditions
const publisher = await didRegistry.getDIDOwner(did) const publisher = await didRegistry.getDIDOwner(did)
const lockRewardConditionId = await lockRewardCondition.generateIdHash(agreementId, await escrowReward.getAddress(), amount) const lockRewardConditionId = await lockRewardCondition.generateIdHash(
const accessSecretStoreConditionId = await accessSecretStoreCondition.generateIdHash(agreementId, did, consumer) agreementId,
await escrowReward.getAddress(),
amount
)
const accessSecretStoreConditionId = await accessSecretStoreCondition.generateIdHash(
agreementId,
did,
consumer
)
const escrowRewardId = await escrowReward.generateIdHash( const escrowRewardId = await escrowReward.generateIdHash(
agreementId, agreementId,
String(amount), String(amount),
publisher, publisher,
consumer, consumer,
lockRewardConditionId, lockRewardConditionId,
accessSecretStoreConditionId, accessSecretStoreConditionId
) )
return { return {
lockRewardConditionId, lockRewardConditionId,
accessSecretStoreConditionId, accessSecretStoreConditionId,
escrowRewardId, escrowRewardId
} }
} }
} }

View File

@ -1,2 +1,4 @@
export * from "./AgreementTemplate.abstract" export * from './AgreementTemplate.abstract'
export { EscrowAccessSecretStoreTemplate } from "./EscrowAccessSecretStoreTemplate" export {
EscrowAccessSecretStoreTemplate
} from './EscrowAccessSecretStoreTemplate'

View File

@ -3,7 +3,7 @@ enum AccessStatus {
Committed, Committed,
Delivered, Delivered,
Verified, Verified,
Revoked, Revoked
} }
export default AccessStatus export default AccessStatus

View File

@ -1,5 +1,5 @@
import { LogLevel } from "../utils/Logger" import { LogLevel } from '../utils/Logger'
export { LogLevel } from "../utils/Logger" export { LogLevel } from '../utils/Logger'
export class Config { export class Config {
/** /**

View File

@ -1,4 +1,4 @@
import InputType from "./InputType" import InputType from './InputType'
export default class MethodReflection { export default class MethodReflection {
public contractName: string public contractName: string

View File

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

View File

@ -1,7 +1,7 @@
import BigNumber from "bignumber.js" import BigNumber from 'bignumber.js'
import Balance from "../models/Balance" import Balance from '../models/Balance'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
/** /**
* Account information. * Account information.
@ -10,7 +10,7 @@ export default class Account extends Instantiable {
private password?: string private password?: string
private token?: string private token?: string
constructor(private id: string = "0x0", config?: InstantiableConfig) { constructor(private id: string = '0x0', config?: InstantiableConfig) {
super() super()
if (config) { if (config) {
this.setInstanceConfig(config) this.setInstanceConfig(config)
@ -54,7 +54,7 @@ export default class Account extends Instantiable {
* @return {Promise<string>} Account token. * @return {Promise<string>} Account token.
*/ */
public async getToken(): Promise<string> { public async getToken(): Promise<string> {
return this.token || await this.ocean.auth.restore(this) return this.token || (await this.ocean.auth.restore(this))
} }
/** /**
@ -77,8 +77,8 @@ export default class Account extends Instantiable {
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async getOceanBalance(): Promise<number> { public async getOceanBalance(): Promise<number> {
const token = this.ocean.keeper.token const { token } = this.ocean.keeper
return await token.balanceOf(this.id) / (10 ** await token.decimals()) return (await token.balanceOf(this.id)) / 10 ** (await token.decimals())
} }
/** /**
@ -86,9 +86,8 @@ export default class Account extends Instantiable {
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async getEtherBalance(): Promise<number> { public async getEtherBalance(): Promise<number> {
return this.web3 return this.web3.eth
.eth .getBalance(this.id, 'latest')
.getBalance(this.id, "latest")
.then((balance: string): number => { .then((balance: string): number => {
return new BigNumber(balance).toNumber() return new BigNumber(balance).toNumber()
}) })
@ -101,7 +100,7 @@ export default class Account extends Instantiable {
public async getBalance(): Promise<Balance> { public async getBalance(): Promise<Balance> {
return { return {
eth: await this.getEtherBalance(), eth: await this.getEtherBalance(),
ocn: await this.getOceanBalance(), ocn: await this.getOceanBalance()
} }
} }
@ -113,13 +112,10 @@ export default class Account extends Instantiable {
public async requestTokens(amount: number | string): Promise<string> { public async requestTokens(amount: number | string): Promise<string> {
amount = String(amount) amount = String(amount)
try { try {
await this.ocean.keeper await this.ocean.keeper.dispenser.requestTokens(amount, this.id)
.dispenser
.requestTokens(amount, this.id)
} catch (e) { } catch (e) {
this.logger.error(e) this.logger.error(e)
throw new Error("Error requesting tokens") throw new Error('Error requesting tokens')
} }
return amount return amount
} }

View File

@ -1,12 +1,11 @@
import { generateId } from "../utils/GeneratorHelpers" import { generateId } from '../utils/GeneratorHelpers'
const prefix = "did:op:" const prefix = 'did:op:'
/** /**
* Decentralized ID. * Decentralized ID.
*/ */
export default class DID { export default class DID {
/** /**
* Parses a DID from a string. * Parses a DID from a string.
* @param {string} didString DID in string. * @param {string} didString DID in string.

View File

@ -1,26 +1,28 @@
import { OceanAccounts } from "./OceanAccounts" import { OceanAccounts } from './OceanAccounts'
import { OceanAgreements } from "./OceanAgreements" import { OceanAgreements } from './OceanAgreements'
import { OceanAssets } from "./OceanAssets" import { OceanAssets } from './OceanAssets'
import { OceanAuth } from "./OceanAuth" import { OceanAuth } from './OceanAuth'
import { OceanSecretStore } from "./OceanSecretStore" import { OceanSecretStore } from './OceanSecretStore'
import { OceanTokens } from "./OceanTokens" import { OceanTokens } from './OceanTokens'
import { OceanVersions } from "./OceanVersions" import { OceanVersions } from './OceanVersions'
import { OceanUtils } from "./utils/OceanUtils" import { OceanUtils } from './utils/OceanUtils'
import { Aquarius } from "../aquarius/Aquarius" import { Aquarius } from '../aquarius/Aquarius'
import { Brizo } from "../brizo/Brizo" import { Brizo } from '../brizo/Brizo'
import Keeper from "../keeper/Keeper" import Keeper from '../keeper/Keeper'
import { Config } from "../models/Config" import { Config } from '../models/Config'
import { Instantiable, generateIntantiableConfigFromConfig } from "../Instantiable.abstract" import {
Instantiable,
generateIntantiableConfigFromConfig
} from '../Instantiable.abstract'
/** /**
* Main interface for Ocean Protocol. * Main interface for Ocean Protocol.
*/ */
export class Ocean extends Instantiable { export class Ocean extends Instantiable {
/** /**
* Returns the instance of Ocean. * Returns the instance of Ocean.
* @param {Config} config Ocean instance configuration. * @param {Config} config Ocean instance configuration.
@ -31,7 +33,7 @@ export class Ocean extends Instantiable {
const instanceConfig = { const instanceConfig = {
...generateIntantiableConfigFromConfig(config), ...generateIntantiableConfigFromConfig(config),
ocean: instance, ocean: instance
} }
instance.setInstanceConfig(instanceConfig) instance.setInstanceConfig(instanceConfig)
@ -44,7 +46,9 @@ export class Ocean extends Instantiable {
instance.auth = await OceanAuth.getInstance(instanceConfig) instance.auth = await OceanAuth.getInstance(instanceConfig)
instance.assets = await OceanAssets.getInstance(instanceConfig) instance.assets = await OceanAssets.getInstance(instanceConfig)
instance.agreements = await OceanAgreements.getInstance(instanceConfig) instance.agreements = await OceanAgreements.getInstance(instanceConfig)
instance.secretStore = await OceanSecretStore.getInstance(instanceConfig) instance.secretStore = await OceanSecretStore.getInstance(
instanceConfig
)
instance.tokens = await OceanTokens.getInstance(instanceConfig) instance.tokens = await OceanTokens.getInstance(instanceConfig)
instance.versions = await OceanVersions.getInstance(instanceConfig) instance.versions = await OceanVersions.getInstance(instanceConfig)

View File

@ -1,17 +1,18 @@
import Balance from "../models/Balance" import Balance from '../models/Balance'
import Account from "./Account" import Account from './Account'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
/** /**
* Account submodule of Ocean Protocol. * Account submodule of Ocean Protocol.
*/ */
export class OceanAccounts extends Instantiable { export class OceanAccounts extends Instantiable {
/** /**
* Returns the instance of OceanAccounts. * Returns the instance of OceanAccounts.
* @return {Promise<OceanAccounts>} * @return {Promise<OceanAccounts>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<OceanAccounts> { public static async getInstance(
config: InstantiableConfig
): Promise<OceanAccounts> {
const instance = new OceanAccounts() const instance = new OceanAccounts()
instance.setInstanceConfig(config) instance.setInstanceConfig(config)
@ -23,12 +24,12 @@ export class OceanAccounts extends Instantiable {
* @return {Promise<Account[]>} * @return {Promise<Account[]>}
*/ */
public async list(): Promise<Account[]> { public async list(): Promise<Account[]> {
// retrieve eth accounts // retrieve eth accounts
const ethAccounts: string[] = await this.web3.eth.getAccounts() const ethAccounts: string[] = await this.web3.eth.getAccounts()
const accountPromises = ethAccounts const accountPromises = ethAccounts.map(
.map((address) => new Account(address, this.instanceConfig)) address => new Account(address, this.instanceConfig)
)
return Promise.all(accountPromises) return Promise.all(accountPromises)
} }
@ -47,7 +48,10 @@ export class OceanAccounts extends Instantiable {
* @param {number} amount Token amount. * @param {number} amount Token amount.
* @return {Promise<boolean>} Success. * @return {Promise<boolean>} Success.
*/ */
public async requestTokens(account: Account, amount: number): Promise<boolean> { public async requestTokens(
account: Account,
amount: number
): Promise<boolean> {
try { try {
await account.requestTokens(amount) await account.requestTokens(amount)
return true return true

View File

@ -1,12 +1,12 @@
import { generateId } from "../utils/GeneratorHelpers" import { generateId } from '../utils/GeneratorHelpers'
import Account from "./Account" import Account from './Account'
import DID from "./DID" import DID from './DID'
import { zeroX, didPrefixed } from "../utils" import { zeroX, didPrefixed } from '../utils'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import { AgreementConditionsStatus } from "../keeper/contracts/templates/AgreementTemplate.abstract" import { AgreementConditionsStatus } from '../keeper/contracts/templates/AgreementTemplate.abstract'
import { ConditionState } from "../keeper/contracts/conditions/Condition.abstract" import { ConditionState } from '../keeper/contracts/conditions/Condition.abstract'
import { OceanAgreementsConditions } from "./OceanAgreementsConditions" import { OceanAgreementsConditions } from './OceanAgreementsConditions'
export interface AgreementPrepareResult { export interface AgreementPrepareResult {
agreementId: string agreementId: string
@ -17,15 +17,18 @@ export interface AgreementPrepareResult {
* Agreements submodule of Ocean Protocol. * Agreements submodule of Ocean Protocol.
*/ */
export class OceanAgreements extends Instantiable { export class OceanAgreements extends Instantiable {
/** /**
* Returns the instance of OceanAgreements. * Returns the instance of OceanAgreements.
* @return {Promise<OceanAgreements>} * @return {Promise<OceanAgreements>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<OceanAgreements> { public static async getInstance(
config: InstantiableConfig
): Promise<OceanAgreements> {
const instance = new OceanAgreements() const instance = new OceanAgreements()
instance.setInstanceConfig(config) instance.setInstanceConfig(config)
instance.conditions = await OceanAgreementsConditions.getInstance(config) instance.conditions = await OceanAgreementsConditions.getInstance(
config
)
return instance return instance
} }
@ -46,27 +49,32 @@ export class OceanAgreements extends Instantiable {
public async prepare( public async prepare(
did: string, did: string,
serviceDefinitionId: string, serviceDefinitionId: string,
consumer: Account, consumer: Account
): Promise<AgreementPrepareResult> { ): Promise<AgreementPrepareResult> {
const d: DID = DID.parse(did as string) const d: DID = DID.parse(did as string)
const ddo = await this.ocean.aquarius.retrieveDDO(d) const ddo = await this.ocean.aquarius.retrieveDDO(d)
const agreementId: string = zeroX(generateId()) const agreementId: string = zeroX(generateId())
const templateName = ddo.findServiceByType("Access").serviceAgreementTemplate.contractName const templateName = ddo.findServiceByType('Access')
.serviceAgreementTemplate.contractName
const agreementConditionsIds = await this.ocean.keeper const agreementConditionsIds = await this.ocean.keeper
.getTemplateByName(templateName) .getTemplateByName(templateName)
.getAgreementIdsFromDDO(agreementId, ddo, consumer.getId(), consumer.getId()) .getAgreementIdsFromDDO(
agreementId,
ddo,
consumer.getId(),
consumer.getId()
)
const signature = await this.ocean.utils.agreements.signServiceAgreement( const signature = await this.ocean.utils.agreements.signServiceAgreement(
ddo, ddo,
serviceDefinitionId, serviceDefinitionId,
agreementId, agreementId,
agreementConditionsIds, agreementConditionsIds,
consumer, consumer
) )
return {agreementId, signature} return { agreementId, signature }
} }
/** /**
@ -81,20 +89,20 @@ export class OceanAgreements extends Instantiable {
agreementId: string, agreementId: string,
serviceDefinitionId: string, serviceDefinitionId: string,
signature: string, signature: string,
consumer: Account, consumer: Account
): Promise<void> { ): Promise<void> {
const result = await this.ocean.brizo.initializeServiceAgreement(
const result = await this.ocean.brizo didPrefixed(did),
.initializeServiceAgreement( zeroX(agreementId),
didPrefixed(did), serviceDefinitionId,
zeroX(agreementId), zeroX(signature),
serviceDefinitionId, consumer.getId()
zeroX(signature), )
consumer.getId(),
)
if (!result.ok) { if (!result.ok) {
throw new Error("Error on initialize agreement: " + await result.text()) throw new Error(
'Error on initialize agreement: ' + (await result.text())
)
} }
} }
@ -116,15 +124,21 @@ export class OceanAgreements extends Instantiable {
serviceDefinitionId: string, serviceDefinitionId: string,
signature: string, signature: string,
consumer: Account, consumer: Account,
publisher: Account, publisher: Account
) { ) {
const d: DID = DID.parse(did) const d: DID = DID.parse(did)
const ddo = await this.ocean.aquarius.retrieveDDO(d) const ddo = await this.ocean.aquarius.retrieveDDO(d)
const templateName = ddo.findServiceById<"Access">(serviceDefinitionId).serviceAgreementTemplate.contractName const templateName = ddo.findServiceById<'Access'>(serviceDefinitionId)
.serviceAgreementTemplate.contractName
await this.ocean.keeper await this.ocean.keeper
.getTemplateByName(templateName) .getTemplateByName(templateName)
.createAgreementFromDDO(agreementId, ddo, consumer.getId(), publisher.getId()) .createAgreementFromDDO(
agreementId,
ddo,
consumer.getId(),
publisher.getId()
)
return true return true
} }
@ -137,13 +151,20 @@ export class OceanAgreements extends Instantiable {
* @param {boolean} extended Returns a complete status with dependencies. * @param {boolean} extended Returns a complete status with dependencies.
* @return {Promise<any>} * @return {Promise<any>}
*/ */
public async status(agreementId: string, extended?: false): Promise<{[condition: string]: ConditionState}>
public async status(agreementId: string, extended: true): Promise<AgreementConditionsStatus>
public async status( public async status(
agreementId: string, agreementId: string,
extended: boolean = false, extended?: false
) { ): Promise<{ [condition: string]: ConditionState }>
const {templateId} = await this.ocean.keeper.agreementStoreManager.getAgreement(agreementId) public async status(
agreementId: string,
extended: true
): Promise<AgreementConditionsStatus>
public async status(agreementId: string, extended: boolean = false) {
const {
templateId
} = await this.ocean.keeper.agreementStoreManager.getAgreement(
agreementId
)
const fullStatus = await this.ocean.keeper const fullStatus = await this.ocean.keeper
.getTemplateByAddress(templateId) .getTemplateByAddress(templateId)
.getAgreementStatus(agreementId) .getAgreementStatus(agreementId)
@ -155,10 +176,9 @@ export class OceanAgreements extends Instantiable {
return fullStatus return fullStatus
} }
const simpleStatus = {} const simpleStatus = {}
Object.entries(fullStatus) Object.entries(fullStatus).forEach(([condition, { state }]) => {
.forEach(([condition, {state}]) => { simpleStatus[condition] = state
simpleStatus[condition] = state })
})
return simpleStatus as any return simpleStatus as any
} }
} }

View File

@ -1,16 +1,17 @@
import Account from "./Account" import Account from './Account'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
/** /**
* Agreements Conditions submodule of Ocean Protocol. * Agreements Conditions submodule of Ocean Protocol.
*/ */
export class OceanAgreementsConditions extends Instantiable { export class OceanAgreementsConditions extends Instantiable {
/** /**
* Returns the instance of OceanAgreementsConditions. * Returns the instance of OceanAgreementsConditions.
* @return {Promise<OceanAgreementsConditions>} * @return {Promise<OceanAgreementsConditions>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<OceanAgreementsConditions> { public static async getInstance(
config: InstantiableConfig
): Promise<OceanAgreementsConditions> {
const instance = new OceanAgreementsConditions() const instance = new OceanAgreementsConditions()
instance.setInstanceConfig(config) instance.setInstanceConfig(config)
@ -24,12 +25,28 @@ export class OceanAgreementsConditions extends Instantiable {
* @param {number} amount Asset amount. * @param {number} amount Asset amount.
* @param {Account} from Account of sender. * @param {Account} from Account of sender.
*/ */
public async lockReward(agreementId: string, amount: number | string, from?: Account) { public async lockReward(
const {lockRewardCondition, escrowReward} = this.ocean.keeper.conditions agreementId: string,
amount: number | string,
from?: Account
) {
const {
lockRewardCondition,
escrowReward
} = this.ocean.keeper.conditions
await this.ocean.keeper.token.approve(lockRewardCondition.getAddress(), amount, from.getId()) await this.ocean.keeper.token.approve(
lockRewardCondition.getAddress(),
amount,
from.getId()
)
const receipt = await lockRewardCondition.fulfill(agreementId, escrowReward.getAddress(), amount, from && from.getId()) const receipt = await lockRewardCondition.fulfill(
agreementId,
escrowReward.getAddress(),
amount,
from && from.getId()
)
return !!receipt.events.Fulfilled return !!receipt.events.Fulfilled
} }
@ -40,10 +57,20 @@ export class OceanAgreementsConditions extends Instantiable {
* @param {string} grantee Consumer address. * @param {string} grantee Consumer address.
* @param {Account} from Account of sender. * @param {Account} from Account of sender.
*/ */
public async grantAccess(agreementId: string, did: string, grantee: string, from?: Account) { public async grantAccess(
const {accessSecretStoreCondition} = this.ocean.keeper.conditions agreementId: string,
did: string,
grantee: string,
from?: Account
) {
const { accessSecretStoreCondition } = this.ocean.keeper.conditions
const receipt = await accessSecretStoreCondition.fulfill(agreementId, did, grantee, from && from.getId()) const receipt = await accessSecretStoreCondition.fulfill(
agreementId,
did,
grantee,
from && from.getId()
)
return !!receipt.events.Fulfilled return !!receipt.events.Fulfilled
} }
@ -66,12 +93,24 @@ export class OceanAgreementsConditions extends Instantiable {
did: string, did: string,
consumer: string, consumer: string,
publisher: string, publisher: string,
from?: Account, from?: Account
) { ) {
const {escrowReward, accessSecretStoreCondition, lockRewardCondition} = this.ocean.keeper.conditions const {
escrowReward,
accessSecretStoreCondition,
lockRewardCondition
} = this.ocean.keeper.conditions
const conditionIdAccess = await accessSecretStoreCondition.generateIdHash(agreementId, did, consumer) const conditionIdAccess = await accessSecretStoreCondition.generateIdHash(
const conditionIdLock = await lockRewardCondition.generateIdHash(agreementId, escrowReward.getAddress(), amount) agreementId,
did,
consumer
)
const conditionIdLock = await lockRewardCondition.generateIdHash(
agreementId,
escrowReward.getAddress(),
amount
)
const receipt = await escrowReward.fulfill( const receipt = await escrowReward.fulfill(
agreementId, agreementId,
@ -80,7 +119,7 @@ export class OceanAgreementsConditions extends Instantiable {
consumer, consumer,
conditionIdLock, conditionIdLock,
conditionIdAccess, conditionIdAccess,
from && from.getId(), from && from.getId()
) )
return !!receipt.events.Fulfilled return !!receipt.events.Fulfilled
} }

View File

@ -1,11 +1,16 @@
import { SearchQuery } from "../aquarius/Aquarius" import { SearchQuery } from '../aquarius/Aquarius'
import { DDO } from "../ddo/DDO" import { DDO } from '../ddo/DDO'
import { MetaData } from "../ddo/MetaData" import { MetaData } from '../ddo/MetaData'
import { Service } from "../ddo/Service" import { Service } from '../ddo/Service'
import Account from "./Account" import Account from './Account'
import DID from "./DID" import DID from './DID'
import { fillConditionsWithDDO, SubscribablePromise, generateId, zeroX } from "../utils" import {
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" fillConditionsWithDDO,
SubscribablePromise,
generateId,
zeroX
} from '../utils'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
export enum CreateProgressStep { export enum CreateProgressStep {
EncryptingFiles, EncryptingFiles,
@ -15,26 +20,27 @@ export enum CreateProgressStep {
RegisteringDid, RegisteringDid,
DidRegistred, DidRegistred,
StoringDdo, StoringDdo,
DdoStored, DdoStored
} }
export enum OrderProgressStep { export enum OrderProgressStep {
CreatingAgreement, CreatingAgreement,
AgreementInitialized, AgreementInitialized,
LockingPayment, LockingPayment,
LockedPayment, LockedPayment
} }
/** /**
* Assets submodule of Ocean Protocol. * Assets submodule of Ocean Protocol.
*/ */
export class OceanAssets extends Instantiable { export class OceanAssets extends Instantiable {
/** /**
* Returns the instance of OceanAssets. * Returns the instance of OceanAssets.
* @return {Promise<OceanAssets>} * @return {Promise<OceanAssets>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<OceanAssets> { public static async getInstance(
config: InstantiableConfig
): Promise<OceanAssets> {
const instance = new OceanAssets() const instance = new OceanAssets()
instance.setInstanceConfig(config) instance.setInstanceConfig(config)
@ -57,18 +63,26 @@ export class OceanAssets extends Instantiable {
* @param {Account} publisher Publisher account. * @param {Account} publisher Publisher account.
* @return {Promise<DDO>} * @return {Promise<DDO>}
*/ */
public create(metadata: MetaData, publisher: Account, services: Service[] = []): SubscribablePromise<CreateProgressStep, DDO> { public create(
this.logger.log("Creating asset") metadata: MetaData,
return new SubscribablePromise(async (observer) => { publisher: Account,
const {secretStoreUri} = this.config services: Service[] = []
const {didRegistry, templates} = this.ocean.keeper ): SubscribablePromise<CreateProgressStep, DDO> {
this.logger.log('Creating asset')
return new SubscribablePromise(async observer => {
const { secretStoreUri } = this.config
const { didRegistry, templates } = this.ocean.keeper
const did: DID = DID.generate() const did: DID = DID.generate()
this.logger.log("Encrypting files") this.logger.log('Encrypting files')
observer.next(CreateProgressStep.EncryptingFiles) observer.next(CreateProgressStep.EncryptingFiles)
const encryptedFiles = await this.ocean.secretStore.encrypt(did.getId(), metadata.base.files, publisher) const encryptedFiles = await this.ocean.secretStore.encrypt(
this.logger.log("Files encrypted") did.getId(),
metadata.base.files,
publisher
)
this.logger.log('Files encrypted')
observer.next(CreateProgressStep.FilesEncrypted) observer.next(CreateProgressStep.FilesEncrypted)
const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate() const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate()
@ -79,40 +93,42 @@ export class OceanAssets extends Instantiable {
// create ddo itself // create ddo itself
const ddo: DDO = new DDO({ const ddo: DDO = new DDO({
id: did.getDid(), id: did.getDid(),
authentication: [{ authentication: [
type: "RsaSignatureAuthentication2018", {
publicKey: did.getDid(), type: 'RsaSignatureAuthentication2018',
}], publicKey: did.getDid()
}
],
publicKey: [ publicKey: [
{ {
id: did.getDid(), id: did.getDid(),
type: "EthereumECDSAKey", type: 'EthereumECDSAKey',
owner: publisher.getId(), owner: publisher.getId()
}, }
], ],
service: [ service: [
{ {
type: "Access", type: 'Access',
creator: "", creator: '',
purchaseEndpoint: this.ocean.brizo.getPurchaseEndpoint(), purchaseEndpoint: this.ocean.brizo.getPurchaseEndpoint(),
serviceEndpoint: this.ocean.brizo.getConsumeEndpoint(), serviceEndpoint: this.ocean.brizo.getConsumeEndpoint(),
name: "dataAssetAccessServiceAgreement", name: 'dataAssetAccessServiceAgreement',
templateId: templates.escrowAccessSecretStoreTemplate.getAddress(), templateId: templates.escrowAccessSecretStoreTemplate.getAddress(),
serviceAgreementTemplate, serviceAgreementTemplate
}, },
{ {
type: "Authorization", type: 'Authorization',
service: "SecretStore", service: 'SecretStore',
serviceEndpoint: secretStoreUri, serviceEndpoint: secretStoreUri
}, },
{ {
type: "Metadata", type: 'Metadata',
serviceEndpoint, serviceEndpoint,
metadata: { metadata: {
// Default values // Default values
curation: { curation: {
rating: 0, rating: 0,
numVotes: 0, numVotes: 0
}, },
// Overwrites defaults // Overwrites defaults
...metadata, ...metadata,
@ -121,23 +137,30 @@ export class OceanAssets extends Instantiable {
...metadata.base, ...metadata.base,
contentUrls: undefined, contentUrls: undefined,
encryptedFiles, encryptedFiles,
files: metadata.base.files files: metadata.base.files.map(
.map((file, index) => ({ (file, index) => ({
...file, ...file,
index, index,
url: undefined, url: undefined
})), })
} as any, )
}, } as any
}
}, },
...services, ...services
] ]
// Remove duplications // Remove duplications
.reverse() .reverse()
.filter(({type}, i, list) => list.findIndex(({type: t}) => t === type) === i) .filter(
({ type }, i, list) =>
list.findIndex(({ type: t }) => t === type) === i
)
.reverse() .reverse()
// Adding ID // Adding ID
.map((_) => ({..._, serviceDefinitionId: String(serviceDefinitionIdCount++)})) as Service[], .map(_ => ({
..._,
serviceDefinitionId: String(serviceDefinitionIdCount++)
})) as Service[]
}) })
// Overwritte initial service agreement conditions // Overwritte initial service agreement conditions
@ -146,72 +169,93 @@ export class OceanAssets extends Instantiable {
serviceAgreementTemplate.conditions = conditions serviceAgreementTemplate.conditions = conditions
ddo.addChecksum() ddo.addChecksum()
this.logger.log("Generating proof") this.logger.log('Generating proof')
observer.next(CreateProgressStep.GeneratingProof) observer.next(CreateProgressStep.GeneratingProof)
await ddo.addProof(this.ocean, publisher.getId(), publisher.getPassword()) await ddo.addProof(
this.logger.log("Proof generated") this.ocean,
publisher.getId(),
publisher.getPassword()
)
this.logger.log('Proof generated')
observer.next(CreateProgressStep.ProofGenerated) observer.next(CreateProgressStep.ProofGenerated)
this.logger.log("Registering DID") this.logger.log('Registering DID')
observer.next(CreateProgressStep.RegisteringDid) observer.next(CreateProgressStep.RegisteringDid)
await didRegistry.registerAttribute( await didRegistry.registerAttribute(
did.getId(), did.getId(),
ddo.getChecksum(), ddo.getChecksum(),
[this.config.brizoAddress], [this.config.brizoAddress],
serviceEndpoint, serviceEndpoint,
publisher.getId(), publisher.getId()
) )
this.logger.log("DID registred") this.logger.log('DID registred')
observer.next(CreateProgressStep.DidRegistred) observer.next(CreateProgressStep.DidRegistred)
this.logger.log("Storing DDO") this.logger.log('Storing DDO')
observer.next(CreateProgressStep.StoringDdo) observer.next(CreateProgressStep.StoringDdo)
const storedDdo = await this.ocean.aquarius.storeDDO(ddo) const storedDdo = await this.ocean.aquarius.storeDDO(ddo)
this.logger.log("DDO stored") this.logger.log('DDO stored')
observer.next(CreateProgressStep.DdoStored) observer.next(CreateProgressStep.DdoStored)
return storedDdo return storedDdo
}) })
} }
// tslint:disable-next-line public async consume(
public async consume(agreementId: string, did: string, serviceDefinitionId: string, consumerAccount: Account, resultPath: string, index?: number): Promise<string> agreementId: string,
// tslint:disable-next-line did: string,
public async consume(agreementId: string, did: string, serviceDefinitionId: string, consumerAccount: Account, resultPath?: undefined | null, index?: number): Promise<true> serviceDefinitionId: string,
consumerAccount: Account,
resultPath: string,
index?: number
): Promise<string>
public async consume(
agreementId: string,
did: string,
serviceDefinitionId: string,
consumerAccount: Account,
resultPath?: undefined | null,
index?: number
): Promise<true>
public async consume( public async consume(
agreementId: string, agreementId: string,
did: string, did: string,
serviceDefinitionId: string, serviceDefinitionId: string,
consumerAccount: Account, consumerAccount: Account,
resultPath?: string, resultPath?: string,
index: number = -1, index: number = -1
): Promise<string | true> { ): Promise<string | true> {
const ddo = await this.resolve(did) const ddo = await this.resolve(did)
const {metadata} = ddo.findServiceByType("Metadata") const { metadata } = ddo.findServiceByType('Metadata')
const accessService = ddo.findServiceById(serviceDefinitionId) const accessService = ddo.findServiceById(serviceDefinitionId)
const files = metadata.base.files const { files } = metadata.base
const {serviceEndpoint} = accessService const { serviceEndpoint } = accessService
if (!serviceEndpoint) { if (!serviceEndpoint) {
throw new Error("Consume asset failed, service definition is missing the `serviceEndpoint`.") throw new Error(
'Consume asset failed, service definition is missing the `serviceEndpoint`.'
)
} }
this.logger.log("Consuming files") this.logger.log('Consuming files')
resultPath = resultPath ? `${resultPath}/datafile.${ddo.shortId()}.${serviceDefinitionId}/` : undefined resultPath = resultPath
? `${resultPath}/datafile.${ddo.shortId()}.${serviceDefinitionId}/`
: undefined
await this.ocean.brizo.consumeService( await this.ocean.brizo.consumeService(
agreementId, agreementId,
serviceEndpoint, serviceEndpoint,
consumerAccount, consumerAccount,
files, files,
resultPath, resultPath,
index, index
) )
this.logger.log("Files consumed") this.logger.log('Files consumed')
if (resultPath) { if (resultPath) {
return resultPath return resultPath
@ -230,60 +274,73 @@ export class OceanAssets extends Instantiable {
public order( public order(
did: string, did: string,
serviceDefinitionId: string, serviceDefinitionId: string,
consumer: Account, consumer: Account
): SubscribablePromise<OrderProgressStep, string> { ): SubscribablePromise<OrderProgressStep, string> {
return new SubscribablePromise(async observer => {
return new SubscribablePromise(async (observer) => {
const oceanAgreements = this.ocean.agreements const oceanAgreements = this.ocean.agreements
const agreementId = zeroX(generateId()) const agreementId = zeroX(generateId())
const ddo = await this.resolve(did) const ddo = await this.resolve(did)
const keeper = this.ocean.keeper const { keeper } = this.ocean
const templateName = ddo.findServiceByType("Access").serviceAgreementTemplate.contractName const templateName = ddo.findServiceByType('Access')
.serviceAgreementTemplate.contractName
const template = keeper.getTemplateByName(templateName) const template = keeper.getTemplateByName(templateName)
const accessCondition = keeper.conditions.accessSecretStoreCondition const accessCondition = keeper.conditions.accessSecretStoreCondition
const paymentFlow = new Promise(async (resolve, reject) => { const paymentFlow = new Promise(async (resolve, reject) => {
await template.getAgreementCreatedEvent(agreementId).once() await template.getAgreementCreatedEvent(agreementId).once()
this.logger.log("Agreement initialized") this.logger.log('Agreement initialized')
observer.next(OrderProgressStep.AgreementInitialized) observer.next(OrderProgressStep.AgreementInitialized)
const {metadata} = ddo.findServiceByType("Metadata") const { metadata } = ddo.findServiceByType('Metadata')
this.logger.log("Locking payment") this.logger.log('Locking payment')
const accessGranted = accessCondition.getConditionFulfilledEvent(agreementId).once() const accessGranted = accessCondition
.getConditionFulfilledEvent(agreementId)
.once()
observer.next(OrderProgressStep.LockingPayment) observer.next(OrderProgressStep.LockingPayment)
const paid = await oceanAgreements.conditions.lockReward(agreementId, metadata.base.price, consumer) const paid = await oceanAgreements.conditions.lockReward(
agreementId,
metadata.base.price,
consumer
)
observer.next(OrderProgressStep.LockedPayment) observer.next(OrderProgressStep.LockedPayment)
if (paid) { if (paid) {
this.logger.log("Payment was OK") this.logger.log('Payment was OK')
} else { } else {
this.logger.error("Payment was KO") this.logger.error('Payment was KO')
this.logger.error("Agreement ID: ", agreementId) this.logger.error('Agreement ID: ', agreementId)
this.logger.error("DID: ", ddo.id) this.logger.error('DID: ', ddo.id)
reject("Error on payment") reject('Error on payment')
} }
await accessGranted await accessGranted
this.logger.log("Access granted") this.logger.log('Access granted')
resolve() resolve()
}) })
observer.next(OrderProgressStep.CreatingAgreement) observer.next(OrderProgressStep.CreatingAgreement)
this.logger.log("Creating agreement") this.logger.log('Creating agreement')
await oceanAgreements.create(did, agreementId, serviceDefinitionId, undefined, consumer, consumer) await oceanAgreements.create(
this.logger.log("Agreement created") did,
agreementId,
serviceDefinitionId,
undefined,
consumer,
consumer
)
this.logger.log('Agreement created')
try { try {
await paymentFlow await paymentFlow
} catch (e) { } catch (e) {
throw new Error("Error paying the asset.") throw new Error('Error paying the asset.')
} }
return agreementId return agreementId
@ -298,11 +355,16 @@ export class OceanAssets extends Instantiable {
public async owner(did: string): Promise<string> { public async owner(did: string): Promise<string> {
const ddo = await this.resolve(did) const ddo = await this.resolve(did)
const checksum = ddo.getChecksum() const checksum = ddo.getChecksum()
const {creator, signatureValue} = ddo.proof const { creator, signatureValue } = ddo.proof
const signer = await this.ocean.utils.signature.verifyText(checksum, signatureValue) const signer = await this.ocean.utils.signature.verifyText(
checksum,
signatureValue
)
if (signer.toLowerCase() !== creator.toLowerCase()) { if (signer.toLowerCase() !== creator.toLowerCase()) {
this.logger.warn(`Owner of ${ddo.id} doesn't match. Expected ${creator} instead of ${signer}.`) this.logger.warn(
`Owner of ${ddo.id} doesn't match. Expected ${creator} instead of ${signer}.`
)
} }
return creator return creator
@ -323,8 +385,9 @@ export class OceanAssets extends Instantiable {
* @return {Promise<string[]>} List of DIDs. * @return {Promise<string[]>} List of DIDs.
*/ */
public async consumerAssets(consumer: string) { public async consumerAssets(consumer: string) {
return (await this.ocean.keeper.conditions.accessSecretStoreCondition.getGrantedDidByConsumer(consumer)) return (await this.ocean.keeper.conditions.accessSecretStoreCondition.getGrantedDidByConsumer(
.map(({did}) => did) consumer
)).map(({ did }) => did)
} }
/** /**
@ -347,11 +410,11 @@ export class OceanAssets extends Instantiable {
page: 1, page: 1,
offset: 100, offset: 100,
query: { query: {
value: 1, value: 1
}, },
sort: { sort: {
value: 1, value: 1
}, }
} as SearchQuery) } as SearchQuery)
} }
} }

View File

@ -1,20 +1,21 @@
import Account from "./Account" import Account from './Account'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
const defaultAuthMessage = "Ocean Protocol Authentication" const defaultAuthMessage = 'Ocean Protocol Authentication'
const defaultExpirationTime = 30 * 24 * 60 * 60 * 1000 // 30 days const defaultExpirationTime = 30 * 24 * 60 * 60 * 1000 // 30 days
const localStorageKey = "SquidTokens" const localStorageKey = 'SquidTokens'
/** /**
* Tokens submodule of Ocean Protocol. * Tokens submodule of Ocean Protocol.
*/ */
export class OceanAuth extends Instantiable { export class OceanAuth extends Instantiable {
/** /**
* Returns the instance of OceanAuth. * Returns the instance of OceanAuth.
* @return {Promise<OceanAuth>} * @return {Promise<OceanAuth>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<OceanAuth> { public static async getInstance(
config: InstantiableConfig
): Promise<OceanAuth> {
const instance = new OceanAuth() const instance = new OceanAuth()
instance.setInstanceConfig(config) instance.setInstanceConfig(config)
@ -31,16 +32,15 @@ export class OceanAuth extends Instantiable {
const message = `${this.getMessage()}\n${time}` const message = `${this.getMessage()}\n${time}`
try { try {
const signature = await this.ocean.utils.signature const signature = await this.ocean.utils.signature.signText(
.signText( message,
message, account.getId(),
account.getId(), account.getPassword()
account.getPassword(), )
)
return `${signature}-${time}` return `${signature}-${time}`
} catch { } catch {
throw new Error("User denied the signature.") throw new Error('User denied the signature.')
} }
} }
@ -51,16 +51,16 @@ export class OceanAuth extends Instantiable {
*/ */
public async check(token: string): Promise<string> { public async check(token: string): Promise<string> {
const expiration = this.getExpiration() const expiration = this.getExpiration()
const [signature, timestamp] = token.split("-") const [signature, timestamp] = token.split('-')
const message = `${this.getMessage()}\n${timestamp}` const message = `${this.getMessage()}\n${timestamp}`
if (((+timestamp * 1000) + expiration) < Date.now()) { if (+timestamp * 1000 + expiration < Date.now()) {
return `0x${"0".repeat(40)}` return `0x${'0'.repeat(40)}`
} }
return this.web3.utils.toChecksumAddress( return this.web3.utils.toChecksumAddress(
await this.ocean.utils.signature.verifyText(message, signature), await this.ocean.utils.signature.verifyText(message, signature)
) )
} }
@ -100,7 +100,7 @@ export class OceanAuth extends Instantiable {
* @return {Promise<boolean>} Is stored and valid. * @return {Promise<boolean>} Is stored and valid.
*/ */
public async isStored(account: Account): Promise<boolean> { public async isStored(account: Account): Promise<boolean> {
return !!await this.restore(account) return !!(await this.restore(account))
} }
private writeToken(address: string, token: string) { private writeToken(address: string, token: string) {
@ -108,10 +108,13 @@ export class OceanAuth extends Instantiable {
const storedTokens = localStorage.getItem(localStorageKey) const storedTokens = localStorage.getItem(localStorageKey)
const tokens = storedTokens ? JSON.parse(storedTokens) : {} const tokens = storedTokens ? JSON.parse(storedTokens) : {}
localStorage.setItem(localStorageKey, JSON.stringify({ localStorage.setItem(
...tokens, localStorageKey,
[address]: token, JSON.stringify({
})) ...tokens,
[address]: token
})
)
} }
private readToken(address: string) { private readToken(address: string) {
@ -124,9 +127,11 @@ export class OceanAuth extends Instantiable {
private getLocalStorage() { private getLocalStorage() {
try { try {
localStorage.getItem("") localStorage.getItem('')
} catch { } catch {
throw new Error("LocalStorage is not supported. This feature is only available on browsers.") throw new Error(
'LocalStorage is not supported. This feature is only available on browsers.'
)
} }
return localStorage return localStorage
} }

View File

@ -1,18 +1,18 @@
import Account from "./Account" import Account from './Account'
import { noDidPrefixed } from "../utils" import { noDidPrefixed } from '../utils'
import { File } from "../ddo/MetaData" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/** /**
* SecretStore submodule of Ocean Protocol. * SecretStore submodule of Ocean Protocol.
*/ */
export class OceanSecretStore extends Instantiable { export class OceanSecretStore extends Instantiable {
/** /**
* Returns the instance of OceanSecretStore. * Returns the instance of OceanSecretStore.
* @return {Promise<OceanSecretStore>} * @return {Promise<OceanSecretStore>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<OceanSecretStore> { public static async getInstance(
config: InstantiableConfig
): Promise<OceanSecretStore> {
const instance = new OceanSecretStore() const instance = new OceanSecretStore()
instance.setInstanceConfig(config) instance.setInstanceConfig(config)
@ -27,11 +27,24 @@ export class OceanSecretStore extends Instantiable {
* @param {string} publisher Publisher account. * @param {string} publisher Publisher account.
* @return {Promise<string>} Encrypted text. * @return {Promise<string>} Encrypted text.
*/ */
public async encrypt(did: string, document: any, publisher: Account): Promise<string> { public async encrypt(
did: string,
document: any,
publisher: Account
): Promise<string> {
const signature = const signature =
await publisher.getToken() (await publisher.getToken()) ||
|| await this.ocean.utils.signature.signText(noDidPrefixed(did), publisher.getId(), publisher.getPassword()) (await this.ocean.utils.signature.signText(
noDidPrefixed(did),
publisher.getId(),
publisher.getPassword()
))
return await this.ocean.brizo.encrypt(noDidPrefixed(did), signature, document, publisher.getId()) return this.ocean.brizo.encrypt(
noDidPrefixed(did),
signature,
document,
publisher.getId()
)
} }
} }

View File

@ -1,16 +1,17 @@
import Account from "./Account" import Account from './Account'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
/** /**
* Tokens submodule of Ocean Protocol. * Tokens submodule of Ocean Protocol.
*/ */
export class OceanTokens extends Instantiable { export class OceanTokens extends Instantiable {
/** /**
* Returns the instance of OceanTokens. * Returns the instance of OceanTokens.
* @return {Promise<OceanTokens>} * @return {Promise<OceanTokens>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<OceanTokens> { public static async getInstance(
config: InstantiableConfig
): Promise<OceanTokens> {
const instance = new OceanTokens() const instance = new OceanTokens()
instance.setInstanceConfig(config) instance.setInstanceConfig(config)
@ -24,10 +25,12 @@ export class OceanTokens extends Instantiable {
* @param {Account} from Sender account address. * @param {Account} from Sender account address.
* @return {Promise<boolean>} Success, * @return {Promise<boolean>} Success,
*/ */
public async transfer(to: string, amount: number, from: Account): Promise<boolean> { public async transfer(
this.ocean.keeper to: string,
.token amount: number,
.transfer(to, amount, from.getId()) from: Account
): Promise<boolean> {
this.ocean.keeper.token.transfer(to, amount, from.getId())
return true return true
} }

View File

@ -1,13 +1,13 @@
import * as keeperPackageJson from "@oceanprotocol/keeper-contracts/package.json" import * as keeperPackageJson from '@oceanprotocol/keeper-contracts/package.json'
import * as metadata from "../metadata.json" import * as metadata from '../metadata.json'
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
export enum OceanPlatformTechStatus { export enum OceanPlatformTechStatus {
Loading = "Loading", Loading = 'Loading',
Unknown = "Unknown", Unknown = 'Unknown',
Stopped = "Stopped", Stopped = 'Stopped',
Working = "Working", Working = 'Working'
} }
export interface OceanPlatformTech { export interface OceanPlatformTech {
@ -20,7 +20,7 @@ export interface OceanPlatformTech {
export interface OceanPlatformKeeperTech extends OceanPlatformTech { export interface OceanPlatformKeeperTech extends OceanPlatformTech {
network?: string network?: string
keeperVersion?: string keeperVersion?: string
contracts?: {[contractName: string]: string} contracts?: { [contractName: string]: string }
} }
export interface OceanPlatformVersions { export interface OceanPlatformVersions {
@ -30,7 +30,7 @@ export interface OceanPlatformVersions {
status: { status: {
ok: boolean ok: boolean
contracts: boolean contracts: boolean
network: boolean, network: boolean
} }
} }
@ -38,12 +38,13 @@ export interface OceanPlatformVersions {
* Versions submodule of Ocean Protocol. * Versions submodule of Ocean Protocol.
*/ */
export class OceanVersions extends Instantiable { export class OceanVersions extends Instantiable {
/** /**
* Returns the instance of OceanVersions. * Returns the instance of OceanVersions.
* @return {Promise<OceanVersions>} * @return {Promise<OceanVersions>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<OceanVersions> { public static async getInstance(
config: InstantiableConfig
): Promise<OceanVersions> {
const instance = new OceanVersions() const instance = new OceanVersions()
instance.setInstanceConfig(config) instance.setInstanceConfig(config)
@ -55,50 +56,62 @@ export class OceanVersions extends Instantiable {
// Squid // Squid
versions.squid = { versions.squid = {
name: "Squid-js", name: 'Squid-js',
version: metadata.version, version: metadata.version,
commit: metadata.commit, commit: metadata.commit,
status: OceanPlatformTechStatus.Working, status: OceanPlatformTechStatus.Working,
network: (await this.ocean.keeper.getNetworkName()).toLowerCase(), network: (await this.ocean.keeper.getNetworkName()).toLowerCase(),
keeperVersion: keeperPackageJson.version, keeperVersion: keeperPackageJson.version,
contracts: Object.values(await this.ocean.keeper.getAllInstances()) contracts: Object.values(
.reduce((acc, {contractName, address}) => ({ await this.ocean.keeper.getAllInstances()
).reduce(
(acc, { contractName, address }) => ({
...acc, ...acc,
[contractName]: address, [contractName]: address
}), {}), }),
{}
)
} }
// Brizo // Brizo
try { try {
const {contracts, "keeper-version": keeperVersion, network, software: name, version} = const {
await this.ocean.brizo.getVersionInfo() contracts,
'keeper-version': keeperVersion,
network,
software: name,
version
} = await this.ocean.brizo.getVersionInfo()
versions.brizo = { versions.brizo = {
name, name,
status: OceanPlatformTechStatus.Working, status: OceanPlatformTechStatus.Working,
version, version,
contracts, contracts,
network, network,
keeperVersion: keeperVersion.replace(/^v/, ""), keeperVersion: keeperVersion.replace(/^v/, '')
} }
} catch { } catch {
versions.brizo = { versions.brizo = {
name: "Brizo", name: 'Brizo',
status: OceanPlatformTechStatus.Stopped, status: OceanPlatformTechStatus.Stopped
} }
} }
// Aquarius // Aquarius
try { try {
const {software: name, version} = await this.ocean.aquarius.getVersionInfo() const {
software: name,
version
} = await this.ocean.aquarius.getVersionInfo()
versions.aquarius = { versions.aquarius = {
name, name,
status: OceanPlatformTechStatus.Working, status: OceanPlatformTechStatus.Working,
version, version
} }
} catch { } catch {
versions.aquarius = { versions.aquarius = {
name: "Aquarius", name: 'Aquarius',
status: OceanPlatformTechStatus.Stopped, status: OceanPlatformTechStatus.Stopped
} }
} }
@ -106,22 +119,22 @@ export class OceanVersions extends Instantiable {
const techs: OceanPlatformKeeperTech[] = Object.values(versions as any) const techs: OceanPlatformKeeperTech[] = Object.values(versions as any)
const networks = techs const networks = techs
.map(({network}) => network) .map(({ network }) => network)
.filter((_) => !!_) .filter(_ => !!_)
.reduce((acc, network) => ({...acc, [network]: true}), {}) .reduce((acc, network) => ({ ...acc, [network]: true }), {})
let contractStatus = true let contractStatus = true
const contractList = techs const contractList = techs
.map(({contracts}) => contracts) .map(({ contracts }) => contracts)
.filter((_) => !!_) .filter(_ => !!_)
Array.from(contractList.map(Object.keys)) Array.from(contractList.map(Object.keys))
.reduce((acc, _) => [...acc, ..._], []) .reduce((acc, _) => [...acc, ..._], [])
.filter((_, i, list) => list.indexOf(_) === i) .filter((_, i, list) => list.indexOf(_) === i)
.forEach((name) => { .forEach(name => {
let address let address
contractList contractList
.map((_) => _[name]) .map(_ => _[name])
.forEach((_) => { .forEach(_ => {
if (!address) { if (!address) {
address = _ address = _
return return
@ -133,9 +146,11 @@ export class OceanVersions extends Instantiable {
}) })
versions.status = { versions.status = {
ok: !techs.find(({status}) => status !== OceanPlatformTechStatus.Working), ok: !techs.find(
({ status }) => status !== OceanPlatformTechStatus.Working
),
network: Object.keys(networks).length === 1, network: Object.keys(networks).length === 1,
contracts: contractStatus, contracts: contractStatus
} }
return versions return versions

View File

@ -1,19 +1,20 @@
import { Instantiable, InstantiableConfig } from "../../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
import { ServiceAgreement } from "./ServiceAgreement" import { ServiceAgreement } from './ServiceAgreement'
import { SignatureUtils } from "./SignatureUtils" import { SignatureUtils } from './SignatureUtils'
import { WebServiceConnector } from "./WebServiceConnector" import { WebServiceConnector } from './WebServiceConnector'
/** /**
* Utils internal submodule of Ocean Protocol. * Utils internal submodule of Ocean Protocol.
*/ */
export class OceanUtils extends Instantiable { export class OceanUtils extends Instantiable {
/** /**
* Returns the instance of OceanUtils. * Returns the instance of OceanUtils.
* @return {Promise<OceanUtils>} * @return {Promise<OceanUtils>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<OceanUtils> { public static async getInstance(
config: InstantiableConfig
): Promise<OceanUtils> {
const instance = new OceanUtils() const instance = new OceanUtils()
instance.setInstanceConfig(config) instance.setInstanceConfig(config)

View File

@ -1,13 +1,11 @@
import * as Web3 from "web3" import { ServiceAgreementTemplateCondition } from '../../ddo/ServiceAgreementTemplate'
import { ServiceAgreementTemplateCondition } from "../../ddo/ServiceAgreementTemplate" import { DDO } from '../../ddo/DDO'
import { DDO } from "../../ddo/DDO" import { ServiceAccess } from '../../ddo/Service'
import { ServiceAccess } from "../../ddo/Service" import Account from '../Account'
import Account from "../Account" import { zeroX } from '../../utils'
import { zeroX } from "../../utils" import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
import { Instantiable, InstantiableConfig } from "../../Instantiable.abstract"
export class ServiceAgreement extends Instantiable { export class ServiceAgreement extends Instantiable {
constructor(config: InstantiableConfig) { constructor(config: InstantiableConfig) {
super() super()
this.setInstanceConfig(config) this.setInstanceConfig(config)
@ -18,15 +16,20 @@ export class ServiceAgreement extends Instantiable {
serviceDefinitionId: string, serviceDefinitionId: string,
serviceAgreementId: string, serviceAgreementId: string,
agreementConditionsIds: string[], agreementConditionsIds: string[],
consumer: Account, consumer: Account
): Promise<string> { ): Promise<string> {
const service = ddo.findServiceById<'Access'>(serviceDefinitionId)
const service = ddo.findServiceById<"Access">(serviceDefinitionId) const timelockValues: number[] = this.getTimeValuesFromService(
const timelockValues: number[] = this.getTimeValuesFromService(service, "timelock") service,
const timeoutValues: number[] = this.getTimeValuesFromService(service, "timeout") 'timelock'
)
const timeoutValues: number[] = this.getTimeValuesFromService(
service,
'timeout'
)
if (!service.templateId) { if (!service.templateId) {
throw new Error("TemplateId not found in DDO.") throw new Error('TemplateId not found in DDO.')
} }
const serviceAgreementHashSignature = await this.createHashSignature( const serviceAgreementHashSignature = await this.createHashSignature(
@ -35,10 +38,10 @@ export class ServiceAgreement extends Instantiable {
agreementConditionsIds, agreementConditionsIds,
timelockValues, timelockValues,
timeoutValues, timeoutValues,
consumer, consumer
) )
this.logger.debug("SA hash signature:", serviceAgreementHashSignature) this.logger.debug('SA hash signature:', serviceAgreementHashSignature)
return serviceAgreementHashSignature return serviceAgreementHashSignature
} }
@ -49,19 +52,21 @@ export class ServiceAgreement extends Instantiable {
valueHashes: string[], valueHashes: string[],
timelockValues: number[], timelockValues: number[],
timeoutValues: number[], timeoutValues: number[],
consumer: Account, consumer: Account
): Promise<string> { ): Promise<string> {
const serviceAgreementHash = this.hashServiceAgreement( const serviceAgreementHash = this.hashServiceAgreement(
templateId, templateId,
serviceAgreementId, serviceAgreementId,
valueHashes, valueHashes,
timelockValues, timelockValues,
timeoutValues, timeoutValues
) )
const serviceAgreementHashSignature = await this.ocean.utils.signature const serviceAgreementHashSignature = await this.ocean.utils.signature.signText(
.signText(serviceAgreementHash, consumer.getId(), consumer.getPassword()) serviceAgreementHash,
consumer.getId(),
consumer.getPassword()
)
return serviceAgreementHashSignature return serviceAgreementHashSignature
} }
@ -71,23 +76,26 @@ export class ServiceAgreement extends Instantiable {
serviceAgreementId: string, serviceAgreementId: string,
valueHashes: string[], valueHashes: string[],
timelocks: number[], timelocks: number[],
timeouts: number[], timeouts: number[]
): string { ): string {
const args = [ const args = [
{type: "address", value: zeroX(serviceAgreementTemplateId)}, { type: 'address', value: zeroX(serviceAgreementTemplateId) },
{type: "bytes32[]", value: valueHashes.map(zeroX)}, { type: 'bytes32[]', value: valueHashes.map(zeroX) },
{type: "uint256[]", value: timelocks}, { type: 'uint256[]', value: timelocks },
{type: "uint256[]", value: timeouts}, { type: 'uint256[]', value: timeouts },
{type: "bytes32", value: zeroX(serviceAgreementId)}, { type: 'bytes32', value: zeroX(serviceAgreementId) }
] ]
return this.web3.utils.soliditySha3(...args).toString("hex") return this.web3.utils.soliditySha3(...args).toString('hex')
} }
private getTimeValuesFromService(service: ServiceAccess, type: "timeout" | "timelock"): number[] { private getTimeValuesFromService(
const timeoutValues: number[] = service.serviceAgreementTemplate.conditions service: ServiceAccess,
.map((condition: ServiceAgreementTemplateCondition) => condition[type]) type: 'timeout' | 'timelock'
): number[] {
const timeoutValues: number[] = service.serviceAgreementTemplate.conditions.map(
(condition: ServiceAgreementTemplateCondition) => condition[type]
)
return timeoutValues return timeoutValues
} }

View File

@ -1,28 +1,34 @@
import { Instantiable, InstantiableConfig } from "../../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
export class SignatureUtils extends Instantiable { export class SignatureUtils extends Instantiable {
constructor(config: InstantiableConfig) { constructor(config: InstantiableConfig) {
super() super()
this.setInstanceConfig(config) this.setInstanceConfig(config)
} }
public async signText(text: string, publicKey: string, password?: string): Promise<string> { public async signText(
const isMetaMask = this.web3 && this.web3.currentProvider && this.web3.currentProvider.isMetaMask text: string,
publicKey: string,
password?: string
): Promise<string> {
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
this.web3.currentProvider.isMetaMask
try { try {
return await this.web3.eth.personal.sign(text, publicKey, password) return await this.web3.eth.personal.sign(text, publicKey, password)
} catch (e) { } catch (e) {
if (isMetaMask) { if (isMetaMask) {
throw e throw e
} }
this.logger.warn("Error on personal sign.") this.logger.warn('Error on personal sign.')
this.logger.warn(e) this.logger.warn(e)
try { try {
return await this.web3.eth.sign(text, publicKey, password) return await this.web3.eth.sign(text, publicKey, password)
} catch (e2) { } catch (e2) {
this.logger.error("Error on sign.") this.logger.error('Error on sign.')
this.logger.error(e2) this.logger.error(e2)
throw new Error("Error executing personal sign") throw new Error('Error executing personal sign')
} }
} }
} }

View File

@ -1,11 +1,10 @@
import fetch, { BodyInit, RequestInit, Response } from "node-fetch" import fetch, { BodyInit, RequestInit, Response } from 'node-fetch'
import { Instantiable, InstantiableConfig } from "../../Instantiable.abstract" import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
/** /**
* Provides a common interface to web services. * Provides a common interface to web services.
*/ */
export class WebServiceConnector extends Instantiable { export class WebServiceConnector extends Instantiable {
constructor(config: InstantiableConfig) { constructor(config: InstantiableConfig) {
super() super()
this.setInstanceConfig(config) this.setInstanceConfig(config)
@ -13,30 +12,30 @@ export class WebServiceConnector extends Instantiable {
public post(url: string, payload: BodyInit): Promise<Response> { public post(url: string, payload: BodyInit): Promise<Response> {
return this.fetch(url, { return this.fetch(url, {
method: "POST", method: 'POST',
body: payload, body: payload,
headers: { headers: {
"Content-type": "application/json", 'Content-type': 'application/json'
}, }
}) })
} }
public get(url: string): Promise<Response> { public get(url: string): Promise<Response> {
return this.fetch(url, { return this.fetch(url, {
method: "GET", method: 'GET',
headers: { headers: {
"Content-type": "application/json", 'Content-type': 'application/json'
}, }
}) })
} }
public put(url: string, payload: BodyInit): Promise<Response> { public put(url: string, payload: BodyInit): Promise<Response> {
return this.fetch(url, { return this.fetch(url, {
method: "PUT", method: 'PUT',
body: payload, body: payload,
headers: { headers: {
"Content-type": "application/json", 'Content-type': 'application/json'
}, }
}) })
} }

View File

@ -1,34 +1,37 @@
import Config from "./models/Config" import Config from './models/Config'
import Account from "./ocean/Account" import Account from './ocean/Account'
import DID from "./ocean/DID" import DID from './ocean/DID'
import { Ocean } from "./ocean/Ocean" import { Ocean } from './ocean/Ocean'
import { LoggerInstance as Logger} from "./utils/Logger" import { LoggerInstance as Logger } from './utils/Logger'
import Keeper from "./keeper/Keeper" import Keeper from './keeper/Keeper'
import * as templates from "./keeper/contracts/templates" import * as templates from './keeper/contracts/templates'
import * as conditions from "./keeper/contracts/conditions" import * as conditions from './keeper/contracts/conditions'
import * as utils from "./utils" import * as utils from './utils'
// Exports // Exports
export * from "./ddo/DDO" export * from './ddo/DDO'
export * from "./ddo/MetaData" export * from './ddo/MetaData'
export { OrderProgressStep, CreateProgressStep } from "./ocean/OceanAssets" export { OrderProgressStep, CreateProgressStep } from './ocean/OceanAssets'
export { OceanPlatformTechStatus, OceanPlatformTech, OceanPlatformKeeperTech, OceanPlatformVersions } from "./ocean/OceanVersions" export {
OceanPlatformTechStatus,
OceanPlatformTech,
OceanPlatformKeeperTech,
OceanPlatformVersions
} from './ocean/OceanVersions'
export { AgreementTemplate } from "./keeper/contracts/templates" export { AgreementTemplate } from './keeper/contracts/templates'
export { Condition, ConditionState } from "./keeper/contracts/conditions" export { Condition, ConditionState } from './keeper/contracts/conditions'
export { export {
Ocean, Ocean,
Account, Account,
Config, Config,
DID, DID,
Logger, Logger,
Keeper, Keeper,
conditions, conditions,
templates, templates,
utils, utils
} }

View File

@ -1,35 +1,49 @@
import { LoggerInstance } from "./Logger" import { LoggerInstance } from './Logger'
// Ox transformer // Ox transformer
export const zeroX = (input: string) => zeroXTransformer(input, true) export const zeroX = (input: string) => zeroXTransformer(input, true)
export const noZeroX = (input: string) => zeroXTransformer(input, false) export const noZeroX = (input: string) => zeroXTransformer(input, false)
export function zeroXTransformer(input: string = "", zeroOutput: boolean) { export function zeroXTransformer(input: string = '', zeroOutput: boolean) {
const {valid, output} = inputMatch(input, /^(?:0x)*([a-f0-9]+)$/i, "zeroXTransformer") const { valid, output } = inputMatch(
return (zeroOutput && valid ? "0x" : "") + output input,
/^(?:0x)*([a-f0-9]+)$/i,
'zeroXTransformer'
)
return (zeroOutput && valid ? '0x' : '') + output
} }
// did:op: transformer // did:op: transformer
export const didPrefixed = (input: string) => didTransformer(input, true) export const didPrefixed = (input: string) => didTransformer(input, true)
export const noDidPrefixed = (input: string) => didTransformer(input, false) export const noDidPrefixed = (input: string) => didTransformer(input, false)
export function didTransformer(input: string = "", prefixOutput: boolean) { export function didTransformer(input: string = '', prefixOutput: boolean) {
const {valid, output} = inputMatch(input, /^(?:0x|did:op:)*([a-f0-9]{64})$/i, "didTransformer") const { valid, output } = inputMatch(
return (prefixOutput && valid ? "did:op:" : "") + output input,
/^(?:0x|did:op:)*([a-f0-9]{64})$/i,
'didTransformer'
)
return (prefixOutput && valid ? 'did:op:' : '') + output
} }
// 0x + did:op: transformer // 0x + did:op: transformer
export const didZeroX = (input: string) => zeroX(didTransformer(input, false)) export const didZeroX = (input: string) => zeroX(didTransformer(input, false))
// Shared functions // Shared functions
function inputMatch(input: string, regexp: RegExp, conversorName: string): {valid: boolean, output: string} { function inputMatch(
if (typeof input !== "string") { input: string,
LoggerInstance.debug("Not input string:") regexp: RegExp,
conversorName: string
): { valid: boolean; output: string } {
if (typeof input !== 'string') {
LoggerInstance.debug('Not input string:')
LoggerInstance.debug(input) LoggerInstance.debug(input)
throw new Error(`[${conversorName}] Expected string, input type: ${typeof input}`) throw new Error(
`[${conversorName}] Expected string, input type: ${typeof input}`
)
} }
const match = input.match(regexp) const match = input.match(regexp)
if (!match) { if (!match) {
LoggerInstance.warn(`[${conversorName}] Input transformation failed.`) LoggerInstance.warn(`[${conversorName}] Input transformation failed.`)
return {valid: false, output: input} return { valid: false, output: input }
} }
return {valid: true, output: match[1]} return { valid: true, output: match[1] }
} }

View File

@ -1,25 +1,33 @@
import { DDO } from "../ddo/DDO" import { DDO } from '../ddo/DDO'
import { ServiceAgreementTemplateCondition, ServiceAgreementTemplateParameter } from "../ddo/ServiceAgreementTemplate" import {
ServiceAgreementTemplateCondition,
ServiceAgreementTemplateParameter
} from '../ddo/ServiceAgreementTemplate'
function fillParameterWithDDO(parameter: ServiceAgreementTemplateParameter, ddo: DDO): ServiceAgreementTemplateParameter { function fillParameterWithDDO(
const getValue = (name) => { parameter: ServiceAgreementTemplateParameter,
ddo: DDO
): ServiceAgreementTemplateParameter {
const getValue = name => {
switch (name) { switch (name) {
case "amount": case 'amount':
case "price": case 'price':
return String(ddo.findServiceByType("Metadata").metadata.base.price) return String(
case "assetId": ddo.findServiceByType('Metadata').metadata.base.price
case "documentId": )
case "documentKeyId": case 'assetId':
case 'documentId':
case 'documentKeyId':
return ddo.shortId() return ddo.shortId()
case "rewardAddress": case 'rewardAddress':
return ddo.publicKey[0].owner return ddo.publicKey[0].owner
} }
return "" return ''
} }
const value = getValue(parameter.name.replace(/^_/, "")) const value = getValue(parameter.name.replace(/^_/, ''))
return {...parameter, value} return { ...parameter, value }
} }
/** /**
@ -28,13 +36,14 @@ function fillParameterWithDDO(parameter: ServiceAgreementTemplateParameter, ddo:
* @param {DDO} ddo DDO related to this conditions. * @param {DDO} ddo DDO related to this conditions.
* @return {ServiceAgreementTemplateCondition[]} Filled conditions. * @return {ServiceAgreementTemplateCondition[]} Filled conditions.
*/ */
export function fillConditionsWithDDO(conditions: ServiceAgreementTemplateCondition[], ddo: DDO): ServiceAgreementTemplateCondition[] { export function fillConditionsWithDDO(
return conditions conditions: ServiceAgreementTemplateCondition[],
.map((condition) => ({ ddo: DDO
...condition, ): ServiceAgreementTemplateCondition[] {
parameters: condition.parameters return conditions.map(condition => ({
.map((parameter) => ({ ...condition,
...fillParameterWithDDO(parameter, ddo), parameters: condition.parameters.map(parameter => ({
})), ...fillParameterWithDDO(parameter, ddo)
})) }))
}))
} }

View File

@ -1,9 +1,9 @@
import {v4} from "uuid" import { v4 } from 'uuid'
export function generateId(length = 64) { export function generateId(length = 64) {
let id = "" let id = ''
while (id.length < length) { while (id.length < length) {
id += v4().replace(/-/g, "") id += v4().replace(/-/g, '')
} }
return id.substr(0, length) return id.substr(0, length)
} }

View File

@ -3,35 +3,34 @@ export enum LogLevel {
Error = 0, Error = 0,
Warn = 1, Warn = 1,
Log = 2, Log = 2,
Verbose = 3, Verbose = 3
} }
export class Logger { export class Logger {
constructor(private logLevel: LogLevel = LogLevel.Verbose) {}
constructor(private logLevel: LogLevel = LogLevel.Verbose) { }
public setLevel(logLevel: LogLevel) { public setLevel(logLevel: LogLevel) {
this.logLevel = logLevel this.logLevel = logLevel
} }
public bypass(...args: any[]) { public bypass(...args: any[]) {
this.dispatch("log", -Infinity as any, ...args) this.dispatch('log', -Infinity as any, ...args)
} }
public debug(...args: any[]) { public debug(...args: any[]) {
this.dispatch("debug", LogLevel.Verbose, ...args) this.dispatch('debug', LogLevel.Verbose, ...args)
} }
public log(...args: any[]) { public log(...args: any[]) {
this.dispatch("log", LogLevel.Log, ...args) this.dispatch('log', LogLevel.Log, ...args)
} }
public warn(...args: any[]) { public warn(...args: any[]) {
this.dispatch("warn", LogLevel.Warn, ...args) this.dispatch('warn', LogLevel.Warn, ...args)
} }
public error(...args: any[]) { public error(...args: any[]) {
this.dispatch("error", LogLevel.Error, ...args) this.dispatch('error', LogLevel.Error, ...args)
} }
private dispatch(verb: string, level: LogLevel, ...args: any[]) { private dispatch(verb: string, level: LogLevel, ...args: any[]) {

View File

@ -1,12 +1,17 @@
const zipObject = (keys = [], values = []) => { const zipObject = (keys = [], values = []) => {
return keys.reduce((acc, key, index) => ({ return keys.reduce(
...acc, (acc, key, index) => ({
[key]: values[index], ...acc,
}), {}) [key]: values[index]
}),
{}
)
} }
export const objectPromiseAll = async (obj: {[key: string]: Promise<any>}) => { export const objectPromiseAll = async (obj: {
const keys = Object.keys(obj) [key: string]: Promise<any>
const result = await Promise.all(Object.values(obj)) }) => {
return zipObject(keys, result) const keys = Object.keys(obj)
const result = await Promise.all(Object.values(obj))
return zipObject(keys, result)
} }

View File

@ -1,37 +1,47 @@
export class SubscribableObserver<T, P> { export class SubscribableObserver<T, P> {
public completed: boolean = false public completed: boolean = false
private subscriptions = new Set<{onNext?: (next: T) => void, onComplete?: (complete: P) => void, onError?: (error: any) => void}>() private subscriptions = new Set<{
onNext?: (next: T) => void
onComplete?: (complete: P) => void
onError?: (error: any) => void
}>()
public subscribe(onNext?: (next: T) => void, onComplete?: (complete: P) => void, onError?: (error: any) => void) { public subscribe(
onNext?: (next: T) => void,
onComplete?: (complete: P) => void,
onError?: (error: any) => void
) {
if (this.completed) { if (this.completed) {
throw new Error("Observer completed.") throw new Error('Observer completed.')
} }
const subscription = {onNext, onComplete, onError} const subscription = { onNext, onComplete, onError }
this.subscriptions.add(subscription) this.subscriptions.add(subscription)
return { return {
unsubscribe: () => this.subscriptions.delete(subscription), unsubscribe: () => this.subscriptions.delete(subscription)
} }
} }
public next(next?: T): void { public next(next?: T): void {
this.emit("onNext", next) this.emit('onNext', next)
} }
public complete(resolve?: P): void { public complete(resolve?: P): void {
this.emit("onComplete", resolve) this.emit('onComplete', resolve)
this.unsubscribe() this.unsubscribe()
} }
public error(error?: any): void { public error(error?: any): void {
this.emit("onError", error) this.emit('onError', error)
this.unsubscribe() this.unsubscribe()
} }
private emit(type: "onNext" | "onComplete" | "onError", value: any) { private emit(type: 'onNext' | 'onComplete' | 'onError', value: any) {
Array.from(this.subscriptions) Array.from(this.subscriptions)
.map((subscription) => subscription[type]) .map(subscription => subscription[type])
.filter((callback: any) => callback && typeof callback === "function") .filter(
(callback: any) => callback && typeof callback === 'function'
)
.forEach((callback: any) => callback(value)) .forEach((callback: any) => callback(value))
} }

View File

@ -1,18 +1,19 @@
import { SubscribableObserver } from "./SubscribableObserver" import { SubscribableObserver } from './SubscribableObserver'
export class SubscribablePromise<T extends any, P extends any> { export class SubscribablePromise<T extends any, P extends any> {
private observer = new SubscribableObserver<T, P>() private observer = new SubscribableObserver<T, P>()
private promise = Object.assign( private promise = Object.assign(
new Promise<P>((resolve, reject) => { new Promise<P>((resolve, reject) => {
setTimeout(() => { setTimeout(() => {
this.observer this.observer.subscribe(undefined, resolve, reject)
.subscribe(undefined, resolve, reject)
}, 0) }, 0)
}), }),
this, this
) )
constructor(executor: (observer: SubscribableObserver<T, P>) => void | Promise<P>) { constructor(
executor: (observer: SubscribableObserver<T, P>) => void | Promise<P>
) {
// Defear // Defear
setTimeout(() => this.init(executor), 1) setTimeout(() => this.init(executor), 1)
} }
@ -26,7 +27,10 @@ export class SubscribablePromise<T extends any, P extends any> {
return this return this
} }
public then(onfulfilled?: (value: P) => any, onrejected?: (error: any) => any) { public then(
onfulfilled?: (value: P) => any,
onrejected?: (error: any) => any
) {
return Object.assign(this.promise.then(onfulfilled, onrejected), this) return Object.assign(this.promise.then(onfulfilled, onrejected), this)
} }
@ -38,17 +42,19 @@ export class SubscribablePromise<T extends any, P extends any> {
return Object.assign(this.promise.finally(onfinally), this) return Object.assign(this.promise.finally(onfinally), this)
} }
private init(executor: (observer: SubscribableObserver<T, P>) => void | Promise<P>) { private init(
executor: (observer: SubscribableObserver<T, P>) => void | Promise<P>
) {
const execution = executor(this.observer) const execution = executor(this.observer)
Promise.resolve(execution as any) Promise.resolve(execution as any)
.then((result) => { .then(result => {
if (typeof (execution as any).then === "function") { if (typeof (execution as any).then === 'function') {
this.observer.complete(result) this.observer.complete(result)
} }
}) })
.catch((result) => { .catch(result => {
if (typeof (execution as any).then === "function") { if (typeof (execution as any).then === 'function') {
this.observer.error(result) this.observer.error(result)
} }
}) })

View File

@ -1,7 +1,7 @@
export * from "./PromiseResolver" export * from './PromiseResolver'
export * from "./Logger" export * from './Logger'
export * from "./ConversionTypeHelpers" export * from './ConversionTypeHelpers'
export * from "./GeneratorHelpers" export * from './GeneratorHelpers'
export * from "./DDOHelpers" export * from './DDOHelpers'
export * from "./SubscribablePromise" export * from './SubscribablePromise'
export * from "./SubscribableObserver" export * from './SubscribableObserver'

View File

@ -1,11 +1,9 @@
import * as assert from "assert" import * as assert from 'assert'
import * as squid from "../src/squid" import * as squid from '../src/squid'
describe("Squid", () => { describe('Squid', () => {
describe('interface', () => {
describe("interface", () => { it('should expose Ocean', async () => {
it("should expose Ocean", async () => {
assert(squid.Ocean) assert(squid.Ocean)
}) })
}) })

View File

@ -1,7 +1,7 @@
import { generateId } from "../src/utils/GeneratorHelpers" import { generateId } from '../src/utils/GeneratorHelpers'
export default class TestIdGenerator { export default class TestIdGenerator {
public static generatePrefixedId() { public static generatePrefixedId() {
return "0x" + generateId() return '0x' + generateId()
} }
} }

View File

@ -1,118 +1,124 @@
import { assert, spy, use } from "chai" import { assert, spy, use } from 'chai'
import * as spies from "chai-spies" import * as spies from 'chai-spies'
import { Ocean } from "../../src/ocean/Ocean" import { Ocean } from '../../src/ocean/Ocean'
import { Aquarius } from "../../src/aquarius/Aquarius" import { Aquarius, SearchQuery } from '../../src/aquarius/Aquarius'
import { SearchQuery } from "../../src/aquarius/Aquarius" import { DDO } from '../../src/ddo/DDO'
import { DDO } from "../../src/ddo/DDO" import DID from '../../src/ocean/DID'
import DID from "../../src/ocean/DID" import config from '../config'
import config from "../config"
use(spies) use(spies)
const reponsify = async (data) => ({ok: true, json: () => Promise.resolve(data)}) const reponsify = async data => ({
ok: true,
describe("Aquarius", () => { json: () => Promise.resolve(data)
})
describe('Aquarius', () => {
let ocean: Ocean let ocean: Ocean
let aquarius: Aquarius let aquarius: Aquarius
// tslint:disable-next-line /* eslint-disable @typescript-eslint/camelcase */
const getResults = (results: DDO[], page = 0, total_pages = 1, total_results = 1) => const getResults = (
({results, page, total_pages, total_results}) results: DDO[],
page = 0,
total_pages = 1,
total_results = 1
) => ({ results, page, total_pages, total_results })
/* eslint-enable @typescript-eslint/camelcase */
beforeEach(async () => { beforeEach(async () => {
ocean = await Ocean.getInstance(config) ocean = await Ocean.getInstance(config)
aquarius = ocean.aquarius aquarius = ocean.aquarius // eslint-disable-line prefer-destructuring
}) })
afterEach(() => { afterEach(() => {
spy.restore() spy.restore()
}) })
describe("#queryMetadata()", () => { describe('#queryMetadata()', () => {
const query = { const query = {
offset: 100, offset: 100,
page: 1, page: 1,
query: { query: {
value: 1, value: 1
}, },
sort: { sort: {
value: 1, value: 1
}, },
text: "Office", text: 'Office'
} as SearchQuery } as SearchQuery
it("should query metadata", async () => { it('should query metadata', async () => {
spy.on(ocean.utils.fetch, "post", () => reponsify(getResults([new DDO()]))) spy.on(ocean.utils.fetch, 'post', () =>
reponsify(getResults([new DDO()]))
)
const result = await aquarius.queryMetadata(query) const result = await aquarius.queryMetadata(query)
assert.typeOf(result.results, "array") assert.typeOf(result.results, 'array')
assert.lengthOf(result.results, 1) assert.lengthOf(result.results, 1)
assert.equal(result.page, 0) assert.equal(result.page, 0)
assert.equal(result.totalPages, 1) assert.equal(result.totalPages, 1)
assert.equal(result.totalResults, 1) assert.equal(result.totalResults, 1)
}) })
it("should query metadata and return real ddo", async () => { it('should query metadata and return real ddo', async () => {
spy.on(ocean.utils.fetch, 'post', () =>
spy.on(ocean.utils.fetch, "post", () => reponsify(getResults([new DDO()]))) reponsify(getResults([new DDO()]))
)
const result = await aquarius.queryMetadata(query) const result = await aquarius.queryMetadata(query)
assert.typeOf(result.results, "array") assert.typeOf(result.results, 'array')
assert.lengthOf(result.results, 1) assert.lengthOf(result.results, 1)
assert.isDefined(result.results[0].findServiceById) assert.isDefined(result.results[0].findServiceById)
}) })
}) })
describe("#queryMetadataByText()", () => { describe('#queryMetadataByText()', () => {
const query = { const query = {
offset: 100, offset: 100,
page: 1, page: 1,
query: { query: {
value: 1, value: 1
}, },
sort: { sort: {
value: 1, value: 1
}, },
text: "Office", text: 'Office'
} as SearchQuery } as SearchQuery
it("should query metadata by text", async () => { it('should query metadata by text', async () => {
spy.on(ocean.utils.fetch, 'get', () =>
spy.on(ocean.utils.fetch, "get", () => reponsify(getResults([new DDO()]))) reponsify(getResults([new DDO()]))
)
const result = await aquarius.queryMetadataByText(query) const result = await aquarius.queryMetadataByText(query)
assert.typeOf(result.results, "array") assert.typeOf(result.results, 'array')
assert.lengthOf(result.results, 1) assert.lengthOf(result.results, 1)
assert.equal(result.page, 0) assert.equal(result.page, 0)
assert.equal(result.totalPages, 1) assert.equal(result.totalPages, 1)
assert.equal(result.totalResults, 1) assert.equal(result.totalResults, 1)
}) })
it("should query metadata and return real ddo", async () => { it('should query metadata and return real ddo', async () => {
spy.on(ocean.utils.fetch, 'get', () =>
spy.on(ocean.utils.fetch, "get", () => reponsify(getResults([new DDO()]))) reponsify(getResults([new DDO()]))
)
const result = await aquarius.queryMetadataByText(query) const result = await aquarius.queryMetadataByText(query)
assert.typeOf(result.results, "array") assert.typeOf(result.results, 'array')
assert.lengthOf(result.results, 1) assert.lengthOf(result.results, 1)
assert.isDefined(result.results[0].findServiceById) assert.isDefined(result.results[0].findServiceById)
}) })
}) })
describe("#storeDDO()", () => { describe('#storeDDO()', () => {
it('should store a ddo', async () => {
it("should store a ddo", async () => {
const did: DID = DID.generate() const did: DID = DID.generate()
const ddo: DDO = new DDO({ const ddo: DDO = new DDO({
id: did.getId(), id: did.getId()
}) })
spy.on(ocean.utils.fetch, "post", () => reponsify(ddo)) spy.on(ocean.utils.fetch, 'post', () => reponsify(ddo))
const result: DDO = await aquarius.storeDDO(ddo) const result: DDO = await aquarius.storeDDO(ddo)
assert(result) assert(result)
@ -120,17 +126,15 @@ describe("Aquarius", () => {
}) })
}) })
describe("#retrieveDDO()", () => { describe('#retrieveDDO()', () => {
it('should store a ddo', async () => {
it("should store a ddo", async () => {
const did: DID = DID.generate() const did: DID = DID.generate()
const ddo: DDO = new DDO({ const ddo: DDO = new DDO({
id: did.getId(), id: did.getId()
}) })
spy.on(ocean.utils.fetch, "post", () => reponsify(ddo)) spy.on(ocean.utils.fetch, 'post', () => reponsify(ddo))
spy.on(ocean.utils.fetch, "get", () => reponsify(ddo)) spy.on(ocean.utils.fetch, 'get', () => reponsify(ddo))
const storageResult: DDO = await aquarius.storeDDO(ddo) const storageResult: DDO = await aquarius.storeDDO(ddo)
assert(storageResult) assert(storageResult)

View File

@ -1,13 +1,13 @@
import { Config, LogLevel } from "../src/models/Config" import { Config, LogLevel } from '../src/models/Config'
import { LoggerInstance } from "../src/utils" import { LoggerInstance } from '../src/utils'
LoggerInstance.setLevel(LogLevel.Error) LoggerInstance.setLevel(LogLevel.Error)
export default { export default {
aquariusUri: "http://localhost:5000", aquariusUri: 'http://localhost:5000',
brizoUri: "http://localhost:3000", brizoUri: 'http://localhost:3000',
nodeUri: `http://localhost:${process.env.ETH_PORT || 8545}`, nodeUri: `http://localhost:${process.env.ETH_PORT || 8545}`,
parityUri: "http://localhost:9545", parityUri: 'http://localhost:9545',
secretStoreUri: "http://localhost:12001", secretStoreUri: 'http://localhost:12001',
verbose: LogLevel.Error, verbose: LogLevel.Error
} as Config } as Config

View File

@ -1,157 +1,175 @@
import { assert, expect, spy, use } from "chai" import { assert, expect, spy, use } from 'chai'
import * as spies from "chai-spies" import * as spies from 'chai-spies'
import * as Web3 from "web3" import * as Web3 from 'web3'
import { DDO } from "../../src/ddo/DDO" import { DDO } from '../../src/ddo/DDO'
import { Service } from "../../src/ddo/Service" import { Service } from '../../src/ddo/Service'
import { Ocean } from "../../src/ocean/Ocean" import { Ocean } from '../../src/ocean/Ocean'
import config from "../config" import config from '../config'
import TestContractHandler from "../keeper/TestContractHandler" import TestContractHandler from '../keeper/TestContractHandler'
import * as jsonDDO from "../testdata/ddo.json" import * as jsonDDO from '../testdata/ddo.json'
use(spies) use(spies)
describe("DDO", () => { describe('DDO', () => {
const testDDO: DDO = new DDO({ const testDDO: DDO = new DDO({
id: `did:op:${"a".repeat(64)}`, id: `did:op:${'a'.repeat(64)}`,
publicKey: [ publicKey: [
{ {
id: "did:op:123456789abcdefghi#keys-1", id: 'did:op:123456789abcdefghi#keys-1',
type: "RsaVerificationKey2018", type: 'RsaVerificationKey2018',
owner: "did:op:123456789abcdefghi", owner: 'did:op:123456789abcdefghi',
publicKeyPem: "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n", publicKeyPem: '-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n'
}, },
{ {
id: "did:op:123456789abcdefghi#keys-2", id: 'did:op:123456789abcdefghi#keys-2',
type: "Ed25519VerificationKey2018", type: 'Ed25519VerificationKey2018',
owner: "did:op:123456789abcdefghi", owner: 'did:op:123456789abcdefghi',
publicKeyBase58: "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV", publicKeyBase58: 'H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV'
}, }
], ],
authentication: [ authentication: [
{ {
type: "RsaSignatureAuthentication2018", type: 'RsaSignatureAuthentication2018',
publicKey: "did:op:123456789abcdefghi#keys-1", publicKey: 'did:op:123456789abcdefghi#keys-1'
}, },
{ {
type: "ieee2410Authentication2018", type: 'ieee2410Authentication2018',
publicKey: "did:op:123456789abcdefghi#keys-2", publicKey: 'did:op:123456789abcdefghi#keys-2'
}, }
], ],
service: [ service: [
{ {
type: "OpenIdConnectVersion1.0Service", type: 'OpenIdConnectVersion1.0Service',
serviceEndpoint: "https://openid.example.com/", serviceEndpoint: 'https://openid.example.com/'
}, },
{ {
type: "CredentialRepositoryService", type: 'CredentialRepositoryService',
serviceEndpoint: "https://repository.example.com/service/8377464", serviceEndpoint:
'https://repository.example.com/service/8377464'
}, },
{ {
type: "XdiService", type: 'XdiService',
serviceEndpoint: "https://xdi.example.com/8377464", serviceEndpoint: 'https://xdi.example.com/8377464'
}, },
{ {
type: "HubService", type: 'HubService',
serviceEndpoint: "https://hub.example.com/.identity/did:op:0123456789abcdef/", serviceEndpoint:
'https://hub.example.com/.identity/did:op:0123456789abcdef/'
}, },
{ {
type: "MessagingService", type: 'MessagingService',
serviceEndpoint: "https://example.com/messages/8377464", serviceEndpoint: 'https://example.com/messages/8377464'
}, },
{ {
type: "SocialWebInboxService", type: 'SocialWebInboxService',
serviceEndpoint: "https://social.example.com/83hfh37dj", serviceEndpoint: 'https://social.example.com/83hfh37dj',
description: "My public social inbox", description: 'My public social inbox',
spamCost: { spamCost: {
amount: "0.50", amount: '0.50',
currency: "USD", currency: 'USD'
}, }
} as any, } as any,
{ {
id: "did:op:123456789abcdefghi;bops", id: 'did:op:123456789abcdefghi;bops',
type: "BopsService", type: 'BopsService',
serviceEndpoint: "https://bops.example.com/enterprise/", serviceEndpoint: 'https://bops.example.com/enterprise/'
}, },
{ {
type: "Consume", type: 'Consume',
serviceEndpoint: "http://mybrizo.org/api/v1/brizo/services/consume?pubKey=${pubKey}&serviceId={serviceId}&url={url}", serviceEndpoint:
'http://mybrizo.org/api/v1/brizo/services/consume?pubKey=${pubKey}&serviceId={serviceId}&url={url}'
}, },
{ {
type: "Compute", type: 'Compute',
// tslint:disable-next-line // tslint:disable-next-line
serviceEndpoint: "http://mybrizo.org/api/v1/brizo/services/compute?pubKey=${pubKey}&serviceId={serviceId}&algo={algo}&container={container}", serviceEndpoint:
'http://mybrizo.org/api/v1/brizo/services/compute?pubKey=${pubKey}&serviceId={serviceId}&algo={algo}&container={container}'
}, },
{ {
type: "Metadata", type: 'Metadata',
serviceEndpoint: "http://myaquarius.org/api/v1/provider/assets/metadata/{did}", serviceEndpoint:
'http://myaquarius.org/api/v1/provider/assets/metadata/{did}',
metadata: { metadata: {
base: { base: {
name: "UK Weather information 2011", name: 'UK Weather information 2011',
type: "dataset", type: 'dataset',
description: "Weather information of UK including temperature and humidity", description:
dateCreated: "2012-10-10T17:00:000Z", 'Weather information of UK including temperature and humidity',
datePublished: "2012-10-10T17:00:000Z", dateCreated: '2012-10-10T17:00:000Z',
author: "Met Office", datePublished: '2012-10-10T17:00:000Z',
license: "CC-BY", author: 'Met Office',
copyrightHolder: "Met Office", license: 'CC-BY',
workExample: "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68", copyrightHolder: 'Met Office',
workExample:
'423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68',
links: [ links: [
{ {
sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/", 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/", 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/", fieldsDescription:
}, 'http://data.ceda.ac.uk/badc/ukcp09/'
}
],
inLanguage: 'en',
categories: ['Economy', 'Data Science'],
tags: [
'weather',
'uk',
'2011',
'temperature',
'humidity'
], ],
inLanguage: "en",
categories: ["Economy", "Data Science"],
tags: ["weather", "uk", "2011", "temperature", "humidity"],
price: 10, price: 10,
files: [ files: [
{ {
index: 0, index: 0,
checksum: "efb2c764274b745f5fc37f97c6b0e761", checksum: 'efb2c764274b745f5fc37f97c6b0e761',
contentLength: 4535431, contentLength: 4535431,
resourceId: "access-log2018-02-13-15-17-29-18386C502CAEA932", resourceId:
'access-log2018-02-13-15-17-29-18386C502CAEA932'
}, },
{ {
index: 1, index: 1,
checksum: "085340abffh21495345af97c6b0e761", checksum: '085340abffh21495345af97c6b0e761',
contentLength: 12324, contentLength: 12324
}, },
{ {
index: 2, index: 2
}, }
], ],
checksum: "", checksum: ''
}, },
curation: { curation: {
rating: 0.93, rating: 0.93,
numVotes: 123, numVotes: 123,
schema: "Binary Voting", schema: 'Binary Voting'
}, },
additionalInformation: { additionalInformation: {
updateFrecuency: "yearly", updateFrecuency: 'yearly',
structuredMarkup: [ structuredMarkup: [
{ {
uri: "http://skos.um.es/unescothes/C01194/jsonld", uri:
mediaType: "application/ld+json", 'http://skos.um.es/unescothes/C01194/jsonld',
mediaType: 'application/ld+json'
}, },
{ {
uri: "http://skos.um.es/unescothes/C01194/turtle", uri:
mediaType: "text/turtle", 'http://skos.um.es/unescothes/C01194/turtle',
}, mediaType: 'text/turtle'
], }
}, ]
}, }
}, }
], }
]
}) })
let web3: Web3 let web3: Web3
@ -167,20 +185,16 @@ describe("DDO", () => {
spy.restore() spy.restore()
}) })
describe("#serialize()", () => { describe('#serialize()', () => {
it('should properly serialize', async () => {
it("should properly serialize", async () => {
const ddoString = DDO.serialize(testDDO) const ddoString = DDO.serialize(testDDO)
assert(ddoString) assert(ddoString)
assert(ddoString.startsWith("{")) assert(ddoString.startsWith('{'))
}) })
}) })
describe("#constructor()", () => { describe('#constructor()', () => {
it('should create an empty ddo', async () => {
it("should create an empty ddo", async () => {
const ddo = new DDO() const ddo = new DDO()
assert(ddo) assert(ddo)
@ -189,15 +203,14 @@ describe("DDO", () => {
assert(ddo.publicKey.length === 0) assert(ddo.publicKey.length === 0)
}) })
it("should create an predefined ddo", async () => { it('should create an predefined ddo', async () => {
const service: Partial<Service> & any = { const service: Partial<Service> & any = {
serviceEndpoint: "http://", serviceEndpoint: 'http://',
description: "nice service", description: 'nice service'
} }
const ddo = new DDO({ const ddo = new DDO({
service: [service as any], service: [service as any]
}) })
assert(ddo) assert(ddo)
@ -209,72 +222,84 @@ describe("DDO", () => {
}) })
}) })
describe("#deserialize()", () => { describe('#deserialize()', () => {
it('should properly deserialize from serialized object', async () => {
it("should properly deserialize from serialized object", async () => {
const ddoString = DDO.serialize(testDDO) const ddoString = DDO.serialize(testDDO)
assert.typeOf(ddoString, "string") assert.typeOf(ddoString, 'string')
const ddo: DDO = DDO.deserialize(ddoString) const ddo: DDO = DDO.deserialize(ddoString)
assert.instanceOf(ddo, DDO) assert.instanceOf(ddo, DDO)
assert.equal(ddo.id, testDDO.id) assert.equal(ddo.id, testDDO.id)
assert.equal(ddo.publicKey[0].publicKeyPem, testDDO.publicKey[0].publicKeyPem) assert.equal(
ddo.publicKey[0].publicKeyPem,
testDDO.publicKey[0].publicKeyPem
)
}) })
it("should properly deserialize from json file", async () => { it('should properly deserialize from json file', async () => {
const ddo: DDO = DDO.deserialize(JSON.stringify(jsonDDO)) const ddo: DDO = DDO.deserialize(JSON.stringify(jsonDDO))
assert(ddo) assert(ddo)
assert.equal(ddo.id, jsonDDO.id) assert.equal(ddo.id, jsonDDO.id)
assert.equal(ddo.publicKey[0].publicKeyPem, jsonDDO.publicKey[0].publicKeyPem) assert.equal(
ddo.publicKey[0].publicKeyPem,
jsonDDO.publicKey[0].publicKeyPem
)
}) })
}) })
describe("#getChecksum()", () => { describe('#getChecksum()', () => {
it("should properly generate a the checksum DDO", async () => { it('should properly generate a the checksum DDO', async () => {
const ddo = new DDO(testDDO) const ddo = new DDO(testDDO)
const checksum = ddo.getChecksum() const checksum = ddo.getChecksum()
assert.equal(checksum, "0x15f27a7a3c7b15d2b06dec7347c6b8da168adddd7df51a8ebbbe87b59b80049b") assert.equal(
checksum,
'0x15f27a7a3c7b15d2b06dec7347c6b8da168adddd7df51a8ebbbe87b59b80049b'
)
}) })
}) })
describe("#generateProof()", () => { describe('#generateProof()', () => {
const publicKey = `0x${'a'.repeat(40)}`
const signature = `0x${'a'.repeat(130)}`
const publicKey = `0x${"a".repeat(40)}` it('should properly generate the proof', async () => {
const signature = `0x${"a".repeat(130)}` const signTextSpy = spy.on(
ocean.utils.signature,
it("should properly generate the proof", async () => { 'signText',
const signTextSpy = spy.on(ocean.utils.signature, "signText", () => signature) () => signature
)
const ddo = new DDO(testDDO) const ddo = new DDO(testDDO)
const checksum = ddo.getChecksum() const checksum = ddo.getChecksum()
const proof = await ddo.generateProof(ocean, publicKey) const proof = await ddo.generateProof(ocean, publicKey)
assert.include(proof as any, { assert.include(proof as any, {
creator: publicKey, creator: publicKey,
type: "DDOIntegritySignature", type: 'DDOIntegritySignature',
signatureValue: signature, signatureValue: signature
}) })
expect(signTextSpy).to.have.been.called.with(checksum, publicKey) expect(signTextSpy).to.have.been.called.with(checksum, publicKey)
}) })
}) })
describe("#addProof()", () => { describe('#addProof()', () => {
const publicKey = `0x${'a'.repeat(40)}`
const publicKey = `0x${"a".repeat(40)}` it('should properly add the proof on the DDO', async () => {
it("should properly add the proof on the DDO", async () => {
const fakeProof = { const fakeProof = {
creation: Date.now(), creation: Date.now(),
creator: "test", creator: 'test',
type: "test", type: 'test',
signaturValue: "test", signaturValue: 'test'
} as any } as any
const ddo = new DDO(testDDO) const ddo = new DDO(testDDO)
const generateProofSpy = spy.on(ddo, "generateProof", () => fakeProof) const generateProofSpy = spy.on(
ddo,
'generateProof',
() => fakeProof
)
await ddo.addProof(web3, publicKey) await ddo.addProof(web3, publicKey)
assert.equal(ddo.proof, fakeProof) assert.equal(ddo.proof, fakeProof)

View File

@ -1,15 +1,14 @@
import {assert} from "chai" import { assert } from 'chai'
import Account from "../../src/ocean/Account" import Account from '../../src/ocean/Account'
import { Ocean } from "../../src/ocean/Ocean" import { Ocean } from '../../src/ocean/Ocean'
import config from "../config" import config from '../config'
import ContractBaseMock from "../mocks/ContractBase.Mock" import ContractBaseMock from '../mocks/ContractBase.Mock'
import TestContractHandler from "./TestContractHandler" import TestContractHandler from './TestContractHandler'
const wrappedContract = new ContractBaseMock("OceanToken") const wrappedContract = new ContractBaseMock('OceanToken')
let accounts: Account[] let accounts: Account[]
describe("ContractWrapperBase", () => { describe('ContractWrapperBase', () => {
before(async () => { before(async () => {
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
const ocean: Ocean = await Ocean.getInstance(config) const ocean: Ocean = await Ocean.getInstance(config)
@ -17,79 +16,58 @@ describe("ContractWrapperBase", () => {
await wrappedContract.initMock((ocean as any).instanceConfig) await wrappedContract.initMock((ocean as any).instanceConfig)
}) })
describe("#call()", () => { describe('#call()', () => {
it('should fail to call on an unknown contract function', done => {
wrappedContract.callMock('balanceOfxxx', []).catch(() => {
done()
})
})
it("should fail to call on an unknown contract function", (done) => { it('should fail to call on an contract function with wrong set of parameters', done => {
wrappedContract.callMock('balanceOf', []).catch(() => {
done()
})
})
wrappedContract.callMock("balanceOfxxx", []) it('should fail to call on an unknown contract function', done => {
wrappedContract
.sendMock('balanceOfxxx', '0x00', ['0x00'])
.catch(() => { .catch(() => {
done() done()
}) })
}) })
it("should fail to call on an contract function with wrong set of parameters", (done) => { it('should fail to call on an contract function with wrong set of parameters', done => {
wrappedContract.sendMock('approve', '0x000', []).catch(() => {
wrappedContract.callMock("balanceOf", []) done()
.catch(() => { })
done()
})
}) })
})
it("should fail to call on an unknown contract function", (done) => { describe('#send()', () => {
it('should fail to call on an unknown contract function', done => {
wrappedContract.sendMock("balanceOfxxx", "0x00", ["0x00"]) wrappedContract
.sendMock('transferxxx', accounts[0].getId(), [])
.catch(() => { .catch(() => {
done()
})
})
it("should fail to call on an contract function with wrong set of parameters", (done) => {
wrappedContract.sendMock("approve", "0x000", [])
.catch(() => {
done() done()
}) })
}) })
}) })
describe("#send()", () => { describe('#getSignatureOfMethod()', () => {
it('should a signature of the function', async () => {
it("should fail to call on an unknown contract function", (done) => { const sig = wrappedContract.getSignatureOfMethod('name')
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(sig)
assert(typeof sig === "string") assert(typeof sig === 'string')
assert(sig.startsWith("0x")) assert(sig.startsWith('0x'))
}) })
}) })
describe("#getEventData()", () => { describe('#getEventData()', () => {
it('should fail on unknown event', done => {
it("should fail on unknown event", (done) => { wrappedContract.getEventData('crazyevent', {}).catch(() => {
done()
wrappedContract.getEventData("crazyevent", {}) })
.catch(() => {
done()
})
}) })
}) })
}) })

View File

@ -1,12 +1,11 @@
import { assert } from "chai" import { assert } from 'chai'
import { EventHandler } from "../../src/keeper/EventHandler" import { EventHandler } from '../../src/keeper/EventHandler'
import { ContractEventSubscription } from "../../src/keeper/ContractEvent" import { ContractEventSubscription } from '../../src/keeper/ContractEvent'
import { Ocean } from "../../src/ocean/Ocean" import { Ocean } from '../../src/ocean/Ocean'
import config from "../config" import config from '../config'
import TestContractHandler from "./TestContractHandler" import TestContractHandler from './TestContractHandler'
describe("ContractEvent", () => {
describe('ContractEvent', () => {
let ocean: Ocean let ocean: Ocean
let account: string let account: string
let eventHandler: EventHandler let eventHandler: EventHandler
@ -18,17 +17,22 @@ describe("ContractEvent", () => {
eventHandler = new EventHandler((ocean as any).instanceConfig) eventHandler = new EventHandler((ocean as any).instanceConfig)
account = (await ocean.accounts.list())[0].getId() account = (await ocean.accounts.list())[0].getId()
executeTransaction = () => ocean.keeper.dispenser.requestTokens(10, account) executeTransaction = () =>
ocean.keeper.dispenser.requestTokens(10, account)
}) })
describe("#subscribe()", () => { describe('#subscribe()', () => {
it("should listen the events", async () => { it('should listen the events', async () => {
const event = eventHandler.getEvent(ocean.keeper.token, "Transfer", {to: account}) const event = eventHandler.getEvent(
ocean.keeper.token,
'Transfer',
{ to: account }
)
let validResolve = false let validResolve = false
let subscription: ContractEventSubscription let subscription: ContractEventSubscription
const waitUntilEvent = new Promise((resolve) => { const waitUntilEvent = new Promise(resolve => {
subscription = event.subscribe((events) => { subscription = event.subscribe(events => {
assert.isDefined(events) assert.isDefined(events)
assert.lengthOf(events, 2) assert.lengthOf(events, 2)
if (validResolve) { if (validResolve) {
@ -37,18 +41,12 @@ describe("ContractEvent", () => {
}) })
}) })
await Promise.all([ await Promise.all([executeTransaction(), executeTransaction()])
executeTransaction(),
executeTransaction(),
])
await new Promise((_) => setTimeout(_, 2000)) await new Promise(_ => setTimeout(_, 2000))
validResolve = true validResolve = true
await Promise.all([ await Promise.all([executeTransaction(), executeTransaction()])
executeTransaction(),
executeTransaction(),
])
await waitUntilEvent await waitUntilEvent
@ -56,14 +54,18 @@ describe("ContractEvent", () => {
}) })
}) })
describe("#once()", () => { describe('#once()', () => {
it("should listen only once", async () => { it('should listen only once', async () => {
const to = account const to = account
const event = eventHandler.getEvent(ocean.keeper.token, "Transfer", {to}) const event = eventHandler.getEvent(
ocean.keeper.token,
'Transfer',
{ to }
)
let canBeRejected = false let canBeRejected = false
const waitUntilEvent = new Promise((resolve, reject) => { const waitUntilEvent = new Promise((resolve, reject) => {
event.once((events) => { event.once(events => {
if (canBeRejected) { if (canBeRejected) {
reject() reject()
} }
@ -73,7 +75,7 @@ describe("ContractEvent", () => {
await executeTransaction() await executeTransaction()
await new Promise((_) => setTimeout(_, 2000)) await new Promise(_ => setTimeout(_, 2000))
canBeRejected = true canBeRejected = true
await executeTransaction() await executeTransaction()
@ -81,13 +83,17 @@ describe("ContractEvent", () => {
await waitUntilEvent await waitUntilEvent
}) })
it("should get the event like a promise", async () => { it('should get the event like a promise', async () => {
const to = account const to = account
const event = eventHandler.getEvent(ocean.keeper.token, "Transfer", {to}) const event = eventHandler.getEvent(
ocean.keeper.token,
'Transfer',
{ to }
)
const waitUntilEvent = event.once() const waitUntilEvent = event.once()
await new Promise((_) => setTimeout(_, 400)) await new Promise(_ => setTimeout(_, 400))
await executeTransaction() await executeTransaction()

View File

@ -1,29 +1,27 @@
import {assert} from "chai" import { assert } from 'chai'
import ContractHandler from "../../src/keeper/ContractHandler" import ContractHandler from '../../src/keeper/ContractHandler'
import { Ocean } from "../../src/ocean/Ocean" import { Ocean } from '../../src/ocean/Ocean'
import config from "../config" import config from '../config'
describe("ContractHandler", () => { describe('ContractHandler', () => {
let contractHandler: ContractHandler let contractHandler: ContractHandler
before(async () => { before(async () => {
const instanceConfig = (await Ocean.getInstance(config) as any).instanceConfig const instanceConfig = ((await Ocean.getInstance(config)) as any)
.instanceConfig
contractHandler = new ContractHandler(instanceConfig) contractHandler = new ContractHandler(instanceConfig)
}) })
describe("#get()", () => { describe('#get()', () => {
it('should load and get OceanToken correctly', async () => {
it("should load and get OceanToken correctly", async () => { assert(await contractHandler.get('OceanToken'))
assert(await contractHandler.get("OceanToken"))
}) })
it("should fail to load an unknown contract", (done) => { it('should fail to load an unknown contract', done => {
contractHandler.get('OceanXXX').catch(() => {
contractHandler.get("OceanXXX") done()
.catch(() => { })
done()
})
}) })
}) })
}) })

View File

@ -1,67 +1,92 @@
import {assert} from "chai" import { assert } from 'chai'
import DIDRegistry from "../../src/keeper/contracts/DIDRegistry" import DIDRegistry from '../../src/keeper/contracts/DIDRegistry'
import Account from "../../src/ocean/Account" import Account from '../../src/ocean/Account'
import { Ocean } from "../../src/ocean/Ocean" import { Ocean } from '../../src/ocean/Ocean'
import { generateId } from "../../src/utils/GeneratorHelpers" import { generateId } from '../../src/utils/GeneratorHelpers'
import config from "../config" import config from '../config'
import TestContractHandler from "./TestContractHandler" import TestContractHandler from './TestContractHandler'
let ocean: Ocean let ocean: Ocean
let didRegistry: DIDRegistry let didRegistry: DIDRegistry
describe("DIDRegistry", () => { describe('DIDRegistry', () => {
before(async () => { before(async () => {
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
ocean = await Ocean.getInstance(config) ocean = await Ocean.getInstance(config)
didRegistry = ocean.keeper.didRegistry didRegistry = ocean.keeper.didRegistry
}) })
describe("#registerAttribute()", () => { describe('#registerAttribute()', () => {
it('should register an attribute in a new did', async () => {
it("should register an attribute in a new did", async () => {
const ownerAccount: Account = (await ocean.accounts.list())[0] const ownerAccount: Account = (await ocean.accounts.list())[0]
const did = generateId() const did = generateId()
const data = "my nice provider, is nice" const data = 'my nice provider, is nice'
const receipt = await didRegistry.registerAttribute(did, `0123456789abcdef`, [], data, ownerAccount.getId()) const receipt = await didRegistry.registerAttribute(
did,
`0123456789abcdef`,
[],
data,
ownerAccount.getId()
)
assert(receipt.status) assert(receipt.status)
assert(receipt.events.DIDAttributeRegistered) assert(receipt.events.DIDAttributeRegistered)
}) })
it("should register another attribute in the same did", async () => { it('should register another attribute in the same did', async () => {
const ownerAccount: Account = (await ocean.accounts.list())[0] const ownerAccount: Account = (await ocean.accounts.list())[0]
const did = generateId() const did = generateId()
{ {
// register the first attribute // register the first attribute
const data = "my nice provider, is nice" const data = 'my nice provider, is nice'
await didRegistry.registerAttribute(did, "0123456789abcdef", [], data, ownerAccount.getId()) await didRegistry.registerAttribute(
did,
'0123456789abcdef',
[],
data,
ownerAccount.getId()
)
} }
{ {
// register the second attribute with the same did // register the second attribute with the same did
const data = "asdsad" const data = 'asdsad'
const receipt = await didRegistry.registerAttribute(did, "0123456789abcdef", [], data, ownerAccount.getId()) const receipt = await didRegistry.registerAttribute(
did,
'0123456789abcdef',
[],
data,
ownerAccount.getId()
)
assert.isTrue(receipt.status) assert.isTrue(receipt.status)
assert.isDefined(receipt.events.DIDAttributeRegistered) assert.isDefined(receipt.events.DIDAttributeRegistered)
} }
}) })
}) })
describe("#getDIDOwner()", () => { describe('#getDIDOwner()', () => {
it("should get the owner of a did properly", async () => { it('should get the owner of a did properly', async () => {
const ownerAccount: Account = (await ocean.accounts.list())[0] const ownerAccount: Account = (await ocean.accounts.list())[0]
const did = generateId() const did = generateId()
const data = "my nice provider, is nice" const data = 'my nice provider, is nice'
await didRegistry.registerAttribute(did, "0123456789abcdef", [], data, ownerAccount.getId()) await didRegistry.registerAttribute(
did,
'0123456789abcdef',
[],
data,
ownerAccount.getId()
)
const owner = await didRegistry.getDIDOwner(did) const owner = await didRegistry.getDIDOwner(did)
assert.equal(owner, ownerAccount.getId(), `Got ${owner} but expected ${ownerAccount.getId()}`) assert.equal(
owner,
ownerAccount.getId(),
`Got ${owner} but expected ${ownerAccount.getId()}`
)
}) })
it("should get 0x0 for a not registered did", async () => { it('should get 0x0 for a not registered did', async () => {
const owner = await didRegistry.getDIDOwner("1234") const owner = await didRegistry.getDIDOwner('1234')
assert.equal(owner, `0x${"0".repeat(40)}`) assert.equal(owner, `0x${'0'.repeat(40)}`)
}) })
}) })
}) })

View File

@ -1,13 +1,12 @@
import { assert, expect, spy, use } from "chai" import { assert, expect, spy, use } from 'chai'
import * as spies from "chai-spies" import * as spies from 'chai-spies'
import { EventHandler } from "../../src/keeper/EventHandler" import { EventHandler } from '../../src/keeper/EventHandler'
import { Ocean } from "../../src/ocean/Ocean" import { Ocean } from '../../src/ocean/Ocean'
import config from "../config" import config from '../config'
use(spies) use(spies)
describe("EventHandler", () => { describe('EventHandler', () => {
let ocean: Ocean let ocean: Ocean
let eventHandler: EventHandler let eventHandler: EventHandler
@ -20,20 +19,24 @@ describe("EventHandler", () => {
spy.restore() spy.restore()
}) })
describe("#subscribe()", () => { describe('#subscribe()', () => {
it("should subscribe to an event", async () => { it('should subscribe to an event', async () => {
const countBefore = eventHandler.count const countBefore = eventHandler.count
const subscription = eventHandler.subscribe(() => null) const subscription = eventHandler.subscribe(() => null)
assert.isDefined(subscription) assert.isDefined(subscription)
const countAfter = eventHandler.count const countAfter = eventHandler.count
assert.equal(countBefore + 1, countAfter, "The event seems not added.") assert.equal(
countBefore + 1,
countAfter,
'The event seems not added.'
)
subscription.unsubscribe() subscription.unsubscribe()
}) })
it("should unsubscribe using the subscription", async () => { it('should unsubscribe using the subscription', async () => {
const countBefore = eventHandler.count const countBefore = eventHandler.count
const subscription = eventHandler.subscribe(() => null) const subscription = eventHandler.subscribe(() => null)
@ -42,12 +45,12 @@ describe("EventHandler", () => {
subscription.unsubscribe() subscription.unsubscribe()
const countAfter = eventHandler.count const countAfter = eventHandler.count
assert.equal(countBefore, countAfter, "The event seems not added.") assert.equal(countBefore, countAfter, 'The event seems not added.')
}) })
}) })
describe("#unsubscribe()", () => { describe('#unsubscribe()', () => {
it("should unsubscribe from an event", async () => { it('should unsubscribe from an event', async () => {
const countBefore = eventHandler.count const countBefore = eventHandler.count
const callback = () => null const callback = () => null
@ -55,25 +58,29 @@ describe("EventHandler", () => {
eventHandler.unsubscribe(callback) eventHandler.unsubscribe(callback)
const countAfter = eventHandler.count const countAfter = eventHandler.count
assert.equal(countBefore, countAfter, "The event seems not removed.") assert.equal(
countBefore,
countAfter,
'The event seems not removed.'
)
}) })
}) })
describe("#checkBlock()", () => { describe('#checkBlock()', () => {
it("should call the callback on each new block", async () => { it('should call the callback on each new block', async () => {
let blockNumber = 100000000000 let blockNumber = 100000000000
const callbackSpy = spy() const callbackSpy = spy()
spy.on((ocean as any).web3.eth, "getBlockNumber", () => blockNumber) spy.on((ocean as any).web3.eth, 'getBlockNumber', () => blockNumber)
const subscription = eventHandler.subscribe(callbackSpy) const subscription = eventHandler.subscribe(callbackSpy)
await new Promise((_) => setTimeout(_, 300)) await new Promise(_ => setTimeout(_, 300))
expect(callbackSpy).not.to.has.been.called() expect(callbackSpy).not.to.has.been.called()
blockNumber++ blockNumber++
await new Promise((_) => setTimeout(_, 300)) await new Promise(_ => setTimeout(_, 300))
expect(callbackSpy).to.has.been.called.with(blockNumber) expect(callbackSpy).to.has.been.called.with(blockNumber)

View File

@ -1,36 +1,32 @@
import {assert} from "chai" import { assert } from 'chai'
import config from "../config" import config from '../config'
import TestContractHandler from "./TestContractHandler" import TestContractHandler from './TestContractHandler'
import Keeper from "../../src/keeper/Keeper" import Keeper from '../../src/keeper/Keeper'
import { Ocean } from "../../src/ocean/Ocean" import { Ocean } from '../../src/ocean/Ocean'
let keeper: Keeper let keeper: Keeper
describe("Keeper", () => { describe('Keeper', () => {
before(async () => { before(async () => {
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
const ocean = await Ocean.getInstance(config) const ocean = await Ocean.getInstance(config)
keeper = ocean.keeper keeper = ocean.keeper
}) })
describe("public interface", () => { describe('public interface', () => {
it('should have dispenser', () => {
it("should have dispenser", () => {
assert(keeper.dispenser !== null) assert(keeper.dispenser !== null)
}) })
it("should have token", () => { it('should have token', () => {
assert(keeper.token !== null) assert(keeper.token !== null)
}) })
}) })
describe("#getNetworkName()", () => { describe('#getNetworkName()', () => {
it('should get development as default', async () => {
it("should get development as default", async () => {
const networkName: string = await keeper.getNetworkName() const networkName: string = await keeper.getNetworkName()
assert(networkName === "Development") assert(networkName === 'Development')
}) })
}) })
}) })

View File

@ -1,11 +1,10 @@
import Contract from "web3-eth-contract" import Contract from 'web3-eth-contract'
import ContractHandler from "../../src/keeper/ContractHandler" import ContractHandler from '../../src/keeper/ContractHandler'
import Web3Provider from "../../src/keeper/Web3Provider" import Web3Provider from '../../src/keeper/Web3Provider'
import Logger from "../../src/utils/Logger" import Logger from '../../src/utils/Logger'
import config from "../config" import config from '../config'
export default class TestContractHandler extends ContractHandler { export default class TestContractHandler extends ContractHandler {
public static async prepareContracts() { public static async prepareContracts() {
const web3 = Web3Provider.getWeb3(config) const web3 = Web3Provider.getWeb3(config)
const deployerAddress = (await web3.eth.getAccounts())[0] const deployerAddress = (await web3.eth.getAccounts())[0]
@ -18,77 +17,131 @@ export default class TestContractHandler extends ContractHandler {
private static networkId: number private static networkId: number
private static async deployContracts(deployerAddress: string) { private static async deployContracts(deployerAddress: string) {
Logger.log("Trying to deploy contracts") Logger.log('Trying to deploy contracts')
// Libraries // Libraries
const epochLibrary = await TestContractHandler.deployContract("EpochLibrary", deployerAddress) const epochLibrary = await TestContractHandler.deployContract(
const didRegistryLibrary = await TestContractHandler.deployContract("DIDRegistryLibrary", deployerAddress) 'EpochLibrary',
deployerAddress
)
const didRegistryLibrary = await TestContractHandler.deployContract(
'DIDRegistryLibrary',
deployerAddress
)
// Contracts // Contracts
const token = await TestContractHandler.deployContract("OceanToken", deployerAddress, [deployerAddress, deployerAddress]) const token = await TestContractHandler.deployContract(
'OceanToken',
deployerAddress,
[deployerAddress, deployerAddress]
)
const dispenser = await TestContractHandler.deployContract("Dispenser", deployerAddress, [token.options.address, deployerAddress]) const dispenser = await TestContractHandler.deployContract(
'Dispenser',
deployerAddress,
[token.options.address, deployerAddress]
)
// Add dispenser as Token minter // Add dispenser as Token minter
if (!token.$initialized) { if (!token.$initialized) {
await token.methods.addMinter(dispenser.options.address) await token.methods
.send({from: deployerAddress}) .addMinter(dispenser.options.address)
.send({ from: deployerAddress })
} }
const didRegistry = await TestContractHandler.deployContract("DIDRegistry", deployerAddress, [deployerAddress], { const didRegistry = await TestContractHandler.deployContract(
DIDRegistryLibrary: didRegistryLibrary.options.address, 'DIDRegistry',
}) deployerAddress,
[deployerAddress],
{
DIDRegistryLibrary: didRegistryLibrary.options.address
}
)
// Managers // Managers
const templateStoreManager = await TestContractHandler.deployContract("TemplateStoreManager", deployerAddress, [ const templateStoreManager = await TestContractHandler.deployContract(
'TemplateStoreManager',
deployerAddress, deployerAddress,
]) [deployerAddress]
const conditionStoreManager = await TestContractHandler.deployContract("ConditionStoreManager", deployerAddress, [ )
const conditionStoreManager = await TestContractHandler.deployContract(
'ConditionStoreManager',
deployerAddress, deployerAddress,
], { [deployerAddress],
EpochLibrary: epochLibrary.options.address, {
}) EpochLibrary: epochLibrary.options.address
const agreementStoreManager = await TestContractHandler.deployContract("AgreementStoreManager", deployerAddress, [ }
deployerAddress, conditionStoreManager.options.address, templateStoreManager.options.address, didRegistry.options.address, )
]) const agreementStoreManager = await TestContractHandler.deployContract(
'AgreementStoreManager',
deployerAddress,
[
deployerAddress,
conditionStoreManager.options.address,
templateStoreManager.options.address,
didRegistry.options.address
]
)
// Conditions // Conditions
const lockRewardCondition = await TestContractHandler.deployContract("LockRewardCondition", deployerAddress, [ const lockRewardCondition = await TestContractHandler.deployContract(
deployerAddress, conditionStoreManager.options.address, token.options.address, 'LockRewardCondition',
]) deployerAddress,
const accessSecretStoreCondition = await TestContractHandler.deployContract("AccessSecretStoreCondition", deployerAddress, [ [
deployerAddress, conditionStoreManager.options.address, agreementStoreManager.options.address, deployerAddress,
]) conditionStoreManager.options.address,
token.options.address
]
)
const accessSecretStoreCondition = await TestContractHandler.deployContract(
'AccessSecretStoreCondition',
deployerAddress,
[
deployerAddress,
conditionStoreManager.options.address,
agreementStoreManager.options.address
]
)
// Conditions rewards // Conditions rewards
const escrowReward = await TestContractHandler.deployContract("EscrowReward", deployerAddress, [ const escrowReward = await TestContractHandler.deployContract(
deployerAddress, conditionStoreManager.options.address, token.options.address, 'EscrowReward',
]) deployerAddress,
[
deployerAddress,
conditionStoreManager.options.address,
token.options.address
]
)
// Templates // Templates
await TestContractHandler.deployContract("EscrowAccessSecretStoreTemplate", deployerAddress, [ await TestContractHandler.deployContract(
'EscrowAccessSecretStoreTemplate',
deployerAddress, deployerAddress,
agreementStoreManager.options.address, [
didRegistry.options.address, deployerAddress,
accessSecretStoreCondition.options.address, agreementStoreManager.options.address,
lockRewardCondition.options.address, didRegistry.options.address,
escrowReward.options.address, accessSecretStoreCondition.options.address,
]) lockRewardCondition.options.address,
escrowReward.options.address
]
)
} }
private static async deployContract( private static async deployContract(
name: string, name: string,
from: string, from: string,
args: any[] = [], args: any[] = [],
tokens: {[name: string]: string} = {}, tokens: { [name: string]: string } = {}
): Promise<Contract & {$initialized: boolean}> { ): Promise<Contract & { $initialized: boolean }> {
const where = this.networkId const where = this.networkId
// dont redeploy if there is already something loaded // dont redeploy if there is already something loaded
if (TestContractHandler.hasContract(name, where)) { if (TestContractHandler.hasContract(name, where)) {
const contract = await ContractHandler.getContract(name, where) const contract = await ContractHandler.getContract(name, where)
if (contract.testContract) { if (contract.testContract) {
return {...contract, $initialized: true} return { ...contract, $initialized: true }
} }
} }
@ -96,50 +149,70 @@ export default class TestContractHandler extends ContractHandler {
let contractInstance: Contract let contractInstance: Contract
try { try {
Logger.log("Deploying", name) Logger.log('Deploying', name)
const sendConfig = { const sendConfig = {
from, from,
gas: 3000000, gas: 3000000,
gasPrice: 10000000000, gasPrice: 10000000000
} }
const artifact = require(`@oceanprotocol/keeper-contracts/artifacts/${name}.development.json`) const artifact = require(`@oceanprotocol/keeper-contracts/artifacts/${name}.development.json`)
const tempContract = new web3.eth.Contract(artifact.abi, artifact.address) const tempContract = new web3.eth.Contract(
artifact.abi,
artifact.address
)
const isZos = !!tempContract.methods.initialize const isZos = !!tempContract.methods.initialize
Logger.debug({ Logger.debug({
name, from, isZos, args, name,
from,
isZos,
args,
libraries: artifact.bytecode libraries: artifact.bytecode
.replace(/(0x)?[a-f0-9]{8}/gi, "") .replace(/(0x)?[a-f0-9]{8}/gi, '')
.replace(/__([^_]+)_*[0-9a-f]{2}/g, "|$1") .replace(/__([^_]+)_*[0-9a-f]{2}/g, '|$1')
.split("|") .split('|')
.splice(1), .splice(1)
}) })
contractInstance = await tempContract contractInstance = await tempContract
.deploy({ .deploy({
data: TestContractHandler.replaceTokens(artifact.bytecode.toString(), tokens), data: TestContractHandler.replaceTokens(
arguments: isZos ? undefined : args, artifact.bytecode.toString(),
tokens
),
arguments: isZos ? undefined : args
}) })
.send(sendConfig) .send(sendConfig)
if (isZos) { if (isZos) {
await contractInstance.methods.initialize(...args).send(sendConfig) await contractInstance.methods
.initialize(...args)
.send(sendConfig)
} }
contractInstance.testContract = true contractInstance.testContract = true
ContractHandler.setContract(name, where, contractInstance) ContractHandler.setContract(name, where, contractInstance)
// Logger.log("Deployed", name, "at", contractInstance.options.address); // Logger.log("Deployed", name, "at", contractInstance.options.address);
} catch (err) { } catch (err) {
Logger.error("Deployment failed for", name, "with args", JSON.stringify(args, null, 2), err.message) Logger.error(
'Deployment failed for',
name,
'with args',
JSON.stringify(args, null, 2),
err.message
)
throw err throw err
} }
return contractInstance return contractInstance
} }
private static replaceTokens(bytecode: string, tokens: {[name: string]: string}): string { private static replaceTokens(
return Object.entries(tokens) bytecode: string,
.reduce( tokens: { [name: string]: string }
(acc, [token, address]) => acc.replace(new RegExp(`_+${token}_+`, "g"), address.substr(2)), ): string {
bytecode, return Object.entries(tokens).reduce(
) (acc, [token, address]) =>
acc.replace(new RegExp(`_+${token}_+`, 'g'), address.substr(2)),
bytecode
)
} }
} }

View File

@ -1,33 +1,37 @@
import {assert} from "chai" import { assert } from 'chai'
import { AccessSecretStoreCondition } from "../../../src/keeper/contracts/conditions" import { AccessSecretStoreCondition } from '../../../src/keeper/contracts/conditions'
import { Ocean } from "../../../src/ocean/Ocean" import { Ocean } from '../../../src/ocean/Ocean'
import config from "../../config" import config from '../../config'
import TestContractHandler from "../TestContractHandler" import TestContractHandler from '../TestContractHandler'
let condition: AccessSecretStoreCondition let condition: AccessSecretStoreCondition
describe("AccessSecretStoreCondition", () => { describe('AccessSecretStoreCondition', () => {
const agreementId = `0x${'a'.repeat(64)}`
const agreementId = `0x${"a".repeat(64)}` const did = `did:op:${'a'.repeat(64)}`
const did = `did:op:${"a".repeat(64)}` const address = `0x${'a'.repeat(40)}`
const address = `0x${"a".repeat(40)}`
before(async () => { before(async () => {
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
condition = (await Ocean.getInstance(config)).keeper.conditions.accessSecretStoreCondition condition = (await Ocean.getInstance(config)).keeper.conditions
.accessSecretStoreCondition
}) })
describe("#hashValues()", () => { describe('#hashValues()', () => {
it("should hash the values", async () => { it('should hash the values', async () => {
const hash = await condition.hashValues(did, address) const hash = await condition.hashValues(did, address)
assert.match(hash, /^0x[a-f0-9]{64}$/i) assert.match(hash, /^0x[a-f0-9]{64}$/i)
assert.equal(hash, "0x1abbd7e58bc32bff739ee1e756a4108882322f2ec939d5e2f251e6b8424947fb", "The hash is not the expected.") assert.equal(
hash,
'0x1abbd7e58bc32bff739ee1e756a4108882322f2ec939d5e2f251e6b8424947fb',
'The hash is not the expected.'
)
}) })
}) })
describe("#generateId()", () => { describe('#generateId()', () => {
it("should generate an ID", async () => { it('should generate an ID', async () => {
const hash = await condition.hashValues(did, address) const hash = await condition.hashValues(did, address)
const id = await condition.generateId(agreementId, hash) const id = await condition.generateId(agreementId, hash)

View File

@ -1,18 +1,17 @@
import {assert} from "chai" import { assert } from 'chai'
import { EscrowReward } from "../../../src/keeper/contracts/conditions" import { EscrowReward } from '../../../src/keeper/contracts/conditions'
import { Ocean } from "../../../src/ocean/Ocean" import { Ocean } from '../../../src/ocean/Ocean'
import config from "../../config" import config from '../../config'
import TestContractHandler from "../TestContractHandler" import TestContractHandler from '../TestContractHandler'
let condition: EscrowReward let condition: EscrowReward
describe("EscrowReward", () => { describe('EscrowReward', () => {
const agreementId = `0x${'a'.repeat(64)}`
const agreementId = `0x${"a".repeat(64)}` const did = `0x${'a'.repeat(64)}`
const did = `0x${"a".repeat(64)}`
const amount = 15 const amount = 15
const publisher = `0x${"a".repeat(40)}` const publisher = `0x${'a'.repeat(40)}`
const consumer = `0x${"b".repeat(40)}` const consumer = `0x${'b'.repeat(40)}`
let lockCondition let lockCondition
let releaseCondition let releaseCondition
@ -22,21 +21,41 @@ describe("EscrowReward", () => {
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
condition = keeper.conditions.escrowReward condition = keeper.conditions.escrowReward
lockCondition = await keeper.conditions.lockRewardCondition.generateIdHash(agreementId, publisher, amount) lockCondition = await keeper.conditions.lockRewardCondition.generateIdHash(
releaseCondition = await keeper.conditions.accessSecretStoreCondition.generateIdHash(agreementId, did, consumer) agreementId,
publisher,
amount
)
releaseCondition = await keeper.conditions.accessSecretStoreCondition.generateIdHash(
agreementId,
did,
consumer
)
}) })
describe("#hashValues()", () => { describe('#hashValues()', () => {
it("should hash the values", async () => { it('should hash the values', async () => {
const hash = await condition.hashValues(amount, consumer, publisher, lockCondition, releaseCondition) const hash = await condition.hashValues(
amount,
consumer,
publisher,
lockCondition,
releaseCondition
)
assert.match(hash, /^0x[a-f0-9]{64}$/i) assert.match(hash, /^0x[a-f0-9]{64}$/i)
}) })
}) })
describe("#generateId()", () => { describe('#generateId()', () => {
it("should generate an ID", async () => { it('should generate an ID', async () => {
const hash = await condition.hashValues(amount, consumer, publisher, lockCondition, releaseCondition) const hash = await condition.hashValues(
amount,
consumer,
publisher,
lockCondition,
releaseCondition
)
const id = await condition.generateId(agreementId, hash) const id = await condition.generateId(agreementId, hash)
assert.match(id, /^0x[a-f0-9]{64}$/i) assert.match(id, /^0x[a-f0-9]{64}$/i)

View File

@ -1,33 +1,37 @@
import {assert} from "chai" import { assert } from 'chai'
import { LockRewardCondition } from "../../../src/keeper/contracts/conditions" import { LockRewardCondition } from '../../../src/keeper/contracts/conditions'
import { Ocean } from "../../../src/ocean/Ocean" import { Ocean } from '../../../src/ocean/Ocean'
import config from "../../config" import config from '../../config'
import TestContractHandler from "../TestContractHandler" import TestContractHandler from '../TestContractHandler'
let condition: LockRewardCondition let condition: LockRewardCondition
describe("LockRewardCondition", () => { describe('LockRewardCondition', () => {
const agreementId = `0x${'a'.repeat(64)}`
const agreementId = `0x${"a".repeat(64)}` const address = `0x${'a'.repeat(40)}`
const address = `0x${"a".repeat(40)}`
const amount = 15 const amount = 15
before(async () => { before(async () => {
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
condition = (await Ocean.getInstance(config)).keeper.conditions.lockRewardCondition condition = (await Ocean.getInstance(config)).keeper.conditions
.lockRewardCondition
}) })
describe("#hashValues()", () => { describe('#hashValues()', () => {
it("should hash the values", async () => { it('should hash the values', async () => {
const hash = await condition.hashValues(address, amount) const hash = await condition.hashValues(address, amount)
assert.match(hash, /^0x[a-f0-9]{64}$/i) assert.match(hash, /^0x[a-f0-9]{64}$/i)
assert.equal(hash, "0x2543c2ea4b9403bb3e5df1145c70731454748e72a37acc80d025f85e03267973", "The hash is not the expected.") assert.equal(
hash,
'0x2543c2ea4b9403bb3e5df1145c70731454748e72a37acc80d025f85e03267973',
'The hash is not the expected.'
)
}) })
}) })
describe("#generateId()", () => { describe('#generateId()', () => {
it("should generate an ID", async () => { it('should generate an ID', async () => {
const hash = await condition.hashValues(address, amount) const hash = await condition.hashValues(address, amount)
const id = await condition.generateId(agreementId, hash) const id = await condition.generateId(agreementId, hash)

View File

@ -1,18 +1,16 @@
import {assert} from "chai" import { assert } from 'chai'
import { EscrowAccessSecretStoreTemplate } from "../../../src/keeper/contracts/templates" import { EscrowAccessSecretStoreTemplate } from '../../../src/keeper/contracts/templates'
import config from "../../config" import config from '../../config'
import TestContractHandler from "../TestContractHandler" import TestContractHandler from '../TestContractHandler'
import { Ocean } from "../../../src/ocean/Ocean" import { Ocean } from '../../../src/ocean/Ocean'
let condition: EscrowAccessSecretStoreTemplate let condition: EscrowAccessSecretStoreTemplate
describe("EscrowAccessSecretStoreTemplate", () => { describe('EscrowAccessSecretStoreTemplate', () => {
before(async () => { before(async () => {
const ocean: Ocean = await Ocean.getInstance(config) const ocean: Ocean = await Ocean.getInstance(config)
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
condition = ocean.keeper.templates.escrowAccessSecretStoreTemplate condition = ocean.keeper.templates.escrowAccessSecretStoreTemplate
}) })
// describe("#hashValues()", () => { // describe("#hashValues()", () => {
@ -23,5 +21,4 @@ describe("EscrowAccessSecretStoreTemplate", () => {
// assert.match(hash, /^0x[a-f0-9]{64}$/i) // assert.match(hash, /^0x[a-f0-9]{64}$/i)
// }) // })
// }) // })
}) })

View File

@ -1,13 +1,12 @@
import { Aquarius } from "../../src/aquarius/Aquarius" import { Aquarius } from '../../src/aquarius/Aquarius'
import { DDO } from "../../src/ddo/DDO" import { DDO } from '../../src/ddo/DDO'
import DID from "../../src/ocean/DID" import DID from '../../src/ocean/DID'
const ddoStore: Map<string, any> = new Map<string, any>() const ddoStore: Map<string, any> = new Map<string, any>()
export default class AquariusMock extends Aquarius { export default class AquariusMock extends Aquarius {
public async getAccessUrl(accessToken: any, payload: any): Promise<string> { public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
return "http://test/test" return 'http://test/test'
} }
public async storeDDO(ddo: DDO): Promise<DDO> { public async storeDDO(ddo: DDO): Promise<DDO> {

View File

@ -1,10 +1,13 @@
import { Brizo } from "../../src/brizo/Brizo" import { Brizo } from '../../src/brizo/Brizo'
export default class BrizoMock extends Brizo { export default class BrizoMock extends Brizo {
public async initializeServiceAgreement(
public async initializeServiceAgreement(did: string, serviceAgreementId: string, serviceDefinitionId: string, did: string,
signature: string, consumerPublicKey: string): Promise<any> { serviceAgreementId: string,
serviceDefinitionId: string,
signature: string,
consumerPublicKey: string
): Promise<any> {
return true return true
} }
} }

View File

@ -1,4 +1,4 @@
import ContractBase from "../../src/keeper/contracts/ContractBase" import ContractBase from '../../src/keeper/contracts/ContractBase'
export default class ContractBaseMock extends ContractBase { export default class ContractBaseMock extends ContractBase {
public async initMock(config: any) { public async initMock(config: any) {

View File

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

View File

@ -1,15 +1,13 @@
import WebServiceConnector from "../../src/utils/WebServiceConnector" import WebServiceConnector from '../../src/utils/WebServiceConnector'
// @ts-ignore // @ts-ignore
export default class WebServiceConnectorMock extends WebServiceConnector { export default class WebServiceConnectorMock extends WebServiceConnector {
constructor(private returnData: any) { constructor(private returnData: any) {
super() super()
} }
// @ts-ignore // @ts-ignore
private async fetch(url, opts): Promise<any> { private async fetch(url, opts): Promise<any> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
resolve({ resolve({
ok: true, ok: true,
@ -17,8 +15,10 @@ export default class WebServiceConnectorMock extends WebServiceConnector {
return this.returnData ? this.returnData : {} return this.returnData ? this.returnData : {}
}, },
text: () => { text: () => {
return this.returnData ? JSON.stringify(this.returnData.toString()) : "" return this.returnData
}, ? JSON.stringify(this.returnData.toString())
: ''
}
}) })
}) })
} }

Some files were not shown because too many files have changed in this diff Show More