mirror of
https://github.com/oceanprotocol-archive/squid-js.git
synced 2024-02-02 15:31:51 +01:00
commit
90baab2f87
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
|
"printWidth": 90,
|
||||||
"trailingComma": "none"
|
"trailingComma": "none"
|
||||||
}
|
}
|
||||||
|
10
.travis.yml
10
.travis.yml
@ -2,7 +2,7 @@ dist: xenial
|
|||||||
sudo: required
|
sudo: required
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- '11'
|
- '12'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
@ -21,10 +21,10 @@ before_script:
|
|||||||
- ganache-cli --port 18545 > ganache-cli.log &
|
- ganache-cli --port 18545 > ganache-cli.log &
|
||||||
- git clone https://github.com/oceanprotocol/barge
|
- git clone https://github.com/oceanprotocol/barge
|
||||||
- cd barge
|
- cd barge
|
||||||
- export AQUARIUS_VERSION=v0.3.8
|
- export AQUARIUS_VERSION=v1.0.5
|
||||||
- export BRIZO_VERSION=v0.4.5
|
- export BRIZO_VERSION=v0.7.2
|
||||||
- export KEEPER_VERSION=v0.12.7
|
- export KEEPER_VERSION=v0.12.7
|
||||||
- export EVENTS_HANDLER_VERSION=v0.1.2
|
- export EVENTS_HANDLER_VERSION=v0.3.4
|
||||||
- export KEEPER_OWNER_ROLE_ADDRESS="0xe2DD09d719Da89e5a3D0F2549c7E24566e947260"
|
- export KEEPER_OWNER_ROLE_ADDRESS="0xe2DD09d719Da89e5a3D0F2549c7E24566e947260"
|
||||||
- rm -rf "${HOME}/.ocean/keeper-contracts/artifacts"
|
- rm -rf "${HOME}/.ocean/keeper-contracts/artifacts"
|
||||||
- bash -x start_ocean.sh --no-commons --no-dashboard 2>&1 > start_ocean.log &
|
- bash -x start_ocean.sh --no-commons --no-dashboard 2>&1 > start_ocean.log &
|
||||||
@ -32,10 +32,10 @@ before_script:
|
|||||||
|
|
||||||
script:
|
script:
|
||||||
- npm run lint
|
- npm run lint
|
||||||
|
- ./scripts/keeper.sh
|
||||||
- export ETH_PORT=18545; npm run test:cover
|
- export ETH_PORT=18545; npm run test:cover
|
||||||
- npm run build
|
- npm run build
|
||||||
- npm run doc
|
- npm run doc
|
||||||
- ./scripts/keeper.sh
|
|
||||||
- npm run integration:cover
|
- npm run integration:cover
|
||||||
- npm run report-coverage
|
- npm run report-coverage
|
||||||
|
|
||||||
|
@ -4,11 +4,20 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
|
|
||||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||||
|
|
||||||
|
#### [v1.0.0-beta.7](https://github.com/oceanprotocol/squid-js/compare/v0.8.3...v1.0.0-beta.7)
|
||||||
|
|
||||||
|
> 22 November 2019
|
||||||
|
|
||||||
|
- fresh package-lock [`0552bcc`](https://github.com/oceanprotocol/squid-js/commit/0552bcc577fb83a5e9d683cb23dcbdfd23f0fa1c)
|
||||||
|
- Change linter config. [`3d7d1f3`](https://github.com/oceanprotocol/squid-js/commit/3d7d1f3972a665ccce4a1d712077435c1cd87459)
|
||||||
|
- tweak printWidth [`143fcbe`](https://github.com/oceanprotocol/squid-js/commit/143fcbecf3661d6a0da7f7d44f74d82caca41ad1)
|
||||||
|
|
||||||
#### [v0.8.3](https://github.com/oceanprotocol/squid-js/compare/v0.8.2...v0.8.3)
|
#### [v0.8.3](https://github.com/oceanprotocol/squid-js/compare/v0.8.2...v0.8.3)
|
||||||
|
|
||||||
> 22 November 2019
|
> 22 November 2019
|
||||||
|
|
||||||
- added xDai [`#336`](https://github.com/oceanprotocol/squid-js/pull/336)
|
- added xDai [`#336`](https://github.com/oceanprotocol/squid-js/pull/336)
|
||||||
|
- Release 0.8.3 [`c8e9bd2`](https://github.com/oceanprotocol/squid-js/commit/c8e9bd24c3850c250df02197582e430dee97152b)
|
||||||
|
|
||||||
#### [v0.8.2](https://github.com/oceanprotocol/squid-js/compare/v0.8.1...v0.8.2)
|
#### [v0.8.2](https://github.com/oceanprotocol/squid-js/compare/v0.8.1...v0.8.2)
|
||||||
|
|
||||||
|
194
MIGRATION.md
Normal file
194
MIGRATION.md
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
# Migration Guide
|
||||||
|
|
||||||
|
Instructions on how to migrate between breaking versions.
|
||||||
|
|
||||||
|
## v0.8.3 → v1.0.0
|
||||||
|
|
||||||
|
### Ocean Protocol Components Requirements
|
||||||
|
|
||||||
|
squid-js v1.0.0 only works against:
|
||||||
|
|
||||||
|
- Aquarius v1.0.2+
|
||||||
|
- Brizo v0.7.0+
|
||||||
|
- Events Handler v0.3.0+
|
||||||
|
- Keeper Contracts v0.12.7+
|
||||||
|
|
||||||
|
### DDO Structure
|
||||||
|
|
||||||
|
The whole structure of the DDO has been changed based on [OEP-12](https://github.com/oceanprotocol/OEPs/tree/master/12) and [OEP-8 v0.4](https://github.com/oceanprotocol/OEPs/tree/master/8/v0.4) to better accomodate the DDOs to hold additional services, like execution of workflows and algorithms.
|
||||||
|
|
||||||
|
For migrating, you only have to deal with the `metadata` service holding the asset metadata, which was restructured too:
|
||||||
|
|
||||||
|
old:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"service": [
|
||||||
|
{
|
||||||
|
"serviceDefinitionId": "0",
|
||||||
|
"serviceEndpoint": "http://localhost:5000/api/v1/aquarius/assets/ddo/{did}",
|
||||||
|
"type": "Metadata",
|
||||||
|
"metadata": {
|
||||||
|
"base": {
|
||||||
|
"name": "Madrid Weather forecast",
|
||||||
|
"description": "Wheater forecast of Europe/Madrid in XML format",
|
||||||
|
"dateCreated": "2019-05-16T12:36:14.535Z",
|
||||||
|
"author": "Norwegian Meteorological Institute",
|
||||||
|
"type": "dataset",
|
||||||
|
"license": "Public Domain",
|
||||||
|
"price": "123000000000000000000",
|
||||||
|
"copyrightHolder": "Norwegian Meteorological Institute",
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"url": "https://example-url.net/weather/forecast/madrid/350750305731.xml",
|
||||||
|
"contentLength": 1000,
|
||||||
|
"contentType": "text/xml",
|
||||||
|
"compression": "none"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": ["Other"],
|
||||||
|
"links": [],
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"additionalInformation": {
|
||||||
|
"updateFrequency": null,
|
||||||
|
"structuredMarkup": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
NEW. Where `main` now holds the non-changable attributes only, everything else has been moved to `additionalInformation`. Likewise, `serviceDefinitionId` is now `index`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"service": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"serviceEndpoint": "http://localhost:5000/api/v1/aquarius/assets/ddo/{did}",
|
||||||
|
"type": "metadata",
|
||||||
|
"attributes": {
|
||||||
|
"main": {
|
||||||
|
"name": "Madrid Weather forecast",
|
||||||
|
"dateCreated": "2019-05-16T12:36:14.535Z",
|
||||||
|
"author": "Norwegian Meteorological Institute",
|
||||||
|
"type": "dataset",
|
||||||
|
"license": "Public Domain",
|
||||||
|
"price": "123000000000000000000",
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"url": "https://example-url.net/weather/forecast/madrid/350750305731.xml",
|
||||||
|
"contentLength": "1000",
|
||||||
|
"contentType": "text/xml",
|
||||||
|
"compression": "none"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"additionalInformation": {
|
||||||
|
"description": "Weather forecast of Europe/Madrid in XML format",
|
||||||
|
"copyrightHolder": "Norwegian Meteorological Institute",
|
||||||
|
"categories": ["Other"],
|
||||||
|
"links": [],
|
||||||
|
"tags": [],
|
||||||
|
"updateFrequency": null,
|
||||||
|
"structuredMarkup": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Those changes require updates to your code whenever you fetch or create a new DDO as outlined below.
|
||||||
|
|
||||||
|
Likewise, you have to migrate the DDOs of existing registered assets to the new structure. For this you can run our migration script on your respective Aquarius instance.
|
||||||
|
|
||||||
|
- [script: CHANGEME](https://github.com/oceanprotocol/CHANGEME)
|
||||||
|
|
||||||
|
### Lowercase Service Names
|
||||||
|
|
||||||
|
All the service names are now in lowercase:
|
||||||
|
|
||||||
|
old:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const service = ddo.findServiceByType('Access')
|
||||||
|
```
|
||||||
|
|
||||||
|
NEW:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const service = ddo.findServiceByType('access')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Accessing New Metadata Structure
|
||||||
|
|
||||||
|
Typically you would grab and restructure asset metadata for display. This works the same as before but the key names have changed:
|
||||||
|
|
||||||
|
old:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { metadata } = ddo.findServiceByType('Metadata')
|
||||||
|
const { base, additionalInformation } = metadata
|
||||||
|
console.log(base.price)
|
||||||
|
console.log(base.description)
|
||||||
|
```
|
||||||
|
|
||||||
|
NEW:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
|
const { main, additionalInformation } = attributes
|
||||||
|
console.log(main.price)
|
||||||
|
console.log(additionalInformation.description)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `service.serviceDefinitionId` → `service.index`
|
||||||
|
|
||||||
|
old:
|
||||||
|
|
||||||
|
```js
|
||||||
|
await ocean.assets.order(ddo.id, service.serviceDefinitionId, accounts[0])
|
||||||
|
```
|
||||||
|
|
||||||
|
NEW:
|
||||||
|
|
||||||
|
```js
|
||||||
|
await ocean.assets.order(ddo.id, service.index, accounts[0])
|
||||||
|
```
|
||||||
|
|
||||||
|
The value of of `service.index` is now also a number, and not a string.
|
||||||
|
|
||||||
|
### File Attribute Changes
|
||||||
|
|
||||||
|
In the file attributes, the `contentLength` is now a string.
|
||||||
|
|
||||||
|
old:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"url": "https://example-url.net/weather/forecast/madrid/350750305731.xml",
|
||||||
|
"contentLength": 1000,
|
||||||
|
"contentType": "text/xml"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
NEW:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"url": "https://example-url.net/weather/forecast/madrid/350750305731.xml",
|
||||||
|
"contentLength": "1000",
|
||||||
|
"contentType": "text/xml"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
@ -21,6 +21,7 @@
|
|||||||
- [Get started](#get-started)
|
- [Get started](#get-started)
|
||||||
- [Examples](#examples)
|
- [Examples](#examples)
|
||||||
- [Documentation](#documentation)
|
- [Documentation](#documentation)
|
||||||
|
- [Migration Guide](#migration-guide)
|
||||||
- [Development](#development)
|
- [Development](#development)
|
||||||
- [Testing](#testing)
|
- [Testing](#testing)
|
||||||
- [Unit Tests](#unit-tests)
|
- [Unit Tests](#unit-tests)
|
||||||
@ -75,6 +76,7 @@ For an overview of endpoint configurations making up various Ocean networks, ple
|
|||||||
|
|
||||||
You can see how `squid-js` is used on:
|
You can see how `squid-js` is used on:
|
||||||
|
|
||||||
|
- [Docs: React Tutorial](https://docs.oceanprotocol.com/tutorials/react-setup/)
|
||||||
- [Integration test](/src/integration/ocean/)
|
- [Integration test](/src/integration/ocean/)
|
||||||
- [Tuna](https://github.com/oceanprotocol/tuna/tree/develop/node)
|
- [Tuna](https://github.com/oceanprotocol/tuna/tree/develop/node)
|
||||||
|
|
||||||
@ -89,6 +91,12 @@ Alternatively, you can generate the raw TypeDoc documentation locally by running
|
|||||||
npm run doc
|
npm run doc
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Migration Guide
|
||||||
|
|
||||||
|
Instructions on how to migrate between breaking versions:
|
||||||
|
|
||||||
|
- [Migration Guide](MIGRATION.md)
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
To start development you need to:
|
To start development you need to:
|
||||||
|
@ -1 +0,0 @@
|
|||||||
this document has been moved to [here](https://github.com/oceanprotocol/dev-ocean/blob/master/doc/architecture/squid.md).
|
|
@ -1,9 +1,9 @@
|
|||||||
import { Config } from '../src'
|
import { Config } from '../src'
|
||||||
const HDWalletProvider = require('@truffle/hdwallet-provider')
|
import HDWalletProvider from '@truffle/hdwallet-provider'
|
||||||
|
|
||||||
const configJson: Config = {
|
const configJson: Config = {
|
||||||
nodeUri: 'http://localhost:8545',
|
nodeUri: 'http://localhost:8545',
|
||||||
aquariusUri: 'http://172.15.0.15:5000',
|
aquariusUri: 'http://aquarius:5000',
|
||||||
brizoUri: 'http://localhost:8030',
|
brizoUri: 'http://localhost:8030',
|
||||||
secretStoreUri: 'http://localhost:12001',
|
secretStoreUri: 'http://localhost:12001',
|
||||||
brizoAddress: '0x068ed00cf0441e4829d9784fcbe7b9e26d4bd8d0',
|
brizoAddress: '0x068ed00cf0441e4829d9784fcbe7b9e26d4bd8d0',
|
||||||
@ -44,12 +44,7 @@ if (process.env.SEED_WORDS) {
|
|||||||
const seedphrase = process.env.SEED_WORDS
|
const seedphrase = process.env.SEED_WORDS
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
configJson.web3Provider = new HDWalletProvider(
|
configJson.web3Provider = new HDWalletProvider(seedphrase, configJson.nodeUri, 0, 5)
|
||||||
seedphrase,
|
|
||||||
configJson.nodeUri,
|
|
||||||
0,
|
|
||||||
5
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const config: Config & { forceVerbose: Config } = configJson as any
|
export const config: Config & { forceVerbose: Config } = configJson as any
|
||||||
|
@ -40,19 +40,33 @@ describe('Asset Owners', () => {
|
|||||||
assert.isTrue(isProvider)
|
assert.isTrue(isProvider)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should get the assets owned by a user', async () => {
|
it('should be added correctly a permission on an asset', async () => {
|
||||||
const { length: initialLength } = await ocean.assets.ownerAssets(
|
const ddo = await ocean.assets.create(metadata as any, account1)
|
||||||
account2.getId()
|
|
||||||
|
assert.isFalse(
|
||||||
|
await ocean.keeper.didRegistry.getPermission(ddo.id, account2.getId())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await ocean.keeper.didRegistry.grantPermission(
|
||||||
|
ddo.id,
|
||||||
|
account2.getId(),
|
||||||
|
account1.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.isTrue(
|
||||||
|
await ocean.keeper.didRegistry.getPermission(ddo.id, account2.getId())
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should get the assets owned by a user', async () => {
|
||||||
|
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(
|
const { length: finalLength } = await ocean.assets.ownerAssets(account2.getId())
|
||||||
account2.getId()
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.equal(finalLength - initialLength, 1)
|
assert.equal(finalLength - initialLength, 1)
|
||||||
})
|
})
|
||||||
@ -72,16 +86,13 @@ describe('Asset Owners', () => {
|
|||||||
// Granting access
|
// Granting access
|
||||||
try {
|
try {
|
||||||
await account2.requestTokens(
|
await account2.requestTokens(
|
||||||
+metadata.base.price *
|
+metadata.main.price * 10 ** -(await ocean.keeper.token.decimals())
|
||||||
10 ** -(await ocean.keeper.token.decimals())
|
|
||||||
)
|
)
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
await ocean.assets.order(
|
const { index } = ddo.findServiceByType('access')
|
||||||
ddo.id,
|
|
||||||
ddo.findServiceByType('Access').serviceDefinitionId,
|
await ocean.assets.order(ddo.id, index, account2)
|
||||||
account2
|
|
||||||
)
|
|
||||||
// Access granted
|
// Access granted
|
||||||
|
|
||||||
const { length: finalLength2 } = await ocean.assets.consumerAssets(
|
const { length: finalLength2 } = await ocean.assets.consumerAssets(
|
||||||
@ -89,4 +100,14 @@ describe('Asset Owners', () => {
|
|||||||
)
|
)
|
||||||
assert.equal(finalLength2 - initialLength, 1)
|
assert.equal(finalLength2 - initialLength, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should be able to transfer ownership', async () => {
|
||||||
|
const { id } = await ocean.assets.create(metadata as any, account1)
|
||||||
|
|
||||||
|
// transfer
|
||||||
|
await ocean.assets.transferOwnership(id, account2.getId())
|
||||||
|
const newOwner = await ocean.keeper.didRegistry.getDIDOwner(id)
|
||||||
|
|
||||||
|
assert.equal(newOwner, account2.getId())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -19,6 +19,12 @@ describe('Authentication Token', () => {
|
|||||||
;[account1, account2] = await ocean.accounts.list()
|
;[account1, account2] = await ocean.accounts.list()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
try {
|
||||||
|
localStorage.clear()
|
||||||
|
} catch {}
|
||||||
|
})
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
@ -31,26 +31,22 @@ describe('Consume Asset', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should regiester a asset', async () => {
|
it('should register an 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(
|
assert.isAtLeast(ddo.authentication.length, 1, 'Default authentication not added')
|
||||||
ddo.authentication.length,
|
|
||||||
1,
|
|
||||||
'Default authentication not added'
|
|
||||||
)
|
|
||||||
assert.isDefined(
|
assert.isDefined(
|
||||||
ddo.findServiceByType('Access'),
|
ddo.findServiceByType('access'),
|
||||||
"DDO Access service doesn't exist"
|
"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 =
|
const claimedTokens =
|
||||||
+metadata.base.price * 10 ** -(await ocean.keeper.token.decimals())
|
+metadata.main.price * 10 ** -(await ocean.keeper.token.decimals())
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await consumer.requestTokens(claimedTokens)
|
await consumer.requestTokens(claimedTokens)
|
||||||
@ -64,11 +60,11 @@ describe('Consume Asset', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
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(
|
serviceAgreementSignatureResult = await ocean.agreements.prepare(
|
||||||
ddo.id,
|
ddo.id,
|
||||||
accessService.serviceDefinitionId,
|
accessService.index,
|
||||||
consumer
|
consumer
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -86,12 +82,12 @@ describe('Consume Asset', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
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,
|
||||||
serviceAgreementSignatureResult.agreementId,
|
serviceAgreementSignatureResult.agreementId,
|
||||||
accessService.serviceDefinitionId,
|
accessService.index,
|
||||||
serviceAgreementSignatureResult.signature,
|
serviceAgreementSignatureResult.signature,
|
||||||
consumer,
|
consumer,
|
||||||
publisher
|
publisher
|
||||||
@ -115,7 +111,7 @@ describe('Consume Asset', () => {
|
|||||||
it('should lock the payment by the consumer', async () => {
|
it('should lock the payment by the consumer', async () => {
|
||||||
const paid = await ocean.agreements.conditions.lockReward(
|
const paid = await ocean.agreements.conditions.lockReward(
|
||||||
serviceAgreementSignatureResult.agreementId,
|
serviceAgreementSignatureResult.agreementId,
|
||||||
ddo.findServiceByType('Metadata').metadata.base.price,
|
ddo.findServiceByType('metadata').attributes.main.price,
|
||||||
consumer
|
consumer
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -156,13 +152,13 @@ describe('Consume Asset', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
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(
|
const path = await ocean.assets.consume(
|
||||||
serviceAgreementSignatureResult.agreementId,
|
serviceAgreementSignatureResult.agreementId,
|
||||||
ddo.id,
|
ddo.id,
|
||||||
accessService.serviceDefinitionId,
|
accessService.index,
|
||||||
consumer,
|
consumer,
|
||||||
folder
|
folder
|
||||||
)
|
)
|
||||||
@ -182,14 +178,14 @@ describe('Consume Asset', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should consume and store one assets', async () => {
|
it('should consume and store one asset', async () => {
|
||||||
const accessService = ddo.findServiceByType('Access')
|
const accessService = ddo.findServiceByType('access')
|
||||||
|
|
||||||
const folder = '/tmp/ocean/squid-js-2'
|
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.index,
|
||||||
consumer,
|
consumer,
|
||||||
folder,
|
folder,
|
||||||
1
|
1
|
||||||
|
@ -50,18 +50,17 @@ describe('Consume Asset (Brizo)', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should order the asset', async () => {
|
it('should order the asset', async () => {
|
||||||
const accessService = ddo.findServiceByType('Access')
|
const accessService = ddo.findServiceByType('access')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await consumer.requestTokens(
|
await consumer.requestTokens(
|
||||||
+metadata.base.price *
|
+metadata.main.price * 10 ** -(await ocean.keeper.token.decimals())
|
||||||
10 ** -(await ocean.keeper.token.decimals())
|
|
||||||
)
|
)
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
const steps = []
|
const steps = []
|
||||||
agreementId = await ocean.assets
|
agreementId = await ocean.assets
|
||||||
.order(ddo.id, accessService.serviceDefinitionId, consumer)
|
.order(ddo.id, accessService.index, consumer)
|
||||||
.next(step => steps.push(step))
|
.next(step => steps.push(step))
|
||||||
|
|
||||||
assert.isDefined(agreementId)
|
assert.isDefined(agreementId)
|
||||||
@ -69,13 +68,13 @@ describe('Consume Asset (Brizo)', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
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(
|
const path = await ocean.assets.consume(
|
||||||
agreementId,
|
agreementId,
|
||||||
ddo.id,
|
ddo.id,
|
||||||
accessService.serviceDefinitionId,
|
accessService.index,
|
||||||
consumer,
|
consumer,
|
||||||
folder
|
folder
|
||||||
)
|
)
|
||||||
|
@ -30,10 +30,12 @@ xdescribe('Consume Asset (Large size)', () => {
|
|||||||
}
|
}
|
||||||
metadata = {
|
metadata = {
|
||||||
...baseMetadata,
|
...baseMetadata,
|
||||||
base: {
|
main: {
|
||||||
...baseMetadata.base,
|
...baseMetadata.main,
|
||||||
files: [
|
files: [
|
||||||
{
|
{
|
||||||
|
index: 0,
|
||||||
|
contentType: 'hello/hello',
|
||||||
url: 'https://speed.hetzner.de/1GB.bin'
|
url: 'https://speed.hetzner.de/1GB.bin'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -48,32 +50,27 @@ xdescribe('Consume Asset (Large size)', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should order the asset', async () => {
|
it('should order the asset', async () => {
|
||||||
const accessService = ddo.findServiceByType('Access')
|
const accessService = ddo.findServiceByType('access')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await consumer.requestTokens(
|
await consumer.requestTokens(
|
||||||
+metadata.base.price *
|
+metadata.main.price * 10 ** -(await ocean.keeper.token.decimals())
|
||||||
10 ** -(await ocean.keeper.token.decimals())
|
|
||||||
)
|
)
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
agreementId = await ocean.assets.order(
|
agreementId = await ocean.assets.order(ddo.id, accessService.index, consumer)
|
||||||
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(
|
const path = await ocean.assets.consume(
|
||||||
agreementId,
|
agreementId,
|
||||||
ddo.id,
|
ddo.id,
|
||||||
accessService.serviceDefinitionId,
|
accessService.index,
|
||||||
consumer,
|
consumer,
|
||||||
folder
|
folder
|
||||||
)
|
)
|
||||||
|
@ -4,11 +4,7 @@ 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 {
|
const { LockRewardCondition, EscrowReward, AccessSecretStoreCondition } = conditions
|
||||||
LockRewardCondition,
|
|
||||||
EscrowReward,
|
|
||||||
AccessSecretStoreCondition
|
|
||||||
} = conditions
|
|
||||||
|
|
||||||
describe('Register Escrow Access Secret Store Template', () => {
|
describe('Register Escrow Access Secret Store Template', () => {
|
||||||
let ocean: Ocean
|
let ocean: Ocean
|
||||||
@ -40,8 +36,7 @@ describe('Register Escrow Access Secret Store Template', () => {
|
|||||||
consumer = (await ocean.accounts.list())[2]
|
consumer = (await ocean.accounts.list())[2]
|
||||||
|
|
||||||
// Conditions
|
// Conditions
|
||||||
accessSecretStoreCondition =
|
accessSecretStoreCondition = keeper.conditions.accessSecretStoreCondition
|
||||||
keeper.conditions.accessSecretStoreCondition
|
|
||||||
lockRewardCondition = keeper.conditions.lockRewardCondition
|
lockRewardCondition = keeper.conditions.lockRewardCondition
|
||||||
escrowReward = keeper.conditions.escrowReward
|
escrowReward = keeper.conditions.escrowReward
|
||||||
|
|
||||||
|
300
integration/ocean/RegisterEscrowComputeExecutionTemplate.test.ts
Normal file
300
integration/ocean/RegisterEscrowComputeExecutionTemplate.test.ts
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import { config } from '../config'
|
||||||
|
|
||||||
|
import { Ocean, templates, conditions, utils, Account, Keeper } from '../../src' // @oceanprotocol/squid
|
||||||
|
|
||||||
|
const { LockRewardCondition, EscrowReward, ComputeExecutionCondition } = conditions
|
||||||
|
|
||||||
|
describe('Register Escrow Compute Execution Template', () => {
|
||||||
|
let ocean: Ocean
|
||||||
|
let keeper: Keeper
|
||||||
|
|
||||||
|
let template: templates.EscrowComputeExecutionTemplate
|
||||||
|
|
||||||
|
const url = 'https://example.com/did/ocean/test-attr-example.txt'
|
||||||
|
const checksum = 'b'.repeat(32)
|
||||||
|
let escrowAmount = 12
|
||||||
|
|
||||||
|
let templateManagerOwner: Account
|
||||||
|
let publisher: Account
|
||||||
|
let consumer: Account
|
||||||
|
|
||||||
|
let computeExecutionCondition: conditions.ComputeExecutionCondition
|
||||||
|
let lockRewardCondition: conditions.LockRewardCondition
|
||||||
|
let escrowReward: conditions.EscrowReward
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
ocean = await Ocean.getInstance(config)
|
||||||
|
keeper = ocean.keeper
|
||||||
|
|
||||||
|
template = keeper.templates.escrowComputeExecutionTemplate
|
||||||
|
|
||||||
|
// Accounts
|
||||||
|
templateManagerOwner = (await ocean.accounts.list())[0]
|
||||||
|
publisher = (await ocean.accounts.list())[1]
|
||||||
|
consumer = (await ocean.accounts.list())[2]
|
||||||
|
|
||||||
|
// Conditions
|
||||||
|
computeExecutionCondition = keeper.conditions.computeExecutionCondition
|
||||||
|
lockRewardCondition = keeper.conditions.lockRewardCondition
|
||||||
|
escrowReward = keeper.conditions.escrowReward
|
||||||
|
|
||||||
|
if (!ocean.keeper.dispenser) {
|
||||||
|
escrowAmount = 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Propose and approve template', () => {
|
||||||
|
it('should propose the template', async () => {
|
||||||
|
await keeper.templateStoreManager.proposeTemplate(
|
||||||
|
template.getAddress(),
|
||||||
|
consumer.getId(),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
// TODO: Use a event to detect template mined
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2 * 1000))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should approve the template', async () => {
|
||||||
|
await keeper.templateStoreManager.approveTemplate(
|
||||||
|
template.getAddress(),
|
||||||
|
templateManagerOwner.getId(),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
// TODO: Use a event to detect template mined
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2 * 1000))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Full flow', () => {
|
||||||
|
const agreementId = `0x${utils.generateId()}`
|
||||||
|
const did = `0x${utils.generateId()}`
|
||||||
|
|
||||||
|
let conditionIdCompute: string
|
||||||
|
let conditionIdLock: string
|
||||||
|
let conditionIdEscrow: string
|
||||||
|
|
||||||
|
it('should register a DID', async () => {
|
||||||
|
await keeper.didRegistry.registerAttribute(
|
||||||
|
did,
|
||||||
|
checksum,
|
||||||
|
[],
|
||||||
|
url,
|
||||||
|
publisher.getId()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should generate the condition IDs', async () => {
|
||||||
|
conditionIdCompute = await computeExecutionCondition.generateIdHash(
|
||||||
|
agreementId,
|
||||||
|
did,
|
||||||
|
consumer.getId()
|
||||||
|
)
|
||||||
|
conditionIdLock = await lockRewardCondition.generateIdHash(
|
||||||
|
agreementId,
|
||||||
|
await escrowReward.getAddress(),
|
||||||
|
escrowAmount
|
||||||
|
)
|
||||||
|
conditionIdEscrow = await escrowReward.generateIdHash(
|
||||||
|
agreementId,
|
||||||
|
escrowAmount,
|
||||||
|
publisher.getId(),
|
||||||
|
consumer.getId(),
|
||||||
|
conditionIdLock,
|
||||||
|
conditionIdCompute
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should have conditions types', async () => {
|
||||||
|
const conditionTypes = await template.getConditionTypes()
|
||||||
|
|
||||||
|
assert.equal(conditionTypes.length, 3, 'Expected 3 conditions.')
|
||||||
|
assert.deepEqual(
|
||||||
|
[...conditionTypes].sort(),
|
||||||
|
[
|
||||||
|
computeExecutionCondition.getAddress(),
|
||||||
|
escrowReward.getAddress(),
|
||||||
|
lockRewardCondition.getAddress()
|
||||||
|
].sort(),
|
||||||
|
"The conditions doesn't match"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should have condition instances asociated', async () => {
|
||||||
|
const conditionInstances = await template.getConditions()
|
||||||
|
|
||||||
|
assert.equal(conditionInstances.length, 3, 'Expected 3 conditions.')
|
||||||
|
|
||||||
|
const conditionClasses = [
|
||||||
|
ComputeExecutionCondition,
|
||||||
|
EscrowReward,
|
||||||
|
LockRewardCondition
|
||||||
|
]
|
||||||
|
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 () => {
|
||||||
|
const agreement = await template.createAgreement(
|
||||||
|
agreementId,
|
||||||
|
did,
|
||||||
|
[conditionIdCompute, conditionIdLock, conditionIdEscrow],
|
||||||
|
[0, 0, 0],
|
||||||
|
[0, 0, 0],
|
||||||
|
consumer.getId(),
|
||||||
|
publisher.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.isTrue(agreement.status)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not trigger the compute', async () => {
|
||||||
|
const computeTriggered = await computeExecutionCondition.wasComputeTriggered(
|
||||||
|
did,
|
||||||
|
consumer.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.isFalse(computeTriggered, 'Compute has been triggered.')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fulfill LockRewardCondition', async () => {
|
||||||
|
try {
|
||||||
|
await consumer.requestTokens(escrowAmount)
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
await keeper.token.approve(
|
||||||
|
lockRewardCondition.getAddress(),
|
||||||
|
escrowAmount,
|
||||||
|
consumer.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
const fulfill = await lockRewardCondition.fulfill(
|
||||||
|
agreementId,
|
||||||
|
escrowReward.getAddress(),
|
||||||
|
escrowAmount,
|
||||||
|
consumer.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.isDefined(fulfill.events.Fulfilled, 'Not Fulfilled event.')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fulfill ComputeExecutionCondition', async () => {
|
||||||
|
const fulfill = await computeExecutionCondition.fulfill(
|
||||||
|
agreementId,
|
||||||
|
did,
|
||||||
|
consumer.getId(),
|
||||||
|
publisher.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.isDefined(fulfill.events.Fulfilled, 'Not Fulfilled event.')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fulfill EscrowReward', async () => {
|
||||||
|
const fulfill = await escrowReward.fulfill(
|
||||||
|
agreementId,
|
||||||
|
escrowAmount,
|
||||||
|
publisher.getId(),
|
||||||
|
consumer.getId(),
|
||||||
|
conditionIdLock,
|
||||||
|
conditionIdCompute,
|
||||||
|
consumer.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.isDefined(fulfill.events.Fulfilled, 'Not Fulfilled event.')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should grant the access to the consumer', async () => {
|
||||||
|
const computeTriggered = await computeExecutionCondition.wasComputeTriggered(
|
||||||
|
did,
|
||||||
|
consumer.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.isTrue(computeTriggered, 'Compute has not been triggered.')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Short flow', () => {
|
||||||
|
const did = utils.generateId()
|
||||||
|
|
||||||
|
let agreementId
|
||||||
|
|
||||||
|
it('should register a DID', async () => {
|
||||||
|
// This part is executed inside Ocean.assets.create()
|
||||||
|
await keeper.didRegistry.registerAttribute(
|
||||||
|
did,
|
||||||
|
checksum,
|
||||||
|
[],
|
||||||
|
url,
|
||||||
|
publisher.getId()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should create a new agreement (short way)', async () => {
|
||||||
|
agreementId = await template.createFullAgreement(
|
||||||
|
did,
|
||||||
|
escrowAmount,
|
||||||
|
consumer.getId(),
|
||||||
|
publisher.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.match(agreementId, /^0x[a-f0-9]{64}$/i)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not grant the access to the consumer', async () => {
|
||||||
|
const computeTriggered = await computeExecutionCondition.wasComputeTriggered(
|
||||||
|
did,
|
||||||
|
consumer.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.isFalse(computeTriggered, 'Compute has been triggered.')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fulfill the conditions from consumer side', async () => {
|
||||||
|
try {
|
||||||
|
await consumer.requestTokens(escrowAmount)
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
await ocean.agreements.conditions.lockReward(
|
||||||
|
agreementId,
|
||||||
|
escrowAmount,
|
||||||
|
consumer
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fulfill the conditions from computing side', async () => {
|
||||||
|
await ocean.agreements.conditions.grantServiceExecution(
|
||||||
|
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 () => {
|
||||||
|
const computeTriggered = await computeExecutionCondition.wasComputeTriggered(
|
||||||
|
did,
|
||||||
|
consumer.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.isTrue(computeTriggered, 'Compute has not been triggered.')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -35,57 +35,41 @@ describe('Search Asset', () => {
|
|||||||
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
|
test2length = (await ocean.assets.search(`Test2${testHash}`)).results.length
|
||||||
.length
|
test3length = (await ocean.assets.search(`Test3${testHash}`)).results.length
|
||||||
test3length = (await ocean.assets.search(`Test3${testHash}`)).results
|
|
||||||
.length
|
|
||||||
|
|
||||||
if (!ocean.keeper.dispenser) {
|
if (!ocean.keeper.dispenser) {
|
||||||
price = 0
|
price = 0
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should regiester some a asset', async () => {
|
it('should register an asset', async () => {
|
||||||
assert.instanceOf(
|
assert.instanceOf(
|
||||||
await ocean.assets.create(
|
await ocean.assets.create(metadataGenerator('Test1') as any, publisher),
|
||||||
metadataGenerator('Test1') as any,
|
|
||||||
publisher
|
|
||||||
),
|
|
||||||
DDO
|
DDO
|
||||||
)
|
)
|
||||||
assert.instanceOf(
|
assert.instanceOf(
|
||||||
await ocean.assets.create(
|
await ocean.assets.create(metadataGenerator('Test2') as any, publisher),
|
||||||
metadataGenerator('Test2') as any,
|
|
||||||
publisher
|
|
||||||
),
|
|
||||||
DDO
|
DDO
|
||||||
)
|
)
|
||||||
assert.instanceOf(
|
assert.instanceOf(
|
||||||
await ocean.assets.create(
|
await ocean.assets.create(metadataGenerator('Test2') as any, publisher),
|
||||||
metadataGenerator('Test2') as any,
|
|
||||||
publisher
|
|
||||||
),
|
|
||||||
DDO
|
DDO
|
||||||
)
|
)
|
||||||
assert.instanceOf(
|
assert.instanceOf(
|
||||||
await ocean.assets.create(
|
await ocean.assets.create(metadataGenerator('Test3') as any, publisher),
|
||||||
metadataGenerator('Test3') as any,
|
|
||||||
publisher
|
|
||||||
),
|
|
||||||
DDO
|
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 -
|
(await ocean.assets.search(`Test2${testHash}`)).results.length - test2length,
|
||||||
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 -
|
(await ocean.assets.search(`Test3${testHash}`)).results.length - test3length,
|
||||||
test3length,
|
|
||||||
1,
|
1,
|
||||||
'Something was wrong searching the assets'
|
'Something was wrong searching the assets'
|
||||||
)
|
)
|
||||||
|
@ -21,11 +21,7 @@ describe('Secret Store', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should encrypt a text', async () => {
|
it('should encrypt a text', async () => {
|
||||||
encryptedContent = await ocean.secretStore.encrypt(
|
encryptedContent = await ocean.secretStore.encrypt(did.getId(), content, account)
|
||||||
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)
|
||||||
|
@ -46,7 +46,6 @@ describe('Signature', () => {
|
|||||||
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 serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate()
|
const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate()
|
||||||
|
|
||||||
@ -54,17 +53,20 @@ describe('Signature', () => {
|
|||||||
id: did,
|
id: did,
|
||||||
service: [
|
service: [
|
||||||
{
|
{
|
||||||
type: 'Access',
|
type: 'access',
|
||||||
|
index: 0,
|
||||||
purchaseEndpoint: undefined,
|
purchaseEndpoint: undefined,
|
||||||
serviceEndpoint: undefined,
|
serviceEndpoint: undefined,
|
||||||
serviceDefinitionId,
|
|
||||||
templateId,
|
templateId,
|
||||||
serviceAgreementTemplate
|
attributes: {
|
||||||
|
serviceAgreementTemplate
|
||||||
|
}
|
||||||
} as any,
|
} as any,
|
||||||
{
|
{
|
||||||
type: 'Metadata',
|
type: 'metadata',
|
||||||
metadata: {
|
index: 1,
|
||||||
base: {
|
attributes: {
|
||||||
|
main: {
|
||||||
price: 10
|
price: 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,13 +76,9 @@ describe('Signature', () => {
|
|||||||
|
|
||||||
const signature = await ocean.utils.agreements.signServiceAgreement(
|
const signature = await ocean.utils.agreements.signServiceAgreement(
|
||||||
ddo,
|
ddo,
|
||||||
serviceDefinitionId,
|
0,
|
||||||
agreementId,
|
agreementId,
|
||||||
[
|
[`0x${'1'.repeat(64)}`, `0x${'2'.repeat(64)}`, `0x${'3'.repeat(64)}`],
|
||||||
`0x${'1'.repeat(64)}`,
|
|
||||||
`0x${'2'.repeat(64)}`,
|
|
||||||
`0x${'3'.repeat(64)}`
|
|
||||||
],
|
|
||||||
consumer
|
consumer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -11,7 +11,8 @@ describe('Versions', () => {
|
|||||||
ocean = await Ocean.getInstance(config)
|
ocean = await Ocean.getInstance(config)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should returns the versions', async () => {
|
// TODO: enable again after new versions of Brizo
|
||||||
|
xit('should return 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)
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"lib": ["es6", "es7", "dom"],
|
"lib": ["es6", "es7", "dom"],
|
||||||
"noUnusedLocals": true
|
"noUnusedLocals": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,33 @@
|
|||||||
import { MetaData } from '../../src' // @oceanprotocol/squid
|
import { MetaData } from '../../src' // @oceanprotocol/squid
|
||||||
|
|
||||||
const metadata: Partial<MetaData> = {
|
const metadata: Partial<MetaData> = {
|
||||||
base: {
|
main: {
|
||||||
name: undefined,
|
name: undefined,
|
||||||
type: 'dataset',
|
type: 'dataset',
|
||||||
description:
|
|
||||||
'Weather information of UK including temperature and humidity',
|
|
||||||
dateCreated: '2012-10-10T17:00:00Z',
|
dateCreated: '2012-10-10T17:00:00Z',
|
||||||
datePublished: '2012-10-10T17:00:00Z',
|
datePublished: '2012-10-10T17:00:00Z',
|
||||||
author: 'Met Office',
|
author: 'Met Office',
|
||||||
license: 'CC-BY',
|
license: 'CC-BY',
|
||||||
|
price: '21' + '0'.repeat(18),
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
contentType: 'application/json',
|
||||||
|
url:
|
||||||
|
'https://raw.githubusercontent.com/oceanprotocol/squid-js/master/package.json'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
contentType: 'text/plain',
|
||||||
|
url:
|
||||||
|
'https://raw.githubusercontent.com/oceanprotocol/squid-js/master/README.md'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
additionalInformation: {
|
||||||
|
description: 'Weather information of UK including temperature and humidity',
|
||||||
copyrightHolder: 'Met Office',
|
copyrightHolder: 'Met Office',
|
||||||
workExample:
|
workExample: '423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68',
|
||||||
'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',
|
||||||
@ -27,34 +42,20 @@ const metadata: Partial<MetaData> = {
|
|||||||
],
|
],
|
||||||
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),
|
|
||||||
files: [
|
|
||||||
{
|
|
||||||
index: 0,
|
|
||||||
url:
|
|
||||||
'https://raw.githubusercontent.com/oceanprotocol/squid-js/master/package.json'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
index: 1,
|
|
||||||
url:
|
|
||||||
'https://raw.githubusercontent.com/oceanprotocol/squid-js/master/README.md'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateMetadata = (
|
export const generateMetadata = (name: string, price?: number): Partial<MetaData> => ({
|
||||||
name: string,
|
|
||||||
price?: number
|
|
||||||
): Partial<MetaData> => ({
|
|
||||||
...metadata,
|
...metadata,
|
||||||
base: {
|
main: {
|
||||||
...metadata.base,
|
...metadata.main,
|
||||||
name,
|
name,
|
||||||
price: (price || 21) + '0'.repeat(18)
|
price: (price || 21) + '0'.repeat(18)
|
||||||
|
},
|
||||||
|
additionalInformation: {
|
||||||
|
...metadata.additionalInformation
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const getMetadata = (price?: number) =>
|
export const getMetadata = (price?: number) => generateMetadata('TestAsset', price)
|
||||||
generateMetadata('TestAsset', price)
|
|
||||||
|
@ -11,15 +11,15 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "brizo",
|
"name": "brizo",
|
||||||
"version": "~0.4.5"
|
"version": "~0.7.2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "aquarius",
|
"name": "aquarius",
|
||||||
"version": "~0.3.8"
|
"version": "~1.0.5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "events-handler",
|
"name": "events-handler",
|
||||||
"version": "~0.1.2"
|
"version": "~0.3.4"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
6142
package-lock.json
generated
6142
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
32
package.json
32
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@oceanprotocol/squid",
|
"name": "@oceanprotocol/squid",
|
||||||
"version": "0.8.3",
|
"version": "1.0.0-beta.7",
|
||||||
"description": "JavaScript client library for Ocean Protocol",
|
"description": "JavaScript client library for Ocean Protocol",
|
||||||
"main": "./dist/node/squid.js",
|
"main": "./dist/node/squid.js",
|
||||||
"typings": "./dist/node/squid.d.ts",
|
"typings": "./dist/node/squid.d.ts",
|
||||||
@ -49,7 +49,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/oceanprotocol/squid-js#readme",
|
"homepage": "https://github.com/oceanprotocol/squid-js#readme",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"web3": "^1.2.0"
|
"web3": "^1.2.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oceanprotocol/keeper-contracts": "^0.12.7",
|
"@oceanprotocol/keeper-contracts": "^0.12.7",
|
||||||
@ -59,37 +59,37 @@
|
|||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
"save-file": "^2.3.1",
|
"save-file": "^2.3.1",
|
||||||
"uuid": "^3.3.3",
|
"uuid": "^3.3.3",
|
||||||
"web3": "1.2.1",
|
"web3": "^1.2.4",
|
||||||
"whatwg-url": "^7.1.0"
|
"whatwg-url": "^7.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@release-it/bumper": "^1.0.5",
|
"@release-it/bumper": "^1.0.5",
|
||||||
"@truffle/hdwallet-provider": "^1.0.23",
|
"@truffle/hdwallet-provider": "^1.0.26",
|
||||||
"@types/chai": "^4.2.4",
|
"@types/chai": "^4.2.6",
|
||||||
"@types/chai-spies": "^1.0.1",
|
"@types/chai-spies": "^1.0.1",
|
||||||
"@types/mocha": "^5.2.7",
|
"@types/mocha": "^5.2.7",
|
||||||
"@types/node": "^12.12.5",
|
"@types/node": "^12.12.14",
|
||||||
"@types/node-fetch": "^2.5.3",
|
"@types/node-fetch": "^2.5.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^2.6.0",
|
"@typescript-eslint/eslint-plugin": "^2.10.0",
|
||||||
"@typescript-eslint/parser": "^2.6.0",
|
"@typescript-eslint/parser": "^2.10.0",
|
||||||
"auto-changelog": "^1.16.2",
|
"auto-changelog": "^1.16.2",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"chai-spies": "^1.0.0",
|
"chai-spies": "^1.0.0",
|
||||||
"cross-env": "^6.0.3",
|
"cross-env": "^6.0.3",
|
||||||
"eslint": "^6.6.0",
|
"eslint": "^6.7.2",
|
||||||
"eslint-config-oceanprotocol": "^1.5.0",
|
"eslint-config-oceanprotocol": "^1.5.0",
|
||||||
"eslint-config-prettier": "^6.5.0",
|
"eslint-config-prettier": "^6.7.0",
|
||||||
"eslint-plugin-prettier": "^3.1.1",
|
"eslint-plugin-prettier": "^3.1.1",
|
||||||
"lcov-result-merger": "^3.1.0",
|
"lcov-result-merger": "^3.1.0",
|
||||||
"mocha": "^6.2.2",
|
"mocha": "^6.2.2",
|
||||||
"mock-local-storage": "^1.1.8",
|
"mock-local-storage": "^1.1.11",
|
||||||
"nyc": "^14.1.1",
|
"nyc": "^14.1.1",
|
||||||
"ora": "^4.0.2",
|
"ora": "^4.0.2",
|
||||||
"prettier": "^1.18.2",
|
"prettier": "^1.19.1",
|
||||||
"source-map-support": "^0.5.16",
|
"source-map-support": "^0.5.16",
|
||||||
"ts-node": "^8.4.1",
|
"ts-node": "^8.5.4",
|
||||||
"typedoc": "^0.15.0",
|
"typedoc": "^0.15.3",
|
||||||
"typescript": "^3.6.4",
|
"typescript": "^3.7.3",
|
||||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||||
"webpack": "^4.41.2",
|
"webpack": "^4.41.2",
|
||||||
"webpack-cli": "^3.3.10",
|
"webpack-cli": "^3.3.10",
|
||||||
|
@ -11,7 +11,7 @@ mkdir -p artifacts
|
|||||||
|
|
||||||
until [ $COMMAND_STATUS -eq 0 ] || [ $RETRY_COUNT -eq 120 ]; do
|
until [ $COMMAND_STATUS -eq 0 ] || [ $RETRY_COUNT -eq 120 ]; do
|
||||||
keeper_contracts_docker_id=$(docker container ls | grep keeper-contracts | awk '{print $1}')
|
keeper_contracts_docker_id=$(docker container ls | grep keeper-contracts | awk '{print $1}')
|
||||||
docker cp "${keeper_contracts_docker_id}":/keeper-contracts/artifacts/ready ./artifacts/ > /dev/null 2>&1
|
docker cp ${keeper_contracts_docker_id}:/keeper-contracts/artifacts/ready ./artifacts/ > /dev/null 2>&1
|
||||||
COMMAND_STATUS=$?
|
COMMAND_STATUS=$?
|
||||||
sleep 5
|
sleep 5
|
||||||
(( RETRY_COUNT=RETRY_COUNT+1 ))
|
(( RETRY_COUNT=RETRY_COUNT+1 ))
|
||||||
|
@ -15,10 +15,7 @@ const outPath = './dist/squid-js.json'
|
|||||||
const files = ['./src/squid.ts']
|
const files = ['./src/squid.ts']
|
||||||
|
|
||||||
// specifically point to tsconfig, otherwise TypeDoc fails
|
// specifically point to tsconfig, otherwise TypeDoc fails
|
||||||
const config = typescript.findConfigFile(
|
const config = typescript.findConfigFile('./tsconfig.js', typescript.sys.fileExists)
|
||||||
'./tsconfig.js',
|
|
||||||
typescript.sys.fileExists
|
|
||||||
)
|
|
||||||
|
|
||||||
const generateJson = () => {
|
const generateJson = () => {
|
||||||
const spinnerTypedoc = ora('Generating TypeDoc json...').start()
|
const spinnerTypedoc = ora('Generating TypeDoc json...').start()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as Web3 from 'web3'
|
import 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'
|
||||||
@ -68,9 +68,7 @@ export abstract class Instantiable {
|
|||||||
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(
|
LoggerInstance.warn('getInstance() methods has needs to be added to child class.')
|
||||||
'getInstance() methods has needs to be added to child class.'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static setInstanceConfig<T extends Instantiable>(
|
protected static setInstanceConfig<T extends Instantiable>(
|
||||||
|
@ -40,26 +40,16 @@ 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(
|
.post(`${accessToken.service_endpoint}/${accessToken.resource_id}`, payload)
|
||||||
`${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(
|
this.logger.error('Failed: ', response.status, response.statusText)
|
||||||
'Failed: ',
|
|
||||||
response.status,
|
|
||||||
response.statusText
|
|
||||||
)
|
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
.then((consumptionUrl: string): string => {
|
.then((consumptionUrl: string): string => {
|
||||||
this.logger.error(
|
this.logger.error('Success accessing consume endpoint: ', consumptionUrl)
|
||||||
'Success accessing consume endpoint: ',
|
|
||||||
consumptionUrl
|
|
||||||
)
|
|
||||||
return consumptionUrl
|
return consumptionUrl
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@ -134,10 +124,7 @@ export class Aquarius extends Instantiable {
|
|||||||
return this.transformResult(results)
|
return this.transformResult(results)
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.logger.error(
|
this.logger.error('Error fetching querying metadata by text: ', error)
|
||||||
'Error fetching querying metadata by text: ',
|
|
||||||
error
|
|
||||||
)
|
|
||||||
return this.transformResult()
|
return this.transformResult()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -186,8 +173,7 @@ export class Aquarius extends Instantiable {
|
|||||||
metadataServiceEndpoint?: string
|
metadataServiceEndpoint?: string
|
||||||
): Promise<DDO> {
|
): Promise<DDO> {
|
||||||
did = did && DID.parse(did)
|
did = did && DID.parse(did)
|
||||||
const fullUrl =
|
const fullUrl = metadataServiceEndpoint || `${this.url}${apiPath}/${did.getDid()}`
|
||||||
metadataServiceEndpoint || `${this.url}${apiPath}/${did.getDid()}`
|
|
||||||
const result = await this.ocean.utils.fetch
|
const result = await this.ocean.utils.fetch
|
||||||
.get(fullUrl)
|
.get(fullUrl)
|
||||||
.then((response: any) => {
|
.then((response: any) => {
|
||||||
@ -222,12 +208,7 @@ export class Aquarius extends Instantiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private transformResult(
|
private transformResult(
|
||||||
{
|
{ results, page, total_pages: totalPages, total_results: totalResults }: any = {
|
||||||
results,
|
|
||||||
page,
|
|
||||||
total_pages: totalPages,
|
|
||||||
total_results: totalResults
|
|
||||||
}: any = {
|
|
||||||
result: [],
|
result: [],
|
||||||
page: 0,
|
page: 0,
|
||||||
total_pages: 0, // eslint-disable-line @typescript-eslint/camelcase
|
total_pages: 0, // eslint-disable-line @typescript-eslint/camelcase
|
||||||
|
@ -37,7 +37,7 @@ export class Brizo extends Instantiable {
|
|||||||
|
|
||||||
public getComputeEndpoint(
|
public getComputeEndpoint(
|
||||||
pubKey: string,
|
pubKey: string,
|
||||||
serviceId: string,
|
serviceIndex: number,
|
||||||
_notUsed: string,
|
_notUsed: string,
|
||||||
container: string
|
container: string
|
||||||
) {
|
) {
|
||||||
@ -47,14 +47,14 @@ export class Brizo extends Instantiable {
|
|||||||
public async initializeServiceAgreement(
|
public async initializeServiceAgreement(
|
||||||
did: string,
|
did: string,
|
||||||
serviceAgreementId: string,
|
serviceAgreementId: string,
|
||||||
serviceDefinitionId: string,
|
serviceIndex: number,
|
||||||
signature: string,
|
signature: string,
|
||||||
consumerAddress: string
|
consumerAddress: string
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const args = {
|
const args = {
|
||||||
did,
|
did,
|
||||||
serviceAgreementId,
|
serviceAgreementId,
|
||||||
serviceDefinitionId,
|
serviceIndex,
|
||||||
signature,
|
signature,
|
||||||
consumerAddress
|
consumerAddress
|
||||||
}
|
}
|
||||||
@ -94,11 +94,7 @@ export class Brizo extends Instantiable {
|
|||||||
consumeUrl += `&signature=${signature}`
|
consumeUrl += `&signature=${signature}`
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.ocean.utils.fetch.downloadFile(
|
await this.ocean.utils.fetch.downloadFile(consumeUrl, destination, i)
|
||||||
consumeUrl,
|
|
||||||
destination,
|
|
||||||
i
|
|
||||||
)
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.error('Error consuming assets')
|
this.logger.error('Error consuming assets')
|
||||||
this.logger.error(e)
|
this.logger.error(e)
|
||||||
|
25
src/ddo/ComputingProvider.ts
Normal file
25
src/ddo/ComputingProvider.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
export interface Provider {
|
||||||
|
type: string
|
||||||
|
description: string
|
||||||
|
environment: {
|
||||||
|
cluster: {
|
||||||
|
type: string
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
supportedContainers: {
|
||||||
|
image: string
|
||||||
|
tag: string
|
||||||
|
checksum: string
|
||||||
|
}[]
|
||||||
|
supportedServers: {
|
||||||
|
serverId: string
|
||||||
|
serverType: string
|
||||||
|
price: string
|
||||||
|
cpu: string
|
||||||
|
gpu: string
|
||||||
|
memory: string
|
||||||
|
disk: string
|
||||||
|
maxExecutionTime: number
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,4 @@
|
|||||||
import * as Web3 from 'web3'
|
|
||||||
import Web3Provider from '../keeper/Web3Provider'
|
import Web3Provider from '../keeper/Web3Provider'
|
||||||
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'
|
||||||
@ -53,8 +51,7 @@ export class DDO {
|
|||||||
public constructor(ddo: Partial<DDO> = {}) {
|
public constructor(ddo: Partial<DDO> = {}) {
|
||||||
Object.assign(this, ddo, {
|
Object.assign(this, ddo, {
|
||||||
created:
|
created:
|
||||||
(ddo && ddo.created) ||
|
(ddo && ddo.created) || new Date().toISOString().replace(/\.[0-9]{3}/, '')
|
||||||
new Date().toISOString().replace(/\.[0-9]{3}/, '')
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,20 +60,16 @@ export class DDO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a service of a DDO by ID.
|
* Finds a service of a DDO by index.
|
||||||
* @param {string} serviceDefinitionId Service ID.
|
* @param {number} Service index.
|
||||||
* @return {Service} Service.
|
* @return {Service} Service.
|
||||||
*/
|
*/
|
||||||
public findServiceById<T extends ServiceType>(
|
public findServiceById<T extends ServiceType>(index: number): Service<T> {
|
||||||
serviceDefinitionId: string
|
if (isNaN(index)) {
|
||||||
): Service<T> {
|
throw new Error('index is not set')
|
||||||
if (!serviceDefinitionId) {
|
|
||||||
throw new Error('serviceDefinitionId not set')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const service = this.service.find(
|
const service = this.service.find(s => s.index === index)
|
||||||
s => s.serviceDefinitionId === serviceDefinitionId
|
|
||||||
)
|
|
||||||
|
|
||||||
return service as Service<T>
|
return service as Service<T>
|
||||||
}
|
}
|
||||||
@ -86,9 +79,7 @@ export class DDO {
|
|||||||
* @param {string} serviceType Service type.
|
* @param {string} serviceType Service type.
|
||||||
* @return {Service} Service.
|
* @return {Service} Service.
|
||||||
*/
|
*/
|
||||||
public findServiceByType<T extends ServiceType>(
|
public findServiceByType<T extends ServiceType>(serviceType: T): Service<T> {
|
||||||
serviceType: T
|
|
||||||
): Service<T> {
|
|
||||||
if (!serviceType) {
|
if (!serviceType) {
|
||||||
throw new Error('serviceType not set')
|
throw new Error('serviceType not set')
|
||||||
}
|
}
|
||||||
@ -101,8 +92,8 @@ export class DDO {
|
|||||||
* @return {string[]} DDO checksum.
|
* @return {string[]} DDO checksum.
|
||||||
*/
|
*/
|
||||||
public getChecksum(): string {
|
public getChecksum(): string {
|
||||||
const { metadata } = this.findServiceByType('Metadata')
|
const { attributes } = this.findServiceByType('metadata')
|
||||||
const { files, name, author, license } = metadata.base
|
const { files, name, author, license } = attributes.main
|
||||||
|
|
||||||
const values = [
|
const values = [
|
||||||
...(files || []).map(({ checksum }) => checksum).filter(_ => !!_),
|
...(files || []).map(({ checksum }) => checksum).filter(_ => !!_),
|
||||||
@ -119,9 +110,9 @@ export class DDO {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates proof using personal sing.
|
* Generates proof using personal sing.
|
||||||
* @param {Web3} web3 Web3 instance.
|
* @param {Ocean} ocean Ocean instance.
|
||||||
* @param {string} publicKey Public key to be used on personal sign.
|
* @param {string} publicKey Public key to be used on personal sign.
|
||||||
* @param {string} password Password if it's requirted.
|
* @param {string} password Password if it's required.
|
||||||
* @return {Promise<Proof>} Proof object.
|
* @return {Promise<Proof>} Proof object.
|
||||||
*/
|
*/
|
||||||
public async generateProof(
|
public async generateProof(
|
||||||
@ -145,33 +136,21 @@ export class DDO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generated and adds the checksum.
|
|
||||||
*/
|
|
||||||
public addChecksum(): void {
|
|
||||||
const metadataService = this.findServiceByType('Metadata')
|
|
||||||
if (metadataService.metadata.base.checksum) {
|
|
||||||
LoggerInstance.log('Checksum already exists')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
metadataService.metadata.base.checksum = this.getChecksum()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates and adds a proof using personal sing on the DDO.
|
* Generates and adds a proof using personal sing on the DDO.
|
||||||
* @param {Web3} web3 Web3 instance.
|
* @param {Ocean} ocean Ocean instance.
|
||||||
* @param {string} publicKey Public key to be used on personal sign.
|
* @param {string} publicKey Public key to be used on personal sign.
|
||||||
* @param {string} password Password if it's requirted.
|
* @param {string} password Password if it's required.
|
||||||
* @return {Promise<Proof>} Proof object.
|
* @return {Promise<Proof>} Proof object.
|
||||||
*/
|
*/
|
||||||
public async addProof(
|
public async addProof(
|
||||||
web3: Web3,
|
ocean: Ocean,
|
||||||
publicKey: string,
|
publicKey: string,
|
||||||
password?: string
|
password?: string
|
||||||
): Promise<void> {
|
): 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(ocean, publicKey, password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,72 @@
|
|||||||
|
export interface StageRequirements {
|
||||||
|
container: {
|
||||||
|
image: string
|
||||||
|
tag: string
|
||||||
|
checksum: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StageInput {
|
||||||
|
index: number
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StageTransformation {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StageOutput {
|
||||||
|
metadataUrl: string
|
||||||
|
secretStoreUrl: string
|
||||||
|
accessProxyUrl: string
|
||||||
|
metadata: MetaDataMain
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Stage {
|
||||||
|
index: number
|
||||||
|
stageType?: string
|
||||||
|
requirements: StageRequirements
|
||||||
|
input: StageInput
|
||||||
|
transformation: StageTransformation
|
||||||
|
output: StageOutput
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Workflow {
|
||||||
|
stages: Stage[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Algorithm {
|
||||||
|
language: string
|
||||||
|
format?: string
|
||||||
|
version?: string
|
||||||
|
entrypoint: string
|
||||||
|
requirements: {
|
||||||
|
requirement: string
|
||||||
|
version: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServiceDefinition {
|
||||||
|
auth: {
|
||||||
|
type: string
|
||||||
|
user?: string
|
||||||
|
password?: string
|
||||||
|
token?: string
|
||||||
|
}
|
||||||
|
endpoints: {
|
||||||
|
index: number
|
||||||
|
url: string
|
||||||
|
method: string
|
||||||
|
contentTypes: string[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Service {
|
||||||
|
spec?: string
|
||||||
|
specChecksum?: string
|
||||||
|
definition: ServiceDefinition
|
||||||
|
}
|
||||||
|
|
||||||
export interface File {
|
export interface File {
|
||||||
/**
|
/**
|
||||||
* File name.
|
* File name.
|
||||||
@ -17,6 +86,13 @@ export interface File {
|
|||||||
*/
|
*/
|
||||||
index?: number
|
index?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File format, if applicable.
|
||||||
|
* @type {string}
|
||||||
|
* @example "text/csv"
|
||||||
|
*/
|
||||||
|
contentType: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File checksum.
|
* File checksum.
|
||||||
* @type {[type]}
|
* @type {[type]}
|
||||||
@ -33,7 +109,7 @@ export interface File {
|
|||||||
* File content length.
|
* File content length.
|
||||||
* @type {[type]}
|
* @type {[type]}
|
||||||
*/
|
*/
|
||||||
contentLength?: number
|
contentLength?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resource ID (depending on the source).
|
* Resource ID (depending on the source).
|
||||||
@ -54,20 +130,13 @@ export interface File {
|
|||||||
* @example "zip"
|
* @example "zip"
|
||||||
*/
|
*/
|
||||||
compression?: string
|
compression?: string
|
||||||
|
|
||||||
/**
|
|
||||||
* File format, if applicable.
|
|
||||||
* @type {string}
|
|
||||||
* @example "text/csv"
|
|
||||||
*/
|
|
||||||
contentType?: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base attributes of Assets Metadata.
|
* Main attributes of assets metadata.
|
||||||
* @see https://github.com/oceanprotocol/OEPs/tree/master/8#base-attributes
|
* @see https://github.com/oceanprotocol/OEPs/tree/master/8
|
||||||
*/
|
*/
|
||||||
export interface MetaDataBase {
|
export interface MetaDataMain {
|
||||||
/**
|
/**
|
||||||
* Descriptive name of the Asset.
|
* Descriptive name of the Asset.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
@ -83,14 +152,6 @@ export interface MetaDataBase {
|
|||||||
*/
|
*/
|
||||||
type: 'dataset' | 'algorithm' | 'container' | 'workflow' | 'other'
|
type: 'dataset' | 'algorithm' | 'container' | 'workflow' | 'other'
|
||||||
|
|
||||||
/**
|
|
||||||
* Details of what the resource is. For a dataset, this attribute
|
|
||||||
* explains what the data represents and what it can be used for.
|
|
||||||
* @type {string}
|
|
||||||
* @example "Weather information of UK including temperature and humidity"
|
|
||||||
*/
|
|
||||||
description?: string
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The date on which the asset was created by the originator in
|
* The date on which the asset was created by the originator in
|
||||||
* ISO 8601 format, Coordinated Universal Time.
|
* ISO 8601 format, Coordinated Universal Time.
|
||||||
@ -123,6 +184,75 @@ export interface MetaDataBase {
|
|||||||
*/
|
*/
|
||||||
license: string
|
license: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Price of the asset.
|
||||||
|
* @type {string}
|
||||||
|
* @example "1000000000000000000"
|
||||||
|
*/
|
||||||
|
price: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of File objects including the encrypted file urls and some additional information.
|
||||||
|
* @type {File[]}
|
||||||
|
*/
|
||||||
|
files: File[]
|
||||||
|
|
||||||
|
encryptedService?: any
|
||||||
|
|
||||||
|
workflow?: Workflow
|
||||||
|
|
||||||
|
algorithm?: Algorithm
|
||||||
|
|
||||||
|
service?: Service
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curation attributes of Assets Metadata.
|
||||||
|
* @see https://github.com/oceanprotocol/OEPs/tree/master/8
|
||||||
|
*/
|
||||||
|
export interface Curation {
|
||||||
|
/**
|
||||||
|
* Decimal value between 0 and 1. 0 is the default value.
|
||||||
|
* @type {number}
|
||||||
|
* @example 0.93
|
||||||
|
*/
|
||||||
|
rating: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of votes. 0 is the default value.
|
||||||
|
* @type {number}
|
||||||
|
* @example 123
|
||||||
|
*/
|
||||||
|
numVotes: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schema applied to calculate the rating.
|
||||||
|
* @type {string}
|
||||||
|
* @example "Binary Voting"
|
||||||
|
*/
|
||||||
|
schema?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag unsuitable content.
|
||||||
|
* @type {boolean}
|
||||||
|
* @example true
|
||||||
|
*/
|
||||||
|
isListed?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional Information of Assets Metadata.
|
||||||
|
* @see https://github.com/oceanprotocol/OEPs/tree/master/8#additional-information
|
||||||
|
*/
|
||||||
|
export interface AdditionalInformation {
|
||||||
|
/**
|
||||||
|
* Details of what the resource is. For a dataset, this attribute
|
||||||
|
* explains what the data represents and what it can be used for.
|
||||||
|
* @type {string}
|
||||||
|
* @example "Weather information of UK including temperature and humidity"
|
||||||
|
*/
|
||||||
|
description?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The party holding the legal copyright. Empty by default.
|
* The party holding the legal copyright. Empty by default.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
@ -179,60 +309,6 @@ export interface MetaDataBase {
|
|||||||
*/
|
*/
|
||||||
tags?: string[]
|
tags?: string[]
|
||||||
|
|
||||||
/**
|
|
||||||
* Price of the asset.
|
|
||||||
* @type {string}
|
|
||||||
* @example "1000000000000000000"
|
|
||||||
*/
|
|
||||||
price: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of File objects including the encrypted file urls and some additional information.
|
|
||||||
* @type {File[]}
|
|
||||||
*/
|
|
||||||
files: File[]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SHA3 hash of concatenated values: [list of all file checksums] + name + author + license + did
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
checksum?: string
|
|
||||||
|
|
||||||
encryptedFiles?: any
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Curation attributes of Assets Metadata.
|
|
||||||
* @see https://github.com/oceanprotocol/OEPs/tree/master/8#curation-attributes
|
|
||||||
*/
|
|
||||||
export interface Curation {
|
|
||||||
/**
|
|
||||||
* Decimal value between 0 and 1. 0 is the default value.
|
|
||||||
* @type {number}
|
|
||||||
* @example 0.93
|
|
||||||
*/
|
|
||||||
rating: number
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of votes. 0 is the default value.
|
|
||||||
* @type {number}
|
|
||||||
* @example 123
|
|
||||||
*/
|
|
||||||
numVotes: number
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schema applied to calculate the rating.
|
|
||||||
* @type {string}
|
|
||||||
* @example "Binary Voting"
|
|
||||||
*/
|
|
||||||
schema?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Additional Information of Assets Metadata.
|
|
||||||
* @see https://github.com/oceanprotocol/OEPs/tree/master/8#additional-information
|
|
||||||
*/
|
|
||||||
export interface AdditionalInformation {
|
|
||||||
/**
|
/**
|
||||||
* An indication of update latency - i.e. How often are updates expected (seldom,
|
* An indication of update latency - i.e. How often are updates expected (seldom,
|
||||||
* annually, quarterly, etc.), or is the resource static that is never expected
|
* annually, quarterly, etc.), or is the resource static that is never expected
|
||||||
@ -240,28 +316,22 @@ export interface AdditionalInformation {
|
|||||||
* @type {string}
|
* @type {string}
|
||||||
* @example "yearly"
|
* @example "yearly"
|
||||||
*/
|
*/
|
||||||
updateFrequency: string
|
updateFrequency?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A link to machine-readable structured markup (such as ttl/json-ld/rdf)
|
* A link to machine-readable structured markup (such as ttl/json-ld/rdf)
|
||||||
* describing the dataset.
|
* describing the dataset.
|
||||||
* @type {StructuredMarkup[]}
|
* @type {StructuredMarkup[]}
|
||||||
*/
|
*/
|
||||||
structuredMarkup: {
|
structuredMarkup?: {
|
||||||
uri: string
|
uri: string
|
||||||
mediaType: string
|
mediaType: string
|
||||||
}[]
|
}[]
|
||||||
|
|
||||||
/**
|
|
||||||
* Checksum of attributes to be able to compare if there are changes in
|
|
||||||
* the asset that you are purchasing.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
checksum: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MetaData {
|
export interface MetaData {
|
||||||
|
main: MetaDataMain
|
||||||
|
encryptedFiles?: string
|
||||||
additionalInformation?: AdditionalInformation
|
additionalInformation?: AdditionalInformation
|
||||||
base: MetaDataBase
|
|
||||||
curation?: Curation
|
curation?: Curation
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,56 @@
|
|||||||
import { MetaData } from './MetaData'
|
import { MetaData } from './MetaData'
|
||||||
import { ServiceAgreementTemplate } from './ServiceAgreementTemplate'
|
import { ServiceAgreementTemplate } from './ServiceAgreementTemplate'
|
||||||
|
import { Provider } from './ComputingProvider'
|
||||||
|
|
||||||
export type ServiceType =
|
export type ServiceType =
|
||||||
| 'Authorization'
|
| 'authorization'
|
||||||
| 'Metadata'
|
| 'metadata'
|
||||||
| 'Access'
|
| 'access'
|
||||||
| 'Compute'
|
| 'compute'
|
||||||
| 'FitchainCompute'
|
| 'computing'
|
||||||
|
| 'fitchainCompute'
|
||||||
|
|
||||||
export interface ServiceCommon {
|
export interface ServiceCommon {
|
||||||
type: ServiceType
|
type: ServiceType
|
||||||
serviceDefinitionId?: string
|
index: number
|
||||||
serviceEndpoint?: string
|
serviceEndpoint?: string
|
||||||
|
attributes: any & {
|
||||||
|
main: { [key: string]: any }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
attributes: MetaData
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ServiceAccess extends ServiceCommon {
|
export interface ServiceAccess extends ServiceCommon {
|
||||||
type: 'Access'
|
type: 'access'
|
||||||
name?: string
|
|
||||||
description?: string
|
|
||||||
creator?: string
|
|
||||||
templateId?: string
|
templateId?: string
|
||||||
purchaseEndpoint?: string
|
attributes: {
|
||||||
|
main: {
|
||||||
|
creator: string
|
||||||
|
name: string
|
||||||
|
datePublished: string
|
||||||
|
price: string
|
||||||
|
timeout: number
|
||||||
|
}
|
||||||
|
serviceAgreementTemplate?: ServiceAgreementTemplate
|
||||||
|
additionalInformation: {
|
||||||
|
description: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServiceComputing extends ServiceCommon {
|
||||||
|
type: 'computing'
|
||||||
|
templateId?: string
|
||||||
|
provider?: Provider
|
||||||
serviceAgreementTemplate?: ServiceAgreementTemplate
|
serviceAgreementTemplate?: ServiceAgreementTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,13 +60,15 @@ export interface ServiceCompute extends ServiceCommon {
|
|||||||
|
|
||||||
export type Service<
|
export type Service<
|
||||||
T extends ServiceType | 'default' = 'default'
|
T extends ServiceType | 'default' = 'default'
|
||||||
> = T extends 'Authorization'
|
> = T extends 'authorization'
|
||||||
? ServiceAuthorization
|
? ServiceAuthorization
|
||||||
: T extends 'Metadata'
|
: T extends 'metadata'
|
||||||
? ServiceMetadata
|
? ServiceMetadata
|
||||||
: T extends 'Access'
|
: T extends 'computing'
|
||||||
|
? ServiceComputing
|
||||||
|
: T extends 'access'
|
||||||
? ServiceAccess
|
? ServiceAccess
|
||||||
: T extends 'Compute'
|
: T extends 'compute'
|
||||||
? ServiceCompute
|
? ServiceCompute
|
||||||
: T extends 'default'
|
: T extends 'default'
|
||||||
? ServiceCommon
|
? ServiceCommon
|
||||||
|
@ -17,9 +17,7 @@ export class ContractEvent {
|
|||||||
private filter: { [key: string]: any }
|
private filter: { [key: string]: any }
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public subscribe(
|
public subscribe(callback: (events: any[]) => void): ContractEventSubscription {
|
||||||
callback: (events: any[]) => void
|
|
||||||
): ContractEventSubscription {
|
|
||||||
const onEvent = async (blockNumber: number) => {
|
const onEvent = async (blockNumber: number) => {
|
||||||
const events = await this.contract.getEventData(this.eventName, {
|
const events = await this.contract.getEventData(this.eventName, {
|
||||||
filter: this.filter,
|
filter: this.filter,
|
||||||
|
@ -11,20 +11,14 @@ export default class ContractHandler extends Instantiable {
|
|||||||
networkId: number,
|
networkId: number,
|
||||||
contractInstance: Contract
|
contractInstance: Contract
|
||||||
) {
|
) {
|
||||||
ContractHandler.contracts.set(
|
ContractHandler.contracts.set(this.getHash(what, networkId), contractInstance)
|
||||||
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<
|
private static contracts: Map<string, Contract> = new Map<string, Contract>()
|
||||||
string,
|
|
||||||
Contract
|
|
||||||
>()
|
|
||||||
|
|
||||||
private static getHash(what: string, networkId: number): string {
|
private static getHash(what: string, networkId: number): string {
|
||||||
return `${what}/#${networkId}`
|
return `${what}/#${networkId}`
|
||||||
@ -35,10 +29,7 @@ export default class ContractHandler extends Instantiable {
|
|||||||
this.setInstanceConfig(config)
|
this.setInstanceConfig(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
public async get(
|
public async get(what: string, optional: boolean = false): Promise<Contract> {
|
||||||
what: string,
|
|
||||||
optional: boolean = false
|
|
||||||
): Promise<Contract> {
|
|
||||||
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 {
|
||||||
@ -65,14 +56,9 @@ export default class ContractHandler extends Instantiable {
|
|||||||
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(
|
throw new Error(`No code deployed at address ${artifact.address}, sorry.`)
|
||||||
`No code deployed at address ${artifact.address}, sorry.`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
const contract = new this.web3.eth.Contract(
|
const contract = new this.web3.eth.Contract(artifact.abi, artifact.address)
|
||||||
artifact.abi,
|
|
||||||
artifact.address
|
|
||||||
)
|
|
||||||
|
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
'Getting instance of',
|
'Getting instance of',
|
||||||
|
@ -7,11 +7,13 @@ import {
|
|||||||
Condition,
|
Condition,
|
||||||
LockRewardCondition,
|
LockRewardCondition,
|
||||||
EscrowReward,
|
EscrowReward,
|
||||||
AccessSecretStoreCondition
|
AccessSecretStoreCondition,
|
||||||
|
ComputeExecutionCondition
|
||||||
} from './contracts/conditions'
|
} from './contracts/conditions'
|
||||||
import {
|
import {
|
||||||
AgreementTemplate,
|
AgreementTemplate,
|
||||||
EscrowAccessSecretStoreTemplate
|
EscrowAccessSecretStoreTemplate,
|
||||||
|
EscrowComputeExecutionTemplate
|
||||||
} from './contracts/templates'
|
} from './contracts/templates'
|
||||||
import {
|
import {
|
||||||
TemplateStoreManager,
|
TemplateStoreManager,
|
||||||
@ -36,9 +38,7 @@ export class Keeper extends Instantiable {
|
|||||||
* Returns Keeper instance.
|
* Returns Keeper instance.
|
||||||
* @return {Promise<Keeper>}
|
* @return {Promise<Keeper>}
|
||||||
*/
|
*/
|
||||||
public static async getInstance(
|
public static async getInstance(config: InstantiableConfig): Promise<Keeper> {
|
||||||
config: InstantiableConfig
|
|
||||||
): Promise<Keeper> {
|
|
||||||
const keeper = new Keeper()
|
const keeper = new Keeper()
|
||||||
keeper.setInstanceConfig(config)
|
keeper.setInstanceConfig(config)
|
||||||
|
|
||||||
@ -54,21 +54,21 @@ 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(
|
agreementStoreManager: AgreementStoreManager.getInstance(config),
|
||||||
config
|
conditionStoreManager: ConditionStoreManager.getInstance(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(
|
accessSecretStoreCondition: AccessSecretStoreCondition.getInstance(
|
||||||
config
|
config
|
||||||
),
|
),
|
||||||
|
computeExecutionCondition: ComputeExecutionCondition.getInstance(config),
|
||||||
// Templates
|
// Templates
|
||||||
escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate.getInstance(
|
escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate.getInstance(
|
||||||
config
|
config
|
||||||
|
),
|
||||||
|
escrowComputeExecutionTemplate: EscrowComputeExecutionTemplate.getInstance(
|
||||||
|
config
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -97,15 +97,16 @@ 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:
|
accessSecretStoreCondition: keeper.instances.accessSecretStoreCondition,
|
||||||
keeper.instances.accessSecretStoreCondition
|
computeExecutionCondition: keeper.instances.computeExecutionCondition
|
||||||
}
|
}
|
||||||
// Conditions
|
// Conditions
|
||||||
keeper.templates = {
|
keeper.templates = {
|
||||||
escrowAccessSecretStoreTemplate:
|
escrowAccessSecretStoreTemplate:
|
||||||
keeper.instances.escrowAccessSecretStoreTemplate
|
keeper.instances.escrowAccessSecretStoreTemplate,
|
||||||
|
escrowComputeExecutionTemplate:
|
||||||
|
keeper.instances.escrowComputeExecutionTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
keeper.utils = {
|
keeper.utils = {
|
||||||
eventHandler: new EventHandler(config)
|
eventHandler: new EventHandler(config)
|
||||||
@ -163,6 +164,7 @@ export class Keeper extends Instantiable {
|
|||||||
lockRewardCondition: LockRewardCondition
|
lockRewardCondition: LockRewardCondition
|
||||||
escrowReward: EscrowReward
|
escrowReward: EscrowReward
|
||||||
accessSecretStoreCondition: AccessSecretStoreCondition
|
accessSecretStoreCondition: AccessSecretStoreCondition
|
||||||
|
computeExecutionCondition: ComputeExecutionCondition
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,6 +172,7 @@ export class Keeper extends Instantiable {
|
|||||||
*/
|
*/
|
||||||
public templates: {
|
public templates: {
|
||||||
escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate
|
escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate
|
||||||
|
escrowComputeExecutionTemplate: EscrowComputeExecutionTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -227,7 +230,7 @@ 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().then(networkId => {
|
return this.web3.eth.net.getId().then((networkId: number) => {
|
||||||
switch (networkId) {
|
switch (networkId) {
|
||||||
case 1:
|
case 1:
|
||||||
return 'Main'
|
return 'Main'
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
import Config from '../models/Config'
|
import Config from '../models/Config'
|
||||||
|
|
||||||
export default class Web3Provider {
|
export default class Web3Provider {
|
||||||
|
@ -15,7 +15,7 @@ export abstract class ContractBase extends Instantiable {
|
|||||||
return this.contract.options.address
|
return this.contract.options.address
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(contractName, private optional: boolean = false) {
|
constructor(contractName: string, private optional: boolean = false) {
|
||||||
super()
|
super()
|
||||||
this.contractName = contractName
|
this.contractName = contractName
|
||||||
}
|
}
|
||||||
@ -54,10 +54,7 @@ export abstract class ContractBase extends Instantiable {
|
|||||||
protected async init(config: InstantiableConfig) {
|
protected async init(config: InstantiableConfig) {
|
||||||
this.setInstanceConfig(config)
|
this.setInstanceConfig(config)
|
||||||
const contractHandler = new ContractHandler(config)
|
const contractHandler = new ContractHandler(config)
|
||||||
this.contract = await contractHandler.get(
|
this.contract = await contractHandler.get(this.contractName, this.optional)
|
||||||
this.contractName,
|
|
||||||
this.optional
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getFromAddress(from?: string): Promise<string> {
|
protected async getFromAddress(from?: string): Promise<string> {
|
||||||
@ -99,23 +96,19 @@ export abstract class ContractBase extends Instantiable {
|
|||||||
})
|
})
|
||||||
return tx
|
return tx
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const mappedArgs = this.searchMethod(name, args).inputs.map(
|
const mappedArgs = this.searchMethod(name, args).inputs.map((input, i) => {
|
||||||
(input, i) => {
|
return {
|
||||||
return {
|
name: input.name,
|
||||||
name: input.name,
|
value: args[i]
|
||||||
value: args[i]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
this.logger.error('-'.repeat(40))
|
this.logger.error('-'.repeat(40))
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Sending transaction "${name}" on contract "${this.contractName}" failed.`
|
`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(
|
this.logger.error(`Parameters: ${JSON.stringify(mappedArgs, null, 2)}`)
|
||||||
`Parameters: ${JSON.stringify(mappedArgs, null, 2)}`
|
|
||||||
)
|
|
||||||
this.logger.error('-'.repeat(40))
|
this.logger.error('-'.repeat(40))
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
@ -127,9 +120,7 @@ export abstract class ContractBase extends Instantiable {
|
|||||||
from?: string
|
from?: string
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
if (!this.contract.methods[name]) {
|
if (!this.contract.methods[name]) {
|
||||||
throw new Error(
|
throw new Error(`Method ${name} is not part of contract ${this.contractName}`)
|
||||||
`Method ${name} is not part of contract ${this.contractName}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// Logger.log(name)
|
// Logger.log(name)
|
||||||
try {
|
try {
|
||||||
@ -150,11 +141,7 @@ export abstract class ContractBase extends Instantiable {
|
|||||||
`Event ${eventName} is not part of contract ${this.contractName}`
|
`Event ${eventName} is not part of contract ${this.contractName}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return this.ocean.keeper.utils.eventHandler.getEvent(
|
return this.ocean.keeper.utils.eventHandler.getEvent(this, eventName, filter)
|
||||||
this,
|
|
||||||
eventName,
|
|
||||||
filter
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private searchMethod(methodName: string, args: any[] = []) {
|
private searchMethod(methodName: string, args: any[] = []) {
|
||||||
@ -165,8 +152,7 @@ export abstract class ContractBase extends Instantiable {
|
|||||||
}))
|
}))
|
||||||
.filter((method: any) => method.name === methodName)
|
.filter((method: any) => method.name === methodName)
|
||||||
const foundMethod =
|
const foundMethod =
|
||||||
methods.find(({ inputs }) => inputs.length === args.length) ||
|
methods.find(({ inputs }) => inputs.length === args.length) || methods[0]
|
||||||
methods[0]
|
|
||||||
if (!foundMethod) {
|
if (!foundMethod) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Method "${methodName}" is not part of contract "${this.contractName}"`
|
`Method "${methodName}" is not part of contract "${this.contractName}"`
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
|
import { TransactionReceipt } from 'web3-core'
|
||||||
import ContractBase from './ContractBase'
|
import ContractBase from './ContractBase'
|
||||||
import { zeroX, didPrefixed, didZeroX } from '../../utils'
|
import { zeroX, noZeroX, didPrefixed, didZeroX } 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
|
|
||||||
): Promise<DIDRegistry> {
|
|
||||||
const didRegistry: DIDRegistry = new DIDRegistry('DIDRegistry')
|
const didRegistry: DIDRegistry = new DIDRegistry('DIDRegistry')
|
||||||
await didRegistry.init(config)
|
await didRegistry.init(config)
|
||||||
return didRegistry
|
return didRegistry
|
||||||
@ -39,9 +38,11 @@ export default class DIDRegistry extends ContractBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getAttributesByOwner(owner: string): Promise<string[]> {
|
public async getAttributesByOwner(owner: string): Promise<string[]> {
|
||||||
return (await this.getPastEvents('DIDAttributeRegistered', {
|
return (
|
||||||
_owner: zeroX(owner)
|
await this.getPastEvents('DIDAttributeRegistered', {
|
||||||
}))
|
_owner: zeroX(owner)
|
||||||
|
})
|
||||||
|
)
|
||||||
.map(({ returnValues }) => returnValues._did)
|
.map(({ returnValues }) => returnValues._did)
|
||||||
.map(didPrefixed)
|
.map(didPrefixed)
|
||||||
}
|
}
|
||||||
@ -49,15 +50,13 @@ export default class DIDRegistry extends ContractBase {
|
|||||||
public async getAttributesByDid(
|
public async getAttributesByDid(
|
||||||
did: string
|
did: string
|
||||||
): Promise<{ did: string; serviceEndpoint: string; checksum: string }> {
|
): Promise<{ did: string; serviceEndpoint: string; checksum: string }> {
|
||||||
return (await this.getPastEvents('DIDAttributeRegistered', {
|
return (
|
||||||
_did: didZeroX(did)
|
await this.getPastEvents('DIDAttributeRegistered', {
|
||||||
})).map(
|
_did: didZeroX(did)
|
||||||
|
})
|
||||||
|
).map(
|
||||||
({
|
({
|
||||||
returnValues: {
|
returnValues: { _did, _checksum: checksum, _value: serviceEndpoint }
|
||||||
_did,
|
|
||||||
_checksum: checksum,
|
|
||||||
_value: serviceEndpoint
|
|
||||||
}
|
|
||||||
}) => ({
|
}) => ({
|
||||||
did: didPrefixed(_did),
|
did: didPrefixed(_did),
|
||||||
serviceEndpoint,
|
serviceEndpoint,
|
||||||
@ -65,4 +64,27 @@ export default class DIDRegistry extends ContractBase {
|
|||||||
})
|
})
|
||||||
)[0]
|
)[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async grantPermission(did: string, grantee: string, ownerAddress: string) {
|
||||||
|
return this.send('grantPermission', ownerAddress, [didZeroX(did), zeroX(grantee)])
|
||||||
|
}
|
||||||
|
|
||||||
|
public async revokePermission(did: string, grantee: string, ownerAddress: string) {
|
||||||
|
return this.send('revokePermission', ownerAddress, [zeroX(did), zeroX(grantee)])
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getPermission(did: string, grantee: string): Promise<boolean> {
|
||||||
|
return this.call('getPermission', [didZeroX(did), zeroX(grantee)])
|
||||||
|
}
|
||||||
|
|
||||||
|
public async transferDIDOwnership(
|
||||||
|
did: string,
|
||||||
|
newOwnerAddress: string,
|
||||||
|
ownerAddress: string
|
||||||
|
): Promise<TransactionReceipt> {
|
||||||
|
return this.send('transferDIDOwnership', ownerAddress, [
|
||||||
|
didZeroX(did),
|
||||||
|
noZeroX(newOwnerAddress)
|
||||||
|
])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,13 @@ 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
|
|
||||||
): Promise<Dispenser> {
|
|
||||||
const dispenser: Dispenser = new Dispenser('Dispenser', true)
|
const dispenser: Dispenser = new Dispenser('Dispenser', true)
|
||||||
await dispenser.init(config)
|
await dispenser.init(config)
|
||||||
return dispenser
|
return dispenser
|
||||||
}
|
}
|
||||||
|
|
||||||
public async requestTokens(
|
public async requestTokens(amount: number | string, receiverAddress: string) {
|
||||||
amount: number | string,
|
|
||||||
receiverAddress: string
|
|
||||||
) {
|
|
||||||
return this.send('requestTokens', receiverAddress, [String(amount)])
|
return this.send('requestTokens', receiverAddress, [String(amount)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,7 @@ 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
|
|
||||||
): Promise<OceanToken> {
|
|
||||||
const token: OceanToken = new OceanToken('OceanToken')
|
const token: OceanToken = new OceanToken('OceanToken')
|
||||||
await token.init(config)
|
await token.init(config)
|
||||||
return token
|
return token
|
||||||
|
@ -17,17 +17,8 @@ export class AccessSecretStoreCondition extends Condition {
|
|||||||
return super.hashValues(didZeroX(did), zeroX(grantee))
|
return super.hashValues(didZeroX(did), zeroX(grantee))
|
||||||
}
|
}
|
||||||
|
|
||||||
public fulfill(
|
public fulfill(agreementId: string, did: string, grantee: string, from?: string) {
|
||||||
agreementId: string,
|
return super.fulfill(agreementId, [didZeroX(did), grantee].map(zeroX), from)
|
||||||
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) {
|
||||||
@ -41,9 +32,11 @@ export class AccessSecretStoreCondition extends Condition {
|
|||||||
public async getGrantedDidByConsumer(
|
public async getGrantedDidByConsumer(
|
||||||
consumer: string
|
consumer: string
|
||||||
): Promise<{ did: string; agreementId: string }[]> {
|
): Promise<{ did: string; agreementId: string }[]> {
|
||||||
return (await this.getPastEvents('Fulfilled', {
|
return (
|
||||||
_grantee: zeroX(consumer)
|
await this.getPastEvents('Fulfilled', {
|
||||||
})).map(({ returnValues }) => ({
|
_grantee: zeroX(consumer)
|
||||||
|
})
|
||||||
|
).map(({ returnValues }) => ({
|
||||||
did: didPrefixed(returnValues._documentId),
|
did: didPrefixed(returnValues._documentId),
|
||||||
agreementId: zeroX(returnValues._agreementId)
|
agreementId: zeroX(returnValues._agreementId)
|
||||||
}))
|
}))
|
||||||
|
40
src/keeper/contracts/conditions/ComputeExecutionCondition.ts
Normal file
40
src/keeper/contracts/conditions/ComputeExecutionCondition.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { Condition } from './Condition.abstract'
|
||||||
|
import { zeroX, didZeroX, didPrefixed } from '../../../utils'
|
||||||
|
import { InstantiableConfig } from '../../../Instantiable.abstract'
|
||||||
|
|
||||||
|
export class ComputeExecutionCondition extends Condition {
|
||||||
|
public static async getInstance(
|
||||||
|
config: InstantiableConfig
|
||||||
|
): Promise<ComputeExecutionCondition> {
|
||||||
|
return Condition.getInstance(
|
||||||
|
config,
|
||||||
|
'ComputeExecutionCondition',
|
||||||
|
ComputeExecutionCondition
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public hashValues(did: string, computeConsumer: string) {
|
||||||
|
return super.hashValues(didZeroX(did), zeroX(computeConsumer))
|
||||||
|
}
|
||||||
|
|
||||||
|
public fulfill(
|
||||||
|
agreementId: string,
|
||||||
|
did: string,
|
||||||
|
computeConsumer: string,
|
||||||
|
from?: string
|
||||||
|
) {
|
||||||
|
return super.fulfill(
|
||||||
|
agreementId,
|
||||||
|
[didZeroX(did), computeConsumer].map(zeroX),
|
||||||
|
from
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public wasComputeTriggered(did: string, computeConsumer: string, from?: string) {
|
||||||
|
return this.call<boolean>(
|
||||||
|
'wasComputeTriggered',
|
||||||
|
[didZeroX(did), computeConsumer].map(zeroX),
|
||||||
|
from
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,7 @@ 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
|
|
||||||
): Promise<EscrowReward> {
|
|
||||||
return Condition.getInstance(config, 'EscrowReward', EscrowReward)
|
return Condition.getInstance(config, 'EscrowReward', EscrowReward)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,12 +31,7 @@ export class EscrowReward extends Condition {
|
|||||||
) {
|
) {
|
||||||
return super.fulfill(
|
return super.fulfill(
|
||||||
agreementId,
|
agreementId,
|
||||||
[
|
[amount, ...[receiver, sender, lockCondition, releaseCondition].map(zeroX)],
|
||||||
amount,
|
|
||||||
...[receiver, sender, lockCondition, releaseCondition].map(
|
|
||||||
zeroX
|
|
||||||
)
|
|
||||||
],
|
|
||||||
from
|
from
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,7 @@ export class LockRewardCondition extends Condition {
|
|||||||
public static async getInstance(
|
public static async getInstance(
|
||||||
config: InstantiableConfig
|
config: InstantiableConfig
|
||||||
): Promise<LockRewardCondition> {
|
): Promise<LockRewardCondition> {
|
||||||
return Condition.getInstance(
|
return Condition.getInstance(config, 'LockRewardCondition', LockRewardCondition)
|
||||||
config,
|
|
||||||
'LockRewardCondition',
|
|
||||||
LockRewardCondition
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public hashValues(rewardAddress: string, amount: number | string) {
|
public hashValues(rewardAddress: string, amount: number | string) {
|
||||||
@ -23,10 +19,6 @@ export class LockRewardCondition extends Condition {
|
|||||||
amount: number | string,
|
amount: number | string,
|
||||||
from?: string
|
from?: string
|
||||||
) {
|
) {
|
||||||
return super.fulfill(
|
return super.fulfill(agreementId, [zeroX(rewardAddress), String(amount)], from)
|
||||||
agreementId,
|
|
||||||
[zeroX(rewardAddress), String(amount)],
|
|
||||||
from
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,3 +2,4 @@ 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'
|
||||||
|
export { ComputeExecutionCondition } from './ComputeExecutionCondition'
|
||||||
|
@ -31,11 +31,7 @@ export class TemplateStoreManager extends ContractBase {
|
|||||||
return this.call('owner', [])
|
return this.call('owner', [])
|
||||||
}
|
}
|
||||||
|
|
||||||
public async proposeTemplate(
|
public async proposeTemplate(address: string, from?: string, ignoreExists?: boolean) {
|
||||||
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.`)
|
||||||
@ -54,9 +50,7 @@ export class TemplateStoreManager extends ContractBase {
|
|||||||
) {
|
) {
|
||||||
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(
|
this.logger.warn(`Template "${address}" is not in "proposed" state.`)
|
||||||
`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.`)
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,7 @@ export abstract class AgreementTemplate extends ContractBase {
|
|||||||
conditionName: string,
|
conditionName: string,
|
||||||
templateClass: any
|
templateClass: any
|
||||||
): Promise<AgreementTemplate & any> {
|
): Promise<AgreementTemplate & any> {
|
||||||
const condition: AgreementTemplate = new (templateClass as any)(
|
const condition: AgreementTemplate = new (templateClass as any)(conditionName)
|
||||||
conditionName
|
|
||||||
)
|
|
||||||
await condition.init(config)
|
await condition.init(config)
|
||||||
return condition
|
return condition
|
||||||
}
|
}
|
||||||
@ -114,9 +112,7 @@ export abstract class AgreementTemplate extends ContractBase {
|
|||||||
from?: string
|
from?: string
|
||||||
): Promise<boolean>
|
): Promise<boolean>
|
||||||
|
|
||||||
public abstract async getServiceAgreementTemplate(): Promise<
|
public abstract async getServiceAgreementTemplate(): Promise<ServiceAgreementTemplate>
|
||||||
ServiceAgreementTemplate
|
|
||||||
>
|
|
||||||
|
|
||||||
public async getServiceAgreementTemplateConditions() {
|
public async getServiceAgreementTemplateConditions() {
|
||||||
const serviceAgreementTemplate = await this.getServiceAgreementTemplate()
|
const serviceAgreementTemplate = await this.getServiceAgreementTemplate()
|
||||||
@ -165,15 +161,17 @@ export abstract class AgreementTemplate extends ContractBase {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const statesPromises = Object.keys(dependencies).map(async (ref, i) => {
|
const statesPromises = Object.keys(dependencies).map(async (ref, i) => {
|
||||||
const {
|
const { contractName } = await this.getServiceAgreementTemplateConditionByRef(
|
||||||
contractName
|
ref
|
||||||
} = await this.getServiceAgreementTemplateConditionByRef(ref)
|
)
|
||||||
return {
|
return {
|
||||||
ref,
|
ref,
|
||||||
contractName,
|
contractName,
|
||||||
state: (await conditionStore.getCondition(
|
state: (
|
||||||
conditionIdByConddition[contractName]
|
await conditionStore.getCondition(
|
||||||
)).state
|
conditionIdByConddition[contractName]
|
||||||
|
)
|
||||||
|
).state
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const states = await Promise.all(statesPromises)
|
const states = await Promise.all(statesPromises)
|
||||||
@ -181,9 +179,7 @@ export abstract class AgreementTemplate extends ContractBase {
|
|||||||
return states.reduce((acc, { contractName, ref, state }) => {
|
return states.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 {
|
return {
|
||||||
...acc,
|
...acc,
|
||||||
[ref]: {
|
[ref]: {
|
||||||
@ -217,11 +213,7 @@ export abstract class AgreementTemplate extends ContractBase {
|
|||||||
this.logger.bypass('-'.repeat(20))
|
this.logger.bypass('-'.repeat(20))
|
||||||
}
|
}
|
||||||
this.logger.bypass(`${condition} (${contractName})`)
|
this.logger.bypass(`${condition} (${contractName})`)
|
||||||
this.logger.bypass(
|
this.logger.bypass(' Status:', state, `(${conditionStateNames[state]})`)
|
||||||
' Status:',
|
|
||||||
state,
|
|
||||||
`(${conditionStateNames[state]})`
|
|
||||||
)
|
|
||||||
if (blocked) {
|
if (blocked) {
|
||||||
this.logger.bypass(' Blocked by:', blockedBy)
|
this.logger.bypass(' Blocked by:', blockedBy)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
import { AgreementTemplate } from './AgreementTemplate.abstract'
|
||||||
|
import { DDO } from '../../../ddo/DDO'
|
||||||
|
import { generateId, zeroX } from '../../../utils'
|
||||||
|
import { InstantiableConfig } from '../../../Instantiable.abstract'
|
||||||
|
|
||||||
|
// import { EscrowComputeExecutionTemplateServiceAgreementTemplate } from './EscrowComputeExecutionTemplate.serviceAgreementTemplate'
|
||||||
|
|
||||||
|
export abstract class BaseEscrowTemplate extends AgreementTemplate {
|
||||||
|
/**
|
||||||
|
* Create a agreement using EscrowComputeExecutionTemplate.
|
||||||
|
* @param {string} agreementId Generated agreement ID.
|
||||||
|
* @param {string} did Asset DID.
|
||||||
|
* @param {string[]} conditionIds List of conditions IDs.
|
||||||
|
* @param {number[]} timeLocks Timelocks.
|
||||||
|
* @param {number[]} timeOuts Timeouts.
|
||||||
|
* @param {string} accessConsumer Consumer address.
|
||||||
|
* @param {string} from Action sender.
|
||||||
|
* @param {any} Transaction receipt.
|
||||||
|
*/
|
||||||
|
public createAgreement(
|
||||||
|
agreementId: string,
|
||||||
|
did: string,
|
||||||
|
conditionIds: string[],
|
||||||
|
timeLocks: number[],
|
||||||
|
timeOuts: number[],
|
||||||
|
accessConsumer: string,
|
||||||
|
from?: string
|
||||||
|
) {
|
||||||
|
return super.createAgreement(
|
||||||
|
agreementId,
|
||||||
|
did,
|
||||||
|
conditionIds,
|
||||||
|
timeLocks,
|
||||||
|
timeOuts,
|
||||||
|
[accessConsumer],
|
||||||
|
from
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getAgreementData(agreementId: string) {
|
||||||
|
return this.call<any>('getAgreementData', [zeroX(agreementId)])
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,12 @@
|
|||||||
import { AgreementTemplate } from './AgreementTemplate.abstract'
|
import { AgreementTemplate } from './AgreementTemplate.abstract'
|
||||||
|
import { BaseEscrowTemplate } from './BaseEscrowTemplate.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 BaseEscrowTemplate {
|
||||||
public static async getInstance(
|
public static async getInstance(
|
||||||
config: InstantiableConfig
|
config: InstantiableConfig
|
||||||
): Promise<EscrowAccessSecretStoreTemplate> {
|
): Promise<EscrowAccessSecretStoreTemplate> {
|
||||||
@ -20,37 +21,6 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
|
|||||||
return escrowAccessSecretStoreTemplateServiceAgreementTemplate
|
return escrowAccessSecretStoreTemplateServiceAgreementTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a agreement using EscrowAccessSecretStoreTemplate.
|
|
||||||
* @param {string} agreementId Generated agreement ID.
|
|
||||||
* @param {string} did Asset DID.
|
|
||||||
* @param {string[]} conditionIds List of conditions IDs.
|
|
||||||
* @param {number[]} timeLocks Timelocks.
|
|
||||||
* @param {number[]} timeOuts Timeouts.
|
|
||||||
* @param {string} accessConsumer Consumer address.
|
|
||||||
* @param {string} from Action sender.
|
|
||||||
* @param {any} Transaction receipt.
|
|
||||||
*/
|
|
||||||
public createAgreement(
|
|
||||||
agreementId: string,
|
|
||||||
did: string,
|
|
||||||
conditionIds: string[],
|
|
||||||
timeLocks: number[],
|
|
||||||
timeOuts: number[],
|
|
||||||
accessConsumer: string,
|
|
||||||
from?: string
|
|
||||||
) {
|
|
||||||
return super.createAgreement(
|
|
||||||
agreementId,
|
|
||||||
did,
|
|
||||||
conditionIds,
|
|
||||||
timeLocks,
|
|
||||||
timeOuts,
|
|
||||||
[accessConsumer],
|
|
||||||
from
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async createAgreementFromDDO(
|
public async createAgreementFromDDO(
|
||||||
agreementId: string,
|
agreementId: string,
|
||||||
ddo: DDO,
|
ddo: DDO,
|
||||||
@ -59,7 +29,7 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
|
|||||||
) {
|
) {
|
||||||
return !!(await this.createFullAgreement(
|
return !!(await this.createFullAgreement(
|
||||||
ddo.shortId(),
|
ddo.shortId(),
|
||||||
ddo.findServiceByType('Metadata').metadata.base.price,
|
ddo.findServiceByType('metadata').attributes.main.price,
|
||||||
consumer,
|
consumer,
|
||||||
from,
|
from,
|
||||||
agreementId
|
agreementId
|
||||||
@ -79,14 +49,10 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
|
|||||||
} = await this.createFullAgreementData(
|
} = await this.createFullAgreementData(
|
||||||
agreementId,
|
agreementId,
|
||||||
ddo.shortId(),
|
ddo.shortId(),
|
||||||
ddo.findServiceByType('Metadata').metadata.base.price,
|
ddo.findServiceByType('metadata').attributes.main.price,
|
||||||
consumer
|
consumer
|
||||||
)
|
)
|
||||||
return [
|
return [accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId]
|
||||||
accessSecretStoreConditionId,
|
|
||||||
lockRewardConditionId,
|
|
||||||
escrowRewardId
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,21 +73,12 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
|
|||||||
accessSecretStoreConditionId,
|
accessSecretStoreConditionId,
|
||||||
lockRewardConditionId,
|
lockRewardConditionId,
|
||||||
escrowRewardId
|
escrowRewardId
|
||||||
} = await this.createFullAgreementData(
|
} = await this.createFullAgreementData(agreementId, did, amount, consumer)
|
||||||
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,
|
||||||
@ -172,8 +129,4 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
|
|||||||
escrowRewardId
|
escrowRewardId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAgreementData(agreementId: string) {
|
|
||||||
return this.call<any>('getAgreementData', [zeroX(agreementId)])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,142 @@
|
|||||||
|
import { ServiceAgreementTemplate } from '../../../ddo/ServiceAgreementTemplate'
|
||||||
|
|
||||||
|
export const escrowComputeExecutionTemplateServiceAgreementTemplate: ServiceAgreementTemplate = {
|
||||||
|
contractName: 'EscrowComputeExecutionTemplate',
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
name: 'AgreementCreated',
|
||||||
|
actorType: 'consumer',
|
||||||
|
handler: {
|
||||||
|
moduleName: 'serviceExecutionTemplate',
|
||||||
|
functionName: 'fulfillLockRewardCondition',
|
||||||
|
version: '0.1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fulfillmentOrder: [
|
||||||
|
'lockReward.fulfill',
|
||||||
|
'serviceExecution.fulfill',
|
||||||
|
'escrowReward.fulfill'
|
||||||
|
],
|
||||||
|
conditionDependency: {
|
||||||
|
lockReward: [],
|
||||||
|
serviceExecution: [],
|
||||||
|
escrowReward: ['lockReward', 'serviceExecution']
|
||||||
|
},
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
name: 'lockReward',
|
||||||
|
timelock: 0,
|
||||||
|
timeout: 0,
|
||||||
|
contractName: 'LockRewardCondition',
|
||||||
|
functionName: 'fulfill',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: '_rewardAddress',
|
||||||
|
type: 'address',
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_amount',
|
||||||
|
type: 'uint256',
|
||||||
|
value: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
name: 'Fulfilled',
|
||||||
|
actorType: 'publisher',
|
||||||
|
handler: {
|
||||||
|
moduleName: 'lockRewardCondition',
|
||||||
|
functionName: 'fulfillServiceExecutionCondition',
|
||||||
|
version: '0.1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'serviceExecution',
|
||||||
|
timelock: 0,
|
||||||
|
timeout: 0,
|
||||||
|
contractName: 'ComputeExecutionCondition',
|
||||||
|
functionName: 'fulfill',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: '_documentId',
|
||||||
|
type: 'bytes32',
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_grantee',
|
||||||
|
type: 'address',
|
||||||
|
value: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
name: 'Fulfilled',
|
||||||
|
actorType: 'publisher',
|
||||||
|
handler: {
|
||||||
|
moduleName: 'serviceExecution',
|
||||||
|
functionName: 'fulfillServiceExecutionCondition',
|
||||||
|
version: '0.1'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TimedOut',
|
||||||
|
actorType: 'consumer',
|
||||||
|
handler: {
|
||||||
|
moduleName: 'serviceExec',
|
||||||
|
functionName: 'fulfillServiceExecutionCondition',
|
||||||
|
version: '0.1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'escrowReward',
|
||||||
|
timelock: 0,
|
||||||
|
timeout: 0,
|
||||||
|
contractName: 'EscrowReward',
|
||||||
|
functionName: 'fulfill',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: '_amount',
|
||||||
|
type: 'uint256',
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_receiver',
|
||||||
|
type: 'address',
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_sender',
|
||||||
|
type: 'address',
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_lockCondition',
|
||||||
|
type: 'bytes32',
|
||||||
|
value: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_releaseCondition',
|
||||||
|
type: 'bytes32',
|
||||||
|
value: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
name: 'Fulfilled',
|
||||||
|
actorType: 'publisher',
|
||||||
|
handler: {
|
||||||
|
moduleName: 'escrowRewardCondition',
|
||||||
|
functionName: 'verifyRewardTokens',
|
||||||
|
version: '0.1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
132
src/keeper/contracts/templates/EscrowComputeExecutionTemplate.ts
Normal file
132
src/keeper/contracts/templates/EscrowComputeExecutionTemplate.ts
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
import { AgreementTemplate } from './AgreementTemplate.abstract'
|
||||||
|
import { BaseEscrowTemplate } from './BaseEscrowTemplate.abstract'
|
||||||
|
import { DDO } from '../../../ddo/DDO'
|
||||||
|
import { generateId, zeroX } from '../../../utils'
|
||||||
|
import { InstantiableConfig } from '../../../Instantiable.abstract'
|
||||||
|
|
||||||
|
import { escrowComputeExecutionTemplateServiceAgreementTemplate } from './EscrowComputeExecutionTemplate.serviceAgreementTemplate'
|
||||||
|
|
||||||
|
export class EscrowComputeExecutionTemplate extends BaseEscrowTemplate {
|
||||||
|
public static async getInstance(
|
||||||
|
config: InstantiableConfig
|
||||||
|
): Promise<EscrowComputeExecutionTemplate> {
|
||||||
|
return AgreementTemplate.getInstance(
|
||||||
|
config,
|
||||||
|
'EscrowComputeExecutionTemplate',
|
||||||
|
EscrowComputeExecutionTemplate
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getServiceAgreementTemplate() {
|
||||||
|
return escrowComputeExecutionTemplateServiceAgreementTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
public async createAgreementFromDDO(
|
||||||
|
agreementId: string,
|
||||||
|
ddo: DDO,
|
||||||
|
consumer: string,
|
||||||
|
from?: string
|
||||||
|
) {
|
||||||
|
return !!(await this.createFullAgreement(
|
||||||
|
ddo.shortId(),
|
||||||
|
ddo.findServiceByType('metadata').attributes.main.price,
|
||||||
|
consumer,
|
||||||
|
from,
|
||||||
|
agreementId
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getAgreementIdsFromDDO(
|
||||||
|
agreementId: string,
|
||||||
|
ddo: DDO,
|
||||||
|
consumer: string,
|
||||||
|
from?: string
|
||||||
|
) {
|
||||||
|
const {
|
||||||
|
computeExecutionConditionId,
|
||||||
|
lockRewardConditionId,
|
||||||
|
escrowRewardId
|
||||||
|
} = await this.createFullAgreementData(
|
||||||
|
agreementId,
|
||||||
|
ddo.shortId(),
|
||||||
|
ddo.findServiceByType('metadata').attributes.main.price,
|
||||||
|
consumer
|
||||||
|
)
|
||||||
|
return [computeExecutionConditionId, lockRewardConditionId, escrowRewardId]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a agreement using EscrowAccess____SecretStoreTemplate using only the most important information.
|
||||||
|
* @param {string} did Asset DID.
|
||||||
|
* @param {number} amount Asset price.
|
||||||
|
* @param {string} from Consumer address.
|
||||||
|
* @return {Promise<string>} Agreement ID.
|
||||||
|
*/
|
||||||
|
public async createFullAgreement(
|
||||||
|
did: string,
|
||||||
|
amount: number | string,
|
||||||
|
consumer: string,
|
||||||
|
from?: string,
|
||||||
|
agreementId: string = generateId()
|
||||||
|
): Promise<string> {
|
||||||
|
const {
|
||||||
|
computeExecutionConditionId,
|
||||||
|
lockRewardConditionId,
|
||||||
|
escrowRewardId
|
||||||
|
} = await this.createFullAgreementData(agreementId, did, amount, consumer)
|
||||||
|
|
||||||
|
await this.createAgreement(
|
||||||
|
agreementId,
|
||||||
|
did,
|
||||||
|
[computeExecutionConditionId, lockRewardConditionId, escrowRewardId],
|
||||||
|
[0, 0, 0],
|
||||||
|
[0, 0, 0],
|
||||||
|
consumer,
|
||||||
|
from
|
||||||
|
)
|
||||||
|
|
||||||
|
return zeroX(agreementId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createFullAgreementData(
|
||||||
|
agreementId: string,
|
||||||
|
did: string,
|
||||||
|
amount: number | string,
|
||||||
|
consumer: string
|
||||||
|
) {
|
||||||
|
const { didRegistry, conditions } = this.ocean.keeper
|
||||||
|
|
||||||
|
const {
|
||||||
|
computeExecutionCondition,
|
||||||
|
lockRewardCondition,
|
||||||
|
escrowReward
|
||||||
|
} = conditions
|
||||||
|
|
||||||
|
const publisher = await didRegistry.getDIDOwner(did)
|
||||||
|
|
||||||
|
const lockRewardConditionId = await lockRewardCondition.generateIdHash(
|
||||||
|
agreementId,
|
||||||
|
await escrowReward.getAddress(),
|
||||||
|
amount
|
||||||
|
)
|
||||||
|
const computeExecutionConditionId = await computeExecutionCondition.generateIdHash(
|
||||||
|
agreementId,
|
||||||
|
did,
|
||||||
|
consumer
|
||||||
|
)
|
||||||
|
const escrowRewardId = await escrowReward.generateIdHash(
|
||||||
|
agreementId,
|
||||||
|
String(amount),
|
||||||
|
publisher,
|
||||||
|
consumer,
|
||||||
|
lockRewardConditionId,
|
||||||
|
computeExecutionConditionId
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
lockRewardConditionId,
|
||||||
|
computeExecutionConditionId,
|
||||||
|
escrowRewardId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
export * from './AgreementTemplate.abstract'
|
export * from './AgreementTemplate.abstract'
|
||||||
export {
|
export { BaseEscrowTemplate } from './BaseEscrowTemplate.abstract'
|
||||||
EscrowAccessSecretStoreTemplate
|
export { EscrowAccessSecretStoreTemplate } from './EscrowAccessSecretStoreTemplate'
|
||||||
} from './EscrowAccessSecretStoreTemplate'
|
export { EscrowComputeExecutionTemplate } from './EscrowComputeExecutionTemplate'
|
||||||
|
@ -46,9 +46,7 @@ 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(
|
instance.secretStore = await OceanSecretStore.getInstance(instanceConfig)
|
||||||
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)
|
||||||
|
|
||||||
|
@ -10,9 +10,7 @@ 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(
|
public static async getInstance(config: InstantiableConfig): Promise<OceanAccounts> {
|
||||||
config: InstantiableConfig
|
|
||||||
): Promise<OceanAccounts> {
|
|
||||||
const instance = new OceanAccounts()
|
const instance = new OceanAccounts()
|
||||||
instance.setInstanceConfig(config)
|
instance.setInstanceConfig(config)
|
||||||
|
|
||||||
@ -43,15 +41,12 @@ export class OceanAccounts extends Instantiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request tokens for a account.
|
* Request tokens for an account.
|
||||||
* @param {Account} account Account instance.
|
* @param {Account} account Account instance.
|
||||||
* @param {number} amount Token amount.
|
* @param {number} amount Token amount.
|
||||||
* @return {Promise<boolean>} Success.
|
* @return {Promise<boolean>} Success.
|
||||||
*/
|
*/
|
||||||
public async requestTokens(
|
public async requestTokens(account: Account, amount: number): Promise<boolean> {
|
||||||
account: Account,
|
|
||||||
amount: number
|
|
||||||
): Promise<boolean> {
|
|
||||||
try {
|
try {
|
||||||
await account.requestTokens(amount)
|
await account.requestTokens(amount)
|
||||||
return true
|
return true
|
||||||
|
@ -26,9 +26,7 @@ export class OceanAgreements extends Instantiable {
|
|||||||
): Promise<OceanAgreements> {
|
): Promise<OceanAgreements> {
|
||||||
const instance = new OceanAgreements()
|
const instance = new OceanAgreements()
|
||||||
instance.setInstanceConfig(config)
|
instance.setInstanceConfig(config)
|
||||||
instance.conditions = await OceanAgreementsConditions.getInstance(
|
instance.conditions = await OceanAgreementsConditions.getInstance(config)
|
||||||
config
|
|
||||||
)
|
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
@ -42,33 +40,28 @@ export class OceanAgreements extends Instantiable {
|
|||||||
/**
|
/**
|
||||||
* Creates a consumer signature for the specified asset service.
|
* Creates a consumer signature for the specified asset service.
|
||||||
* @param {string} did Decentralized ID.
|
* @param {string} did Decentralized ID.
|
||||||
* @param {string} serviceDefinitionId Service definition ID.
|
* @param {number} index Service index.
|
||||||
* @param {Account} consumer Consumer account.
|
* @param {Account} consumer Consumer account.
|
||||||
* @return {Promise<AgreementPrepareResult>} Agreement ID and signaturee.
|
* @return {Promise<AgreementPrepareResult>} Agreement ID and signaturee.
|
||||||
*/
|
*/
|
||||||
public async prepare(
|
public async prepare(
|
||||||
did: string,
|
did: string,
|
||||||
serviceDefinitionId: string,
|
index: number,
|
||||||
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')
|
const templateName = ddo.findServiceByType('access').attributes
|
||||||
.serviceAgreementTemplate.contractName
|
.serviceAgreementTemplate.contractName
|
||||||
const agreementConditionsIds = await this.ocean.keeper
|
const agreementConditionsIds = await this.ocean.keeper
|
||||||
.getTemplateByName(templateName)
|
.getTemplateByName(templateName)
|
||||||
.getAgreementIdsFromDDO(
|
.getAgreementIdsFromDDO(agreementId, ddo, consumer.getId(), consumer.getId())
|
||||||
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,
|
index,
|
||||||
agreementId,
|
agreementId,
|
||||||
agreementConditionsIds,
|
agreementConditionsIds,
|
||||||
consumer
|
consumer
|
||||||
@ -80,29 +73,27 @@ export class OceanAgreements extends Instantiable {
|
|||||||
/**
|
/**
|
||||||
* Submit a service agreement to the publisher to create the agreement on-chain.
|
* Submit a service agreement to the publisher to create the agreement on-chain.
|
||||||
* @param {string} did Decentralized ID.
|
* @param {string} did Decentralized ID.
|
||||||
* @param {string} serviceDefinitionId Service definition ID.
|
* @param {number} index Service index.
|
||||||
* @param {Account} consumer Consumer account.
|
* @param {Account} consumer Consumer account.
|
||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async send(
|
public async send(
|
||||||
did: string,
|
did: string,
|
||||||
agreementId: string,
|
agreementId: string,
|
||||||
serviceDefinitionId: string,
|
index: number,
|
||||||
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.initializeServiceAgreement(
|
||||||
didPrefixed(did),
|
didPrefixed(did),
|
||||||
zeroX(agreementId),
|
zeroX(agreementId),
|
||||||
serviceDefinitionId,
|
index,
|
||||||
zeroX(signature),
|
zeroX(signature),
|
||||||
consumer.getId()
|
consumer.getId()
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!result.ok) {
|
if (!result.ok) {
|
||||||
throw new Error(
|
throw new Error('Error on initialize agreement: ' + (await result.text()))
|
||||||
'Error on initialize agreement: ' + (await result.text())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +103,7 @@ export class OceanAgreements extends Instantiable {
|
|||||||
* in this method before submitting on-chain.
|
* in this method before submitting on-chain.
|
||||||
* @param {string} did Decentralized ID.
|
* @param {string} did Decentralized ID.
|
||||||
* @param {string} agreementId Service agreement ID.
|
* @param {string} agreementId Service agreement ID.
|
||||||
* @param {string} serviceDefinitionId Service definition ID.
|
* @param {number} index Service index.
|
||||||
* @param {string} signature Service agreement signature.
|
* @param {string} signature Service agreement signature.
|
||||||
* @param {Account} consumer Consumer account.
|
* @param {Account} consumer Consumer account.
|
||||||
* @param {Account} publisher Publisher account.
|
* @param {Account} publisher Publisher account.
|
||||||
@ -121,7 +112,7 @@ export class OceanAgreements extends Instantiable {
|
|||||||
public async create(
|
public async create(
|
||||||
did: string,
|
did: string,
|
||||||
agreementId: string,
|
agreementId: string,
|
||||||
serviceDefinitionId: string,
|
index: number,
|
||||||
signature: string,
|
signature: string,
|
||||||
consumer: Account,
|
consumer: Account,
|
||||||
publisher: Account
|
publisher: Account
|
||||||
@ -129,25 +120,18 @@ export class OceanAgreements extends Instantiable {
|
|||||||
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)
|
const templateName = ddo.findServiceById<'access'>(index).attributes
|
||||||
.serviceAgreementTemplate.contractName
|
.serviceAgreementTemplate.contractName
|
||||||
await this.ocean.keeper
|
await this.ocean.keeper
|
||||||
.getTemplateByName(templateName)
|
.getTemplateByName(templateName)
|
||||||
.createAgreementFromDDO(
|
.createAgreementFromDDO(agreementId, ddo, consumer.getId(), publisher.getId())
|
||||||
agreementId,
|
|
||||||
ddo,
|
|
||||||
consumer.getId(),
|
|
||||||
publisher.getId()
|
|
||||||
)
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the status of a service agreement.
|
* Get the status of a service agreement.
|
||||||
* @param {string} did Decentralized ID.
|
|
||||||
* @param {string} agreementId Service agreement ID.
|
* @param {string} agreementId Service agreement ID.
|
||||||
* @param {string} serviceDefinitionId Service definition ID.
|
|
||||||
* @param {boolean} extended Returns a complete status with dependencies.
|
* @param {boolean} extended Returns a complete status with dependencies.
|
||||||
* @return {Promise<any>}
|
* @return {Promise<any>}
|
||||||
*/
|
*/
|
||||||
@ -162,9 +146,7 @@ export class OceanAgreements extends Instantiable {
|
|||||||
): Promise<AgreementConditionsStatus>
|
): Promise<AgreementConditionsStatus>
|
||||||
|
|
||||||
public async status(agreementId: string, extended: boolean = false) {
|
public async status(agreementId: string, extended: boolean = false) {
|
||||||
const {
|
const { templateId } = await this.ocean.keeper.agreementStoreManager.getAgreement(
|
||||||
templateId
|
|
||||||
} = await this.ocean.keeper.agreementStoreManager.getAgreement(
|
|
||||||
agreementId
|
agreementId
|
||||||
)
|
)
|
||||||
const fullStatus = await this.ocean.keeper
|
const fullStatus = await this.ocean.keeper
|
||||||
|
@ -30,10 +30,7 @@ export class OceanAgreementsConditions extends Instantiable {
|
|||||||
amount: number | string,
|
amount: number | string,
|
||||||
from?: Account
|
from?: Account
|
||||||
) {
|
) {
|
||||||
const {
|
const { lockRewardCondition, escrowReward } = this.ocean.keeper.conditions
|
||||||
lockRewardCondition,
|
|
||||||
escrowReward
|
|
||||||
} = this.ocean.keeper.conditions
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.ocean.keeper.token.approve(
|
await this.ocean.keeper.token.approve(
|
||||||
@ -83,6 +80,34 @@ export class OceanAgreementsConditions extends Instantiable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authorize the consumer defined in the agreement to execute a remote service associated with this asset.
|
||||||
|
* @param {string} agreementId Agreement ID.
|
||||||
|
* @param {string} did Asset ID.
|
||||||
|
* @param {string} grantee Consumer address.
|
||||||
|
* @param {Account} from Account of sender.
|
||||||
|
*/
|
||||||
|
public async grantServiceExecution(
|
||||||
|
agreementId: string,
|
||||||
|
did: string,
|
||||||
|
grantee: string,
|
||||||
|
from?: Account
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const { computeExecutionCondition } = this.ocean.keeper.conditions
|
||||||
|
|
||||||
|
const receipt = await computeExecutionCondition.fulfill(
|
||||||
|
agreementId,
|
||||||
|
did,
|
||||||
|
grantee,
|
||||||
|
from && from.getId()
|
||||||
|
)
|
||||||
|
return !!receipt.events.Fulfilled
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transfer the escrow or locked tokens from the LockRewardCondition contract to the publisher's account.
|
* Transfer the escrow or locked tokens from the LockRewardCondition contract to the publisher's account.
|
||||||
* This should be allowed after access has been given to the consumer and the asset data is downloaded.
|
* This should be allowed after access has been given to the consumer and the asset data is downloaded.
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
|
import { TransactionReceipt } from 'web3-core'
|
||||||
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 {
|
import { fillConditionsWithDDO, SubscribablePromise, generateId, zeroX } from '../utils'
|
||||||
fillConditionsWithDDO,
|
|
||||||
SubscribablePromise,
|
|
||||||
generateId,
|
|
||||||
zeroX
|
|
||||||
} from '../utils'
|
|
||||||
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
|
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
|
||||||
|
|
||||||
export enum CreateProgressStep {
|
export enum CreateProgressStep {
|
||||||
@ -38,9 +34,7 @@ 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(
|
public static async getInstance(config: InstantiableConfig): Promise<OceanAssets> {
|
||||||
config: InstantiableConfig
|
|
||||||
): Promise<OceanAssets> {
|
|
||||||
const instance = new OceanAssets()
|
const instance = new OceanAssets()
|
||||||
instance.setInstanceConfig(config)
|
instance.setInstanceConfig(config)
|
||||||
|
|
||||||
@ -81,7 +75,7 @@ export class OceanAssets extends Instantiable {
|
|||||||
observer.next(CreateProgressStep.EncryptingFiles)
|
observer.next(CreateProgressStep.EncryptingFiles)
|
||||||
const encryptedFiles = await this.ocean.secretStore.encrypt(
|
const encryptedFiles = await this.ocean.secretStore.encrypt(
|
||||||
did.getId(),
|
did.getId(),
|
||||||
metadata.base.files,
|
metadata.main.files,
|
||||||
publisher
|
publisher
|
||||||
)
|
)
|
||||||
this.logger.log('Files encrypted')
|
this.logger.log('Files encrypted')
|
||||||
@ -91,7 +85,7 @@ export class OceanAssets extends Instantiable {
|
|||||||
|
|
||||||
const serviceEndpoint = this.ocean.aquarius.getServiceEndpoint(did)
|
const serviceEndpoint = this.ocean.aquarius.getServiceEndpoint(did)
|
||||||
|
|
||||||
let serviceDefinitionIdCount = 0
|
let indexCount = 0
|
||||||
// create ddo itself
|
// create ddo itself
|
||||||
const ddo: DDO = new DDO({
|
const ddo: DDO = new DDO({
|
||||||
id: did.getDid(),
|
id: did.getDid(),
|
||||||
@ -110,23 +104,30 @@ export class OceanAssets extends Instantiable {
|
|||||||
],
|
],
|
||||||
service: [
|
service: [
|
||||||
{
|
{
|
||||||
type: 'Access',
|
type: 'access',
|
||||||
creator: '',
|
|
||||||
purchaseEndpoint: this.ocean.brizo.getPurchaseEndpoint(),
|
|
||||||
serviceEndpoint: this.ocean.brizo.getConsumeEndpoint(),
|
serviceEndpoint: this.ocean.brizo.getConsumeEndpoint(),
|
||||||
name: 'dataAssetAccessServiceAgreement',
|
|
||||||
templateId: templates.escrowAccessSecretStoreTemplate.getAddress(),
|
templateId: templates.escrowAccessSecretStoreTemplate.getAddress(),
|
||||||
serviceAgreementTemplate
|
attributes: {
|
||||||
|
main: {
|
||||||
|
creator: publisher.getId(),
|
||||||
|
datePublished: metadata.main.datePublished,
|
||||||
|
name: 'dataAssetAccessServiceAgreement',
|
||||||
|
price: metadata.main.price,
|
||||||
|
timeout: 3600
|
||||||
|
},
|
||||||
|
serviceAgreementTemplate
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'Authorization',
|
type: 'authorization',
|
||||||
service: 'SecretStore',
|
service: 'SecretStore',
|
||||||
serviceEndpoint: secretStoreUri
|
serviceEndpoint: secretStoreUri,
|
||||||
|
attributes: { main: {} }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'Metadata',
|
type: 'metadata',
|
||||||
serviceEndpoint,
|
serviceEndpoint,
|
||||||
metadata: {
|
attributes: {
|
||||||
// Default values
|
// Default values
|
||||||
curation: {
|
curation: {
|
||||||
rating: 0,
|
rating: 0,
|
||||||
@ -134,18 +135,15 @@ export class OceanAssets extends Instantiable {
|
|||||||
},
|
},
|
||||||
// Overwrites defaults
|
// Overwrites defaults
|
||||||
...metadata,
|
...metadata,
|
||||||
|
encryptedFiles,
|
||||||
// Cleaning not needed information
|
// Cleaning not needed information
|
||||||
base: {
|
main: {
|
||||||
...metadata.base,
|
...metadata.main,
|
||||||
contentUrls: undefined,
|
files: metadata.main.files.map((file, index) => ({
|
||||||
encryptedFiles,
|
...file,
|
||||||
files: metadata.base.files.map(
|
index,
|
||||||
(file, index) => ({
|
url: undefined
|
||||||
...file,
|
}))
|
||||||
index,
|
|
||||||
url: undefined
|
|
||||||
})
|
|
||||||
)
|
|
||||||
} as any
|
} as any
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -158,26 +156,21 @@ export class OceanAssets extends Instantiable {
|
|||||||
list.findIndex(({ type: t }) => t === type) === i
|
list.findIndex(({ type: t }) => t === type) === i
|
||||||
)
|
)
|
||||||
.reverse()
|
.reverse()
|
||||||
// Adding ID
|
// Adding index
|
||||||
.map(_ => ({
|
.map(_ => ({
|
||||||
..._,
|
..._,
|
||||||
serviceDefinitionId: String(serviceDefinitionIdCount++)
|
index: indexCount++
|
||||||
})) as Service[]
|
})) as Service[]
|
||||||
})
|
})
|
||||||
|
|
||||||
// Overwritte initial service agreement conditions
|
// Overwrite initial service agreement conditions
|
||||||
const rawConditions = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplateConditions()
|
const rawConditions = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplateConditions()
|
||||||
const conditions = fillConditionsWithDDO(rawConditions, ddo)
|
const conditions = fillConditionsWithDDO(rawConditions, ddo)
|
||||||
serviceAgreementTemplate.conditions = conditions
|
serviceAgreementTemplate.conditions = conditions
|
||||||
|
|
||||||
ddo.addChecksum()
|
|
||||||
this.logger.log('Generating proof')
|
this.logger.log('Generating proof')
|
||||||
observer.next(CreateProgressStep.GeneratingProof)
|
observer.next(CreateProgressStep.GeneratingProof)
|
||||||
await ddo.addProof(
|
await ddo.addProof(this.ocean, publisher.getId(), publisher.getPassword())
|
||||||
this.ocean,
|
|
||||||
publisher.getId(),
|
|
||||||
publisher.getPassword()
|
|
||||||
)
|
|
||||||
this.logger.log('Proof generated')
|
this.logger.log('Proof generated')
|
||||||
observer.next(CreateProgressStep.ProofGenerated)
|
observer.next(CreateProgressStep.ProofGenerated)
|
||||||
|
|
||||||
@ -206,7 +199,7 @@ export class OceanAssets extends Instantiable {
|
|||||||
public async consume(
|
public async consume(
|
||||||
agreementId: string,
|
agreementId: string,
|
||||||
did: string,
|
did: string,
|
||||||
serviceDefinitionId: string,
|
serviceIndex: number,
|
||||||
consumerAccount: Account,
|
consumerAccount: Account,
|
||||||
resultPath: string,
|
resultPath: string,
|
||||||
index?: number,
|
index?: number,
|
||||||
@ -216,7 +209,7 @@ export class OceanAssets extends Instantiable {
|
|||||||
public async consume(
|
public async consume(
|
||||||
agreementId: string,
|
agreementId: string,
|
||||||
did: string,
|
did: string,
|
||||||
serviceDefinitionId: string,
|
serviceIndex: number,
|
||||||
consumerAccount: Account,
|
consumerAccount: Account,
|
||||||
resultPath?: undefined | null,
|
resultPath?: undefined | null,
|
||||||
index?: number,
|
index?: number,
|
||||||
@ -226,18 +219,18 @@ export class OceanAssets extends Instantiable {
|
|||||||
public async consume(
|
public async consume(
|
||||||
agreementId: string,
|
agreementId: string,
|
||||||
did: string,
|
did: string,
|
||||||
serviceDefinitionId: string,
|
serviceIndex: number,
|
||||||
consumerAccount: Account,
|
consumerAccount: Account,
|
||||||
resultPath?: string,
|
resultPath?: string,
|
||||||
index: number = -1,
|
index: number = -1,
|
||||||
useSecretStore?: boolean
|
useSecretStore?: boolean
|
||||||
): Promise<string | true> {
|
): Promise<string | true> {
|
||||||
const ddo = await this.resolve(did)
|
const ddo = await this.resolve(did)
|
||||||
const { metadata } = ddo.findServiceByType('Metadata')
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
|
|
||||||
const accessService = ddo.findServiceById(serviceDefinitionId)
|
const accessService = ddo.findServiceById(serviceIndex)
|
||||||
|
|
||||||
const { files } = metadata.base
|
const { files } = attributes.main
|
||||||
|
|
||||||
const { serviceEndpoint } = accessService
|
const { serviceEndpoint } = accessService
|
||||||
|
|
||||||
@ -250,7 +243,7 @@ export class OceanAssets extends Instantiable {
|
|||||||
this.logger.log('Consuming files')
|
this.logger.log('Consuming files')
|
||||||
|
|
||||||
resultPath = resultPath
|
resultPath = resultPath
|
||||||
? `${resultPath}/datafile.${ddo.shortId()}.${serviceDefinitionId}/`
|
? `${resultPath}/datafile.${ddo.shortId()}.${serviceIndex}/`
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
if (!useSecretStore) {
|
if (!useSecretStore) {
|
||||||
@ -265,9 +258,9 @@ export class OceanAssets extends Instantiable {
|
|||||||
} else {
|
} else {
|
||||||
const files = await this.ocean.secretStore.decrypt(
|
const files = await this.ocean.secretStore.decrypt(
|
||||||
did,
|
did,
|
||||||
ddo.findServiceByType('Metadata').metadata.base.encryptedFiles,
|
ddo.findServiceByType('metadata').attributes.encryptedFiles,
|
||||||
consumerAccount,
|
consumerAccount,
|
||||||
ddo.findServiceByType('Authorization').serviceEndpoint
|
ddo.findServiceByType('authorization').serviceEndpoint
|
||||||
)
|
)
|
||||||
const downloads = files
|
const downloads = files
|
||||||
.filter(({ index: i }) => index === -1 || index === i)
|
.filter(({ index: i }) => index === -1 || index === i)
|
||||||
@ -288,13 +281,13 @@ export class OceanAssets extends Instantiable {
|
|||||||
* Start the purchase/order of an asset's service. Starts by signing the service agreement
|
* Start the purchase/order of an asset's service. Starts by signing the service agreement
|
||||||
* then sends the request to the publisher via the service endpoint (Brizo http service).
|
* then sends the request to the publisher via the service endpoint (Brizo http service).
|
||||||
* @param {string} did Decentralized ID.
|
* @param {string} did Decentralized ID.
|
||||||
* @param {string} serviceDefinitionId Service definition ID.
|
* @param {number} index Service index.
|
||||||
* @param {Account} consumer Consumer account.
|
* @param {Account} consumer Consumer account.
|
||||||
* @return {Promise<string>} Returns Agreement ID
|
* @return {Promise<string>} Returns Agreement ID
|
||||||
*/
|
*/
|
||||||
public order(
|
public order(
|
||||||
did: string,
|
did: string,
|
||||||
serviceDefinitionId: string,
|
index: number,
|
||||||
consumer: Account
|
consumer: Account
|
||||||
): SubscribablePromise<OrderProgressStep, string> {
|
): SubscribablePromise<OrderProgressStep, string> {
|
||||||
return new SubscribablePromise(async observer => {
|
return new SubscribablePromise(async observer => {
|
||||||
@ -304,7 +297,7 @@ export class OceanAssets extends Instantiable {
|
|||||||
const ddo = await this.resolve(did)
|
const ddo = await this.resolve(did)
|
||||||
|
|
||||||
const { keeper } = this.ocean
|
const { keeper } = this.ocean
|
||||||
const templateName = ddo.findServiceByType('Access')
|
const templateName = ddo.findServiceByType('access').attributes
|
||||||
.serviceAgreementTemplate.contractName
|
.serviceAgreementTemplate.contractName
|
||||||
const template = keeper.getTemplateByName(templateName)
|
const template = keeper.getTemplateByName(templateName)
|
||||||
const accessCondition = keeper.conditions.accessSecretStoreCondition
|
const accessCondition = keeper.conditions.accessSecretStoreCondition
|
||||||
@ -316,7 +309,7 @@ export class OceanAssets extends Instantiable {
|
|||||||
this.logger.log('Agreement initialized')
|
this.logger.log('Agreement initialized')
|
||||||
observer.next(OrderProgressStep.AgreementInitialized)
|
observer.next(OrderProgressStep.AgreementInitialized)
|
||||||
|
|
||||||
const { metadata } = ddo.findServiceByType('Metadata')
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
|
|
||||||
this.logger.log('Locking payment')
|
this.logger.log('Locking payment')
|
||||||
|
|
||||||
@ -327,7 +320,7 @@ export class OceanAssets extends Instantiable {
|
|||||||
observer.next(OrderProgressStep.LockingPayment)
|
observer.next(OrderProgressStep.LockingPayment)
|
||||||
const paid = await oceanAgreements.conditions.lockReward(
|
const paid = await oceanAgreements.conditions.lockReward(
|
||||||
agreementId,
|
agreementId,
|
||||||
metadata.base.price,
|
attributes.main.price,
|
||||||
consumer
|
consumer
|
||||||
)
|
)
|
||||||
observer.next(OrderProgressStep.LockedPayment)
|
observer.next(OrderProgressStep.LockedPayment)
|
||||||
@ -352,7 +345,7 @@ export class OceanAssets extends Instantiable {
|
|||||||
await oceanAgreements.create(
|
await oceanAgreements.create(
|
||||||
did,
|
did,
|
||||||
agreementId,
|
agreementId,
|
||||||
serviceDefinitionId,
|
index,
|
||||||
undefined,
|
undefined,
|
||||||
consumer,
|
consumer,
|
||||||
consumer
|
consumer
|
||||||
@ -397,19 +390,35 @@ export class OceanAssets extends Instantiable {
|
|||||||
* @param {string} owner Owner address.
|
* @param {string} owner Owner address.
|
||||||
* @return {Promise<string[]>} List of DIDs.
|
* @return {Promise<string[]>} List of DIDs.
|
||||||
*/
|
*/
|
||||||
public async ownerAssets(owner: string) {
|
public async ownerAssets(owner: string): Promise<string[]> {
|
||||||
return this.ocean.keeper.didRegistry.getAttributesByOwner(owner)
|
return this.ocean.keeper.didRegistry.getAttributesByOwner(owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transfer ownership of an asset.
|
||||||
|
* @param {string} did Asset DID.
|
||||||
|
* @param {string} newOwner Ethereum address of the new owner of the DID.
|
||||||
|
* @return {Promise<TransactionReceipt>} Returns Web3 transaction receipt.
|
||||||
|
*/
|
||||||
|
public async transferOwnership(
|
||||||
|
did: string,
|
||||||
|
newOwner: string
|
||||||
|
): Promise<TransactionReceipt> {
|
||||||
|
const owner = await this.ocean.assets.owner(did)
|
||||||
|
return this.ocean.keeper.didRegistry.transferDIDOwnership(did, newOwner, owner)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the assets of a consumer.
|
* Returns the assets of a consumer.
|
||||||
* @param {string} consumer Consumer address.
|
* @param {string} consumer Consumer address.
|
||||||
* @return {Promise<string[]>} List of DIDs.
|
* @return {Promise<string[]>} List of DIDs.
|
||||||
*/
|
*/
|
||||||
public async consumerAssets(consumer: string) {
|
public async consumerAssets(consumer: string): Promise<string[]> {
|
||||||
return (await this.ocean.keeper.conditions.accessSecretStoreCondition.getGrantedDidByConsumer(
|
return (
|
||||||
consumer
|
await this.ocean.keeper.conditions.accessSecretStoreCondition.getGrantedDidByConsumer(
|
||||||
)).map(({ did }) => did)
|
consumer
|
||||||
|
)
|
||||||
|
).map(({ did }) => did)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,9 +13,7 @@ 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(
|
public static async getInstance(config: InstantiableConfig): Promise<OceanAuth> {
|
||||||
config: InstantiableConfig
|
|
||||||
): Promise<OceanAuth> {
|
|
||||||
const instance = new OceanAuth()
|
const instance = new OceanAuth()
|
||||||
instance.setInstanceConfig(config)
|
instance.setInstanceConfig(config)
|
||||||
|
|
||||||
|
@ -65,10 +65,10 @@ export class OceanSecretStore extends Instantiable {
|
|||||||
consumer?: Account,
|
consumer?: Account,
|
||||||
secretStoreUrl?: string
|
secretStoreUrl?: string
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.getSecretStoreByAccount(
|
return this.getSecretStoreByAccount(consumer, secretStoreUrl).decryptDocument(
|
||||||
consumer,
|
noDidPrefixed(did),
|
||||||
secretStoreUrl
|
content
|
||||||
).decryptDocument(noDidPrefixed(did), content)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getSecretStoreByAccount(account: Account, secretStoreUrl?: string) {
|
private getSecretStoreByAccount(account: Account, secretStoreUrl?: string) {
|
||||||
@ -86,13 +86,7 @@ export class OceanSecretStore extends Instantiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getSecretStore(config: SecretStoreConfig): SecretStore {
|
private getSecretStore(config: SecretStoreConfig): SecretStore {
|
||||||
const {
|
const { secretStoreUri, parityUri, password, address, threshold } = config
|
||||||
secretStoreUri,
|
|
||||||
parityUri,
|
|
||||||
password,
|
|
||||||
address,
|
|
||||||
threshold
|
|
||||||
} = config
|
|
||||||
config = { secretStoreUri, parityUri, password, address, threshold }
|
config = { secretStoreUri, parityUri, password, address, threshold }
|
||||||
|
|
||||||
return new SecretStore(config)
|
return new SecretStore(config)
|
||||||
|
@ -9,9 +9,7 @@ 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(
|
public static async getInstance(config: InstantiableConfig): Promise<OceanTokens> {
|
||||||
config: InstantiableConfig
|
|
||||||
): Promise<OceanTokens> {
|
|
||||||
const instance = new OceanTokens()
|
const instance = new OceanTokens()
|
||||||
instance.setInstanceConfig(config)
|
instance.setInstanceConfig(config)
|
||||||
|
|
||||||
@ -20,22 +18,18 @@ export class OceanTokens extends Instantiable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Transfer a number of tokens to the mentioned account.
|
* Transfer a number of tokens to the mentioned account.
|
||||||
* @param {string} to Address that receives the account.
|
* @param {string} to Address that receives the tokens.
|
||||||
* @param {number} amount Tokens to transfer.
|
* @param {number} amount Tokens to transfer.
|
||||||
* @param {Account} from Sender account address.
|
* @param {Account} from Sender account address.
|
||||||
* @return {Promise<boolean>} Success,
|
* @return {Promise<boolean>} Success,
|
||||||
*/
|
*/
|
||||||
public async transfer(
|
public async transfer(to: string, amount: number, from: Account): Promise<boolean> {
|
||||||
to: string,
|
|
||||||
amount: number,
|
|
||||||
from: Account
|
|
||||||
): Promise<boolean> {
|
|
||||||
this.ocean.keeper.token.transfer(to, amount, from.getId())
|
this.ocean.keeper.token.transfer(to, amount, from.getId())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request tokens for a account.
|
* Request tokens for an account.
|
||||||
* @param {Account} account Account instance.
|
* @param {Account} account Account instance.
|
||||||
* @param {number} amount Token amount.
|
* @param {number} amount Token amount.
|
||||||
* @return {Promise<boolean>} Success.
|
* @return {Promise<boolean>} Success.
|
||||||
|
@ -42,9 +42,7 @@ 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(
|
public static async getInstance(config: InstantiableConfig): Promise<OceanVersions> {
|
||||||
config: InstantiableConfig
|
|
||||||
): Promise<OceanVersions> {
|
|
||||||
const instance = new OceanVersions()
|
const instance = new OceanVersions()
|
||||||
instance.setInstanceConfig(config)
|
instance.setInstanceConfig(config)
|
||||||
|
|
||||||
@ -99,10 +97,7 @@ export class OceanVersions extends Instantiable {
|
|||||||
|
|
||||||
// Aquarius
|
// Aquarius
|
||||||
try {
|
try {
|
||||||
const {
|
const { software: name, version } = await this.ocean.aquarius.getVersionInfo()
|
||||||
software: name,
|
|
||||||
version
|
|
||||||
} = await this.ocean.aquarius.getVersionInfo()
|
|
||||||
versions.aquarius = {
|
versions.aquarius = {
|
||||||
name,
|
name,
|
||||||
status: OceanPlatformTechStatus.Working,
|
status: OceanPlatformTechStatus.Working,
|
||||||
@ -124,9 +119,7 @@ export class OceanVersions extends Instantiable {
|
|||||||
.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).filter(_ => !!_)
|
||||||
.map(({ contracts }) => contracts)
|
|
||||||
.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)
|
||||||
@ -140,15 +133,14 @@ export class OceanVersions extends Instantiable {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (address !== _) {
|
if (address !== _) {
|
||||||
|
this.logger.warn(`Error on contract ${name}`)
|
||||||
contractStatus = false
|
contractStatus = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
versions.status = {
|
versions.status = {
|
||||||
ok: !techs.find(
|
ok: !techs.find(({ status }) => status !== OceanPlatformTechStatus.Working),
|
||||||
({ status }) => status !== OceanPlatformTechStatus.Working
|
|
||||||
),
|
|
||||||
network: Object.keys(networks).length === 1,
|
network: Object.keys(networks).length === 1,
|
||||||
contracts: contractStatus
|
contracts: contractStatus
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,7 @@ 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(
|
public static async getInstance(config: InstantiableConfig): Promise<OceanUtils> {
|
||||||
config: InstantiableConfig
|
|
||||||
): Promise<OceanUtils> {
|
|
||||||
const instance = new OceanUtils()
|
const instance = new OceanUtils()
|
||||||
instance.setInstanceConfig(config)
|
instance.setInstanceConfig(config)
|
||||||
|
|
||||||
|
@ -13,20 +13,17 @@ export class ServiceAgreement extends Instantiable {
|
|||||||
|
|
||||||
public async signServiceAgreement(
|
public async signServiceAgreement(
|
||||||
ddo: DDO,
|
ddo: DDO,
|
||||||
serviceDefinitionId: string,
|
index: number,
|
||||||
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'>(index)
|
||||||
const timelockValues: number[] = this.getTimeValuesFromService(
|
const timelockValues: number[] = this.getTimeValuesFromService(
|
||||||
service,
|
service,
|
||||||
'timelock'
|
'timelock'
|
||||||
)
|
)
|
||||||
const timeoutValues: number[] = this.getTimeValuesFromService(
|
const timeoutValues: number[] = this.getTimeValuesFromService(service, 'timeout')
|
||||||
service,
|
|
||||||
'timeout'
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!service.templateId) {
|
if (!service.templateId) {
|
||||||
throw new Error('TemplateId not found in DDO.')
|
throw new Error('TemplateId not found in DDO.')
|
||||||
@ -78,7 +75,7 @@ export class ServiceAgreement extends Instantiable {
|
|||||||
timelocks: number[],
|
timelocks: number[],
|
||||||
timeouts: number[]
|
timeouts: number[]
|
||||||
): string {
|
): string {
|
||||||
const args = [
|
const args: any = [
|
||||||
{ 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 },
|
||||||
@ -86,14 +83,14 @@ export class ServiceAgreement extends Instantiable {
|
|||||||
{ type: 'bytes32', value: zeroX(serviceAgreementId) }
|
{ type: 'bytes32', value: zeroX(serviceAgreementId) }
|
||||||
]
|
]
|
||||||
|
|
||||||
return this.web3.utils.soliditySha3(...args).toString('hex')
|
return this.web3.utils.soliditySha3(...args)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTimeValuesFromService(
|
private getTimeValuesFromService(
|
||||||
service: ServiceAccess,
|
service: ServiceAccess,
|
||||||
type: 'timeout' | 'timelock'
|
type: 'timeout' | 'timelock'
|
||||||
): number[] {
|
): number[] {
|
||||||
const timeoutValues: number[] = service.serviceAgreementTemplate.conditions.map(
|
const timeoutValues: number[] = service.attributes.serviceAgreementTemplate.conditions.map(
|
||||||
(condition: ServiceAgreementTemplateCondition) => condition[type]
|
(condition: ServiceAgreementTemplateCondition) => condition[type]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ export class SignatureUtils extends Instantiable {
|
|||||||
const isMetaMask =
|
const isMetaMask =
|
||||||
this.web3 &&
|
this.web3 &&
|
||||||
this.web3.currentProvider &&
|
this.web3.currentProvider &&
|
||||||
this.web3.currentProvider.isMetaMask
|
(this.web3.currentProvider as any).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) {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import fetch, { BodyInit, RequestInit, Response } from 'node-fetch'
|
import { BodyInit, RequestInit, Response } from 'node-fetch'
|
||||||
import * as fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
|
import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
|
||||||
|
|
||||||
|
const fetch = require('node-fetch')
|
||||||
import save = require('save-file')
|
import save = require('save-file')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,7 +52,7 @@ export class WebServiceConnector extends Instantiable {
|
|||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Response error.')
|
throw new Error('Response error.')
|
||||||
}
|
}
|
||||||
let filename
|
let filename: string
|
||||||
try {
|
try {
|
||||||
filename = response.headers
|
filename = response.headers
|
||||||
.get('content-disposition')
|
.get('content-disposition')
|
||||||
@ -69,9 +69,7 @@ export class WebServiceConnector extends Instantiable {
|
|||||||
// eslint-disable-next-line no-async-promise-executor
|
// eslint-disable-next-line no-async-promise-executor
|
||||||
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(
|
const fileStream = fs.createWriteStream(`${destination}${filename}`)
|
||||||
`${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)
|
||||||
|
12
src/squid.ts
12
src/squid.ts
@ -24,14 +24,4 @@ export {
|
|||||||
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, Account, Config, DID, Logger, Keeper, conditions, templates, utils }
|
||||||
Ocean,
|
|
||||||
Account,
|
|
||||||
Config,
|
|
||||||
DID,
|
|
||||||
Logger,
|
|
||||||
Keeper,
|
|
||||||
conditions,
|
|
||||||
templates,
|
|
||||||
utils
|
|
||||||
}
|
|
||||||
|
@ -36,9 +36,7 @@ function inputMatch(
|
|||||||
if (typeof input !== 'string') {
|
if (typeof input !== 'string') {
|
||||||
LoggerInstance.debug('Not input string:')
|
LoggerInstance.debug('Not input string:')
|
||||||
LoggerInstance.debug(input)
|
LoggerInstance.debug(input)
|
||||||
throw new Error(
|
throw new Error(`[${conversorName}] Expected string, input type: ${typeof input}`)
|
||||||
`[${conversorName}] Expected string, input type: ${typeof input}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
const match = input.match(regexp)
|
const match = input.match(regexp)
|
||||||
if (!match) {
|
if (!match) {
|
||||||
|
@ -12,9 +12,7 @@ function fillParameterWithDDO(
|
|||||||
switch (name) {
|
switch (name) {
|
||||||
case 'amount':
|
case 'amount':
|
||||||
case 'price':
|
case 'price':
|
||||||
return String(
|
return String(ddo.findServiceByType('metadata').attributes.main.price)
|
||||||
ddo.findServiceByType('Metadata').metadata.base.price
|
|
||||||
)
|
|
||||||
case 'assetId':
|
case 'assetId':
|
||||||
case 'documentId':
|
case 'documentId':
|
||||||
case 'documentKeyId':
|
case 'documentKeyId':
|
||||||
|
@ -8,9 +8,7 @@ const zipObject = (keys = [], values = []) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const objectPromiseAll = async (obj: {
|
export const objectPromiseAll = async (obj: { [key: string]: Promise<any> }) => {
|
||||||
[key: string]: Promise<any>
|
|
||||||
}) => {
|
|
||||||
const keys = Object.keys(obj)
|
const keys = Object.keys(obj)
|
||||||
const result = await Promise.all(Object.values(obj))
|
const result = await Promise.all(Object.values(obj))
|
||||||
return zipObject(keys, result)
|
return zipObject(keys, result)
|
||||||
|
@ -40,9 +40,7 @@ export class SubscribableObserver<T, P> {
|
|||||||
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(
|
.filter((callback: any) => callback && typeof callback === 'function')
|
||||||
(callback: any) => callback && typeof callback === 'function'
|
|
||||||
)
|
|
||||||
.forEach((callback: any) => callback(value))
|
.forEach((callback: any) => callback(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,7 @@ export class SubscribablePromise<T extends any, P extends any> {
|
|||||||
this
|
this
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(
|
constructor(executor: (observer: SubscribableObserver<T, P>) => void | Promise<P>) {
|
||||||
executor: (observer: SubscribableObserver<T, P>) => void | Promise<P>
|
|
||||||
) {
|
|
||||||
// Defear
|
// Defear
|
||||||
setTimeout(() => this.init(executor), 1)
|
setTimeout(() => this.init(executor), 1)
|
||||||
}
|
}
|
||||||
@ -28,10 +26,7 @@ export class SubscribablePromise<T extends any, P extends any> {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
public then(
|
public then(onfulfilled?: (value: P) => any, onrejected?: (error: any) => any) {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,9 +38,7 @@ 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(
|
private init(executor: (observer: SubscribableObserver<T, P>) => void | Promise<P>) {
|
||||||
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)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as assert from 'assert'
|
import assert from 'assert'
|
||||||
import * as squid from '../src/squid'
|
import * as squid from '../src/squid'
|
||||||
|
|
||||||
describe('Squid', () => {
|
describe('Squid', () => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { assert, spy, use } from 'chai'
|
import { assert, spy, use } from 'chai'
|
||||||
import * as spies from 'chai-spies'
|
import spies from 'chai-spies'
|
||||||
import { Ocean } from '../../src/ocean/Ocean'
|
import { Ocean } from '../../src/ocean/Ocean'
|
||||||
import { Aquarius, SearchQuery } from '../../src/aquarius/Aquarius'
|
import { Aquarius, SearchQuery } from '../../src/aquarius/Aquarius'
|
||||||
import { DDO } from '../../src/ddo/DDO'
|
import { DDO } from '../../src/ddo/DDO'
|
||||||
@ -22,7 +22,12 @@ describe('Aquarius', () => {
|
|||||||
page = 0,
|
page = 0,
|
||||||
total_pages = 1,
|
total_pages = 1,
|
||||||
total_results = 1
|
total_results = 1
|
||||||
) => ({ results, page, total_pages, total_results })
|
) => ({
|
||||||
|
results,
|
||||||
|
page,
|
||||||
|
total_pages,
|
||||||
|
total_results
|
||||||
|
})
|
||||||
/* eslint-enable @typescript-eslint/camelcase */
|
/* eslint-enable @typescript-eslint/camelcase */
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@ -48,9 +53,7 @@ describe('Aquarius', () => {
|
|||||||
} as SearchQuery
|
} as SearchQuery
|
||||||
|
|
||||||
it('should query metadata', async () => {
|
it('should query metadata', 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')
|
||||||
@ -61,9 +64,7 @@ describe('Aquarius', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
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')
|
||||||
@ -86,9 +87,7 @@ describe('Aquarius', () => {
|
|||||||
} 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')
|
||||||
@ -99,9 +98,7 @@ describe('Aquarius', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
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')
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { assert, expect, spy, use } from 'chai'
|
import { assert, expect, spy, use } from 'chai'
|
||||||
import * as spies from 'chai-spies'
|
import spies from 'chai-spies'
|
||||||
import * as Web3 from 'web3'
|
import 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'
|
||||||
@ -46,8 +46,7 @@ describe('DDO', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'CredentialRepositoryService',
|
type: 'CredentialRepositoryService',
|
||||||
serviceEndpoint:
|
serviceEndpoint: 'https://repository.example.com/service/8377464'
|
||||||
'https://repository.example.com/service/8377464'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'XdiService',
|
type: 'XdiService',
|
||||||
@ -77,29 +76,58 @@ describe('DDO', () => {
|
|||||||
serviceEndpoint: 'https://bops.example.com/enterprise/'
|
serviceEndpoint: 'https://bops.example.com/enterprise/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'Consume',
|
type: 'consume',
|
||||||
serviceEndpoint:
|
serviceEndpoint:
|
||||||
'http://mybrizo.org/api/v1/brizo/services/consume?pubKey={pubKey}&serviceId={serviceId}&url={url}'
|
'http://mybrizo.org/api/v1/brizo/services/consume?pubKey={pubKey}&serviceId={serviceId}&url={url}'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'Compute',
|
type: 'compute',
|
||||||
serviceEndpoint:
|
serviceEndpoint:
|
||||||
'http://mybrizo.org/api/v1/brizo/services/compute?pubKey={pubKey}&serviceId={serviceId}&algo={algo}&container={container}'
|
'http://mybrizo.org/api/v1/brizo/services/compute?pubKey={pubKey}&serviceId={serviceId}&algo={algo}&container={container}'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'Metadata',
|
type: 'metadata',
|
||||||
|
index: 0,
|
||||||
serviceEndpoint:
|
serviceEndpoint:
|
||||||
'http://myaquarius.org/api/v1/provider/assets/metadata/{did}',
|
'http://myaquarius.org/api/v1/provider/assets/metadata/{did}',
|
||||||
metadata: {
|
attributes: {
|
||||||
base: {
|
main: {
|
||||||
name: 'UK Weather information 2011',
|
name: 'UK Weather information 2011',
|
||||||
type: 'dataset',
|
type: 'dataset',
|
||||||
description:
|
|
||||||
'Weather information of UK including temperature and humidity',
|
|
||||||
dateCreated: '2012-10-10T17:00:000Z',
|
dateCreated: '2012-10-10T17:00:000Z',
|
||||||
datePublished: '2012-10-10T17:00:000Z',
|
datePublished: '2012-10-10T17:00:000Z',
|
||||||
author: 'Met Office',
|
author: 'Met Office',
|
||||||
license: 'CC-BY',
|
license: 'CC-BY',
|
||||||
|
price: '10',
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
checksum: 'efb2c764274b745f5fc37f97c6b0e761',
|
||||||
|
contentLength: '4535431',
|
||||||
|
contentType: 'application/json',
|
||||||
|
resourceId:
|
||||||
|
'access-log2018-02-13-15-17-29-18386C502CAEA932'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
checksum: '085340abffh21495345af97c6b0e761',
|
||||||
|
contentLength: '12324',
|
||||||
|
contentType: 'application/json'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 2,
|
||||||
|
contentType: ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
curation: {
|
||||||
|
rating: 0.93,
|
||||||
|
numVotes: 123,
|
||||||
|
schema: 'Binary Voting'
|
||||||
|
},
|
||||||
|
additionalInformation: {
|
||||||
|
description:
|
||||||
|
'Weather information of UK including temperature and humidity',
|
||||||
copyrightHolder: 'Met Office',
|
copyrightHolder: 'Met Office',
|
||||||
workExample:
|
workExample:
|
||||||
'423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68',
|
'423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68',
|
||||||
@ -113,55 +141,20 @@ describe('DDO', () => {
|
|||||||
'http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/'
|
'http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldsDescription:
|
fieldsDescription: 'http://data.ceda.ac.uk/badc/ukcp09/'
|
||||||
'http://data.ceda.ac.uk/badc/ukcp09/'
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
inLanguage: 'en',
|
inLanguage: 'en',
|
||||||
categories: ['Economy', 'Data Science'],
|
categories: ['Economy', 'Data Science'],
|
||||||
tags: [
|
tags: ['weather', 'uk', '2011', 'temperature', 'humidity'],
|
||||||
'weather',
|
updateFrequency: 'yearly',
|
||||||
'uk',
|
|
||||||
'2011',
|
|
||||||
'temperature',
|
|
||||||
'humidity'
|
|
||||||
],
|
|
||||||
price: 10,
|
|
||||||
files: [
|
|
||||||
{
|
|
||||||
index: 0,
|
|
||||||
checksum: 'efb2c764274b745f5fc37f97c6b0e761',
|
|
||||||
contentLength: 4535431,
|
|
||||||
resourceId:
|
|
||||||
'access-log2018-02-13-15-17-29-18386C502CAEA932'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
index: 1,
|
|
||||||
checksum: '085340abffh21495345af97c6b0e761',
|
|
||||||
contentLength: 12324
|
|
||||||
},
|
|
||||||
{
|
|
||||||
index: 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
checksum: ''
|
|
||||||
},
|
|
||||||
curation: {
|
|
||||||
rating: 0.93,
|
|
||||||
numVotes: 123,
|
|
||||||
schema: 'Binary Voting'
|
|
||||||
},
|
|
||||||
additionalInformation: {
|
|
||||||
updateFrecuency: 'yearly',
|
|
||||||
structuredMarkup: [
|
structuredMarkup: [
|
||||||
{
|
{
|
||||||
uri:
|
uri: 'http://skos.um.es/unescothes/C01194/jsonld',
|
||||||
'http://skos.um.es/unescothes/C01194/jsonld',
|
|
||||||
mediaType: 'application/ld+json'
|
mediaType: 'application/ld+json'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
uri:
|
uri: 'http://skos.um.es/unescothes/C01194/turtle',
|
||||||
'http://skos.um.es/unescothes/C01194/turtle',
|
|
||||||
mediaType: 'text/turtle'
|
mediaType: 'text/turtle'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -230,10 +223,7 @@ describe('DDO', () => {
|
|||||||
assert.instanceOf(ddo, DDO)
|
assert.instanceOf(ddo, DDO)
|
||||||
|
|
||||||
assert.equal(ddo.id, testDDO.id)
|
assert.equal(ddo.id, testDDO.id)
|
||||||
assert.equal(
|
assert.equal(ddo.publicKey[0].publicKeyPem, testDDO.publicKey[0].publicKeyPem)
|
||||||
ddo.publicKey[0].publicKeyPem,
|
|
||||||
testDDO.publicKey[0].publicKeyPem
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should properly deserialize from json file', async () => {
|
it('should properly deserialize from json file', async () => {
|
||||||
@ -241,10 +231,7 @@ describe('DDO', () => {
|
|||||||
assert(ddo)
|
assert(ddo)
|
||||||
|
|
||||||
assert.equal(ddo.id, jsonDDO.id)
|
assert.equal(ddo.id, jsonDDO.id)
|
||||||
assert.equal(
|
assert.equal(ddo.publicKey[0].publicKeyPem, jsonDDO.publicKey[0].publicKeyPem)
|
||||||
ddo.publicKey[0].publicKeyPem,
|
|
||||||
jsonDDO.publicKey[0].publicKeyPem
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -265,11 +252,7 @@ describe('DDO', () => {
|
|||||||
const signature = `0x${'a'.repeat(130)}`
|
const signature = `0x${'a'.repeat(130)}`
|
||||||
|
|
||||||
it('should properly generate the proof', async () => {
|
it('should properly generate the proof', async () => {
|
||||||
const signTextSpy = spy.on(
|
const signTextSpy = spy.on(ocean.utils.signature, 'signText', () => signature)
|
||||||
ocean.utils.signature,
|
|
||||||
'signText',
|
|
||||||
() => 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)
|
||||||
@ -294,12 +277,8 @@ describe('DDO', () => {
|
|||||||
signaturValue: 'test'
|
signaturValue: 'test'
|
||||||
} as any
|
} as any
|
||||||
const ddo = new DDO(testDDO)
|
const ddo = new DDO(testDDO)
|
||||||
const generateProofSpy = spy.on(
|
const generateProofSpy = spy.on(ddo, 'generateProof', () => fakeProof)
|
||||||
ddo,
|
await ddo.addProof(ocean, publicKey)
|
||||||
'generateProof',
|
|
||||||
() => fakeProof
|
|
||||||
)
|
|
||||||
await ddo.addProof(web3, publicKey)
|
|
||||||
|
|
||||||
assert.equal(ddo.proof, fakeProof)
|
assert.equal(ddo.proof, fakeProof)
|
||||||
expect(generateProofSpy).to.have.been.called.with(publicKey)
|
expect(generateProofSpy).to.have.been.called.with(publicKey)
|
||||||
|
@ -30,11 +30,9 @@ describe('ContractWrapperBase', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should fail to call on an unknown contract function', done => {
|
it('should fail to call on an unknown contract function', done => {
|
||||||
wrappedContract
|
wrappedContract.sendMock('balanceOfxxx', '0x00', ['0x00']).catch(() => {
|
||||||
.sendMock('balanceOfxxx', '0x00', ['0x00'])
|
done()
|
||||||
.catch(() => {
|
})
|
||||||
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 => {
|
||||||
@ -46,11 +44,9 @@ describe('ContractWrapperBase', () => {
|
|||||||
|
|
||||||
describe('#send()', () => {
|
describe('#send()', () => {
|
||||||
it('should fail to call on an unknown contract function', done => {
|
it('should fail to call on an unknown contract function', done => {
|
||||||
wrappedContract
|
wrappedContract.sendMock('transferxxx', accounts[0].getId(), []).catch(() => {
|
||||||
.sendMock('transferxxx', accounts[0].getId(), [])
|
done()
|
||||||
.catch(() => {
|
})
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -17,17 +17,14 @@ 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 = () =>
|
executeTransaction = () => ocean.keeper.dispenser.requestTokens(10, account)
|
||||||
ocean.keeper.dispenser.requestTokens(10, account)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#subscribe()', () => {
|
describe('#subscribe()', () => {
|
||||||
it('should be able to listen to events', async () => {
|
it('should be able to listen to events', async () => {
|
||||||
const event = eventHandler.getEvent(
|
const event = eventHandler.getEvent(ocean.keeper.token, 'Transfer', {
|
||||||
ocean.keeper.token,
|
to: account
|
||||||
'Transfer',
|
})
|
||||||
{ to: account }
|
|
||||||
)
|
|
||||||
let validResolve = false
|
let validResolve = false
|
||||||
let subscription: ContractEventSubscription
|
let subscription: ContractEventSubscription
|
||||||
|
|
||||||
@ -57,11 +54,7 @@ describe('ContractEvent', () => {
|
|||||||
describe('#once()', () => {
|
describe('#once()', () => {
|
||||||
it('should listen to event only once', async () => {
|
it('should listen to event only once', async () => {
|
||||||
const to = account
|
const to = account
|
||||||
const event = eventHandler.getEvent(
|
const event = eventHandler.getEvent(ocean.keeper.token, 'Transfer', { to })
|
||||||
ocean.keeper.token,
|
|
||||||
'Transfer',
|
|
||||||
{ to }
|
|
||||||
)
|
|
||||||
let canBeRejected = false
|
let canBeRejected = false
|
||||||
|
|
||||||
const waitUntilEvent = new Promise((resolve, reject) => {
|
const waitUntilEvent = new Promise((resolve, reject) => {
|
||||||
@ -85,11 +78,7 @@ describe('ContractEvent', () => {
|
|||||||
|
|
||||||
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(
|
const event = eventHandler.getEvent(ocean.keeper.token, 'Transfer', { to })
|
||||||
ocean.keeper.token,
|
|
||||||
'Transfer',
|
|
||||||
{ to }
|
|
||||||
)
|
|
||||||
|
|
||||||
const waitUntilEvent = event.once()
|
const waitUntilEvent = event.once()
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ 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)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#registerAttribute()', () => {
|
describe('#registerAttribute()', () => {
|
||||||
@ -89,4 +89,36 @@ describe('DIDRegistry', () => {
|
|||||||
assert.equal(owner, `0x${'0'.repeat(40)}`)
|
assert.equal(owner, `0x${'0'.repeat(40)}`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('#transferDIDOwnership()', () => {
|
||||||
|
it('should be able to transfer ownership', async () => {
|
||||||
|
// create and register DID
|
||||||
|
const ownerAccount: Account = (await ocean.accounts.list())[0]
|
||||||
|
const did = generateId()
|
||||||
|
const data = 'my nice provider, is nice'
|
||||||
|
await didRegistry.registerAttribute(
|
||||||
|
did,
|
||||||
|
'0123456789abcdef',
|
||||||
|
[],
|
||||||
|
data,
|
||||||
|
ownerAccount.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
// transfer
|
||||||
|
const newOwnerAccount: Account = (await ocean.accounts.list())[1]
|
||||||
|
await didRegistry.transferDIDOwnership(
|
||||||
|
did,
|
||||||
|
newOwnerAccount.getId(),
|
||||||
|
ownerAccount.getId()
|
||||||
|
)
|
||||||
|
|
||||||
|
// check
|
||||||
|
const newOwner = await didRegistry.getDIDOwner(did)
|
||||||
|
assert.equal(
|
||||||
|
newOwner,
|
||||||
|
newOwnerAccount.getId(),
|
||||||
|
`Got ${newOwner} but expected ${newOwnerAccount.getId()}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { assert, expect, spy, use } from 'chai'
|
import { assert, expect, spy, use } from 'chai'
|
||||||
import * as spies from 'chai-spies'
|
import 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'
|
||||||
@ -27,11 +27,7 @@ describe('EventHandler', () => {
|
|||||||
assert.isDefined(subscription)
|
assert.isDefined(subscription)
|
||||||
|
|
||||||
const countAfter = eventHandler.count
|
const countAfter = eventHandler.count
|
||||||
assert.equal(
|
assert.equal(countBefore + 1, countAfter, 'The event seems not added.')
|
||||||
countBefore + 1,
|
|
||||||
countAfter,
|
|
||||||
'The event seems not added.'
|
|
||||||
)
|
|
||||||
|
|
||||||
subscription.unsubscribe()
|
subscription.unsubscribe()
|
||||||
})
|
})
|
||||||
@ -58,11 +54,7 @@ describe('EventHandler', () => {
|
|||||||
eventHandler.unsubscribe(callback)
|
eventHandler.unsubscribe(callback)
|
||||||
|
|
||||||
const countAfter = eventHandler.count
|
const countAfter = eventHandler.count
|
||||||
assert.equal(
|
assert.equal(countBefore, countAfter, 'The event seems not removed.')
|
||||||
countBefore,
|
|
||||||
countAfter,
|
|
||||||
'The event seems not removed.'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
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'
|
||||||
|
|
||||||
|
interface ContractTest extends Contract {
|
||||||
|
testContract?: boolean
|
||||||
|
$initialized?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
@ -134,32 +139,30 @@ export default class TestContractHandler extends ContractHandler {
|
|||||||
from: string,
|
from: string,
|
||||||
args: any[] = [],
|
args: any[] = [],
|
||||||
tokens: { [name: string]: string } = {}
|
tokens: { [name: string]: string } = {}
|
||||||
): Promise<Contract & { $initialized: boolean }> {
|
): Promise<ContractTest> {
|
||||||
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: ContractTest = await ContractHandler.getContract(name, where)
|
||||||
if (contract.testContract) {
|
if (contract.testContract) {
|
||||||
return { ...contract, $initialized: true }
|
return { ...contract, $initialized: true } as any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const web3 = Web3Provider.getWeb3(config)
|
const web3 = Web3Provider.getWeb3(config)
|
||||||
|
|
||||||
let contractInstance: Contract
|
let contractInstance: ContractTest
|
||||||
try {
|
try {
|
||||||
Logger.log('Deploying', name)
|
Logger.log('Deploying', name)
|
||||||
const sendConfig = {
|
const sendConfig = {
|
||||||
from,
|
from,
|
||||||
gas: 3000000,
|
gas: 3000000,
|
||||||
gasPrice: 10000000000
|
gasPrice: '10000000000'
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line security/detect-non-literal-require
|
||||||
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(
|
const tempContract = new web3.eth.Contract(artifact.abi, artifact.address)
|
||||||
artifact.abi,
|
|
||||||
artifact.address
|
|
||||||
)
|
|
||||||
const isZos = !!tempContract.methods.initialize
|
const isZos = !!tempContract.methods.initialize
|
||||||
|
|
||||||
Logger.debug({
|
Logger.debug({
|
||||||
@ -184,13 +187,11 @@ export default class TestContractHandler extends ContractHandler {
|
|||||||
})
|
})
|
||||||
.send(sendConfig)
|
.send(sendConfig)
|
||||||
if (isZos) {
|
if (isZos) {
|
||||||
await contractInstance.methods
|
await contractInstance.methods.initialize(...args).send(sendConfig)
|
||||||
.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(
|
Logger.error(
|
||||||
'Deployment failed for',
|
'Deployment failed for',
|
||||||
|
@ -4,7 +4,7 @@ export default class BrizoMock extends Brizo {
|
|||||||
public async initializeServiceAgreement(
|
public async initializeServiceAgreement(
|
||||||
did: string,
|
did: string,
|
||||||
serviceAgreementId: string,
|
serviceAgreementId: string,
|
||||||
serviceDefinitionId: string,
|
index: number,
|
||||||
signature: string,
|
signature: string,
|
||||||
consumerPublicKey: string
|
consumerPublicKey: string
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as assert from 'assert'
|
import assert from 'assert'
|
||||||
import DID from '../../src/ocean/DID'
|
import DID from '../../src/ocean/DID'
|
||||||
|
|
||||||
describe('DID', () => {
|
describe('DID', () => {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { assert, spy, use } from 'chai'
|
import { assert, spy, use } from 'chai'
|
||||||
import * as spies from 'chai-spies'
|
import spies from 'chai-spies'
|
||||||
|
|
||||||
import { SearchQuery } from '../../src/aquarius/Aquarius'
|
|
||||||
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'
|
||||||
@ -41,33 +40,4 @@ describe('Ocean', () => {
|
|||||||
assert(typeof accs[0].getId() === 'string')
|
assert(typeof accs[0].getId() === 'string')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#searchAssets()', () => {
|
|
||||||
it('should search for assets', async () => {
|
|
||||||
const query = {
|
|
||||||
offset: 100,
|
|
||||||
page: 1,
|
|
||||||
query: {
|
|
||||||
value: 1
|
|
||||||
},
|
|
||||||
sort: {
|
|
||||||
value: 1
|
|
||||||
},
|
|
||||||
text: 'Office'
|
|
||||||
} as SearchQuery
|
|
||||||
|
|
||||||
const assets = await ocean.assets.query(query)
|
|
||||||
|
|
||||||
assert(assets)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('#searchAssetsByText()', () => {
|
|
||||||
it('should search for assets', async () => {
|
|
||||||
const text = 'office'
|
|
||||||
const assets = await ocean.assets.search(text)
|
|
||||||
|
|
||||||
assert(assets)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { assert, spy, use } from 'chai'
|
import { assert, spy, use } from 'chai'
|
||||||
import * as spies from 'chai-spies'
|
import spies from 'chai-spies'
|
||||||
|
|
||||||
import config from '../config'
|
import config from '../config'
|
||||||
import Account from '../../src/ocean/Account'
|
import Account from '../../src/ocean/Account'
|
||||||
|
48
test/ocean/OceanAssets.test.ts
Normal file
48
test/ocean/OceanAssets.test.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { assert, spy, use } from 'chai'
|
||||||
|
import spies from 'chai-spies'
|
||||||
|
|
||||||
|
import { SearchQuery } from '../../src/aquarius/Aquarius'
|
||||||
|
import { Ocean } from '../../src/ocean/Ocean'
|
||||||
|
import config from '../config'
|
||||||
|
|
||||||
|
use(spies)
|
||||||
|
|
||||||
|
let ocean: Ocean
|
||||||
|
|
||||||
|
describe('OceanAssets', () => {
|
||||||
|
before(async () => {
|
||||||
|
ocean = await Ocean.getInstance(config)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
spy.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#query()', () => {
|
||||||
|
it('should search for assets', async () => {
|
||||||
|
const query: SearchQuery = {
|
||||||
|
offset: 100,
|
||||||
|
page: 1,
|
||||||
|
query: {
|
||||||
|
text: 'Office'
|
||||||
|
},
|
||||||
|
sort: {
|
||||||
|
created: -1
|
||||||
|
}
|
||||||
|
} as SearchQuery
|
||||||
|
|
||||||
|
const assets = await ocean.assets.query(query)
|
||||||
|
|
||||||
|
assert(assets)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#search()', () => {
|
||||||
|
it('should search for assets', async () => {
|
||||||
|
const text = 'office'
|
||||||
|
const assets = await ocean.assets.search(text)
|
||||||
|
|
||||||
|
assert(assets)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -1,5 +1,5 @@
|
|||||||
import { assert, expect, spy, use } from 'chai'
|
import { assert, expect, spy, use } from 'chai'
|
||||||
import * as spies from 'chai-spies'
|
import spies from 'chai-spies'
|
||||||
|
|
||||||
import config from '../config'
|
import config from '../config'
|
||||||
import Account from '../../src/ocean/Account'
|
import Account from '../../src/ocean/Account'
|
||||||
@ -54,11 +54,7 @@ describe('OceanAuth', () => {
|
|||||||
|
|
||||||
describe('#store()', () => {
|
describe('#store()', () => {
|
||||||
it('should sign and store the token', async () => {
|
it('should sign and store the token', async () => {
|
||||||
const writeTokenSpy = spy.on(
|
const writeTokenSpy = spy.on(oceanAuth as any, 'writeToken', () => null)
|
||||||
oceanAuth as any,
|
|
||||||
'writeToken',
|
|
||||||
() => {}
|
|
||||||
)
|
|
||||||
|
|
||||||
await oceanAuth.store(account)
|
await oceanAuth.store(account)
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { assert, expect, spy, use } from 'chai'
|
import { assert, expect, spy, use } from 'chai'
|
||||||
import * as spies from 'chai-spies'
|
import spies from 'chai-spies'
|
||||||
|
|
||||||
import Account from '../../src/ocean/Account'
|
import Account from '../../src/ocean/Account'
|
||||||
import { Ocean } from '../../src/ocean/Ocean'
|
import { Ocean } from '../../src/ocean/Ocean'
|
||||||
@ -33,11 +33,7 @@ describe('OceanSecretStore', () => {
|
|||||||
() => 'encryptedResult'
|
() => 'encryptedResult'
|
||||||
)
|
)
|
||||||
|
|
||||||
const result = await oceanSecretStore.encrypt(
|
const result = await oceanSecretStore.encrypt(did, 'test', accounts[0])
|
||||||
did,
|
|
||||||
'test',
|
|
||||||
accounts[0]
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(secretStoreEncryptSpy).to.have.been.called.with(did, 'test')
|
expect(secretStoreEncryptSpy).to.have.been.called.with(did, 'test')
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { assert, expect, spy, use } from 'chai'
|
import { assert, expect, spy, use } from 'chai'
|
||||||
import * as spies from 'chai-spies'
|
import spies from 'chai-spies'
|
||||||
|
import Web3 from 'web3'
|
||||||
import config from '../../config'
|
import config from '../../config'
|
||||||
|
|
||||||
import { Ocean } from '../../../src/ocean/Ocean'
|
import { Ocean } from '../../../src/ocean/Ocean'
|
||||||
@ -11,7 +11,7 @@ describe('SignatureUtils', () => {
|
|||||||
const publicKey = `0x${'a'.repeat(40)}`
|
const publicKey = `0x${'a'.repeat(40)}`
|
||||||
const text = '0123456789abcde'
|
const text = '0123456789abcde'
|
||||||
const signature = `0x${'a'.repeat(130)}`
|
const signature = `0x${'a'.repeat(130)}`
|
||||||
let web3
|
let web3: Web3
|
||||||
let ocean: Ocean
|
let ocean: Ocean
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
@ -38,18 +38,10 @@ describe('SignatureUtils', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should sign a text as expected using password', async () => {
|
it('should sign a text as expected using password', async () => {
|
||||||
const signed = await ocean.utils.signature.signText(
|
const signed = await ocean.utils.signature.signText(text, publicKey, 'test')
|
||||||
text,
|
|
||||||
publicKey,
|
|
||||||
'test'
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.equal(signed, signature)
|
assert.equal(signed, signature)
|
||||||
expect(personalSignSpy).to.have.been.called.with(
|
expect(personalSignSpy).to.have.been.called.with(text, publicKey, 'test')
|
||||||
text,
|
|
||||||
publicKey,
|
|
||||||
'test'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
69
test/testdata/ddo.json
vendored
69
test/testdata/ddo.json
vendored
@ -39,8 +39,8 @@
|
|||||||
},
|
},
|
||||||
"service": [
|
"service": [
|
||||||
{
|
{
|
||||||
"type": "Access",
|
"type": "access",
|
||||||
"serviceDefinitionId": "0",
|
"index": 0,
|
||||||
"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}",
|
||||||
"purchaseEndpoint": "http://mybrizo.org/api/v1/brizo/services/access/purchase?",
|
"purchaseEndpoint": "http://mybrizo.org/api/v1/brizo/services/access/purchase?",
|
||||||
"templateId": "044852b2a670ade5407e78fb2863c51000000000000000000000000000000000",
|
"templateId": "044852b2a670ade5407e78fb2863c51000000000000000000000000000000000",
|
||||||
@ -58,9 +58,7 @@
|
|||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
"PaymentLocked": {
|
"PaymentLocked": {
|
||||||
"actorType": [
|
"actorType": ["publisher"],
|
||||||
"publisher"
|
|
||||||
],
|
|
||||||
"handlers": [
|
"handlers": [
|
||||||
{
|
{
|
||||||
"moduleName": "accessControl",
|
"moduleName": "accessControl",
|
||||||
@ -84,9 +82,7 @@
|
|||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
"PaymentReleased": {
|
"PaymentReleased": {
|
||||||
"actorType": [
|
"actorType": ["publisher"],
|
||||||
"publisher"
|
|
||||||
],
|
|
||||||
"handlers": [
|
"handlers": [
|
||||||
{
|
{
|
||||||
"moduleName": "serviceAgreement",
|
"moduleName": "serviceAgreement",
|
||||||
@ -110,9 +106,7 @@
|
|||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
"AccessGranted": {
|
"AccessGranted": {
|
||||||
"actorType": [
|
"actorType": ["consumer"],
|
||||||
"consumer"
|
|
||||||
],
|
|
||||||
"handlers": [
|
"handlers": [
|
||||||
{
|
{
|
||||||
"moduleName": "asset",
|
"moduleName": "asset",
|
||||||
@ -136,9 +130,7 @@
|
|||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
"PaymentRefund": {
|
"PaymentRefund": {
|
||||||
"actorType": [
|
"actorType": ["consumer"],
|
||||||
"consumer"
|
|
||||||
],
|
|
||||||
"handlers": [
|
"handlers": [
|
||||||
{
|
{
|
||||||
"moduleName": "serviceAgreement",
|
"moduleName": "serviceAgreement",
|
||||||
@ -152,39 +144,44 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "CloudCompute",
|
"type": "compute",
|
||||||
"serviceDefinitionId": "1",
|
"index": 1,
|
||||||
"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}",
|
||||||
"templateId": "044852b2a670ade5407e78fb2863c51000000000000000000000000000000002"
|
"templateId": "044852b2a670ade5407e78fb2863c51000000000000000000000000000000002"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Metadata",
|
"type": "metadata",
|
||||||
"serviceDefinitionId": "2",
|
"index": 2,
|
||||||
"serviceEndpoint": "http://myaquarius.org/api/v1/provider/assets/metadata/{did}",
|
"serviceEndpoint": "http://myaquarius.org/api/v1/provider/assets/metadata/{did}",
|
||||||
"metadata": {
|
"attributes": {
|
||||||
"base": {
|
"main": {
|
||||||
"name": "UK Weather information 2011",
|
"name": "UK Weather information 2011",
|
||||||
"type": "dataset",
|
"type": "dataset",
|
||||||
"description": "Weather information of UK including temperature and humidity",
|
|
||||||
"dateCreated": "2012-10-10T17:00:000Z",
|
"dateCreated": "2012-10-10T17:00:000Z",
|
||||||
"author": "Met Office",
|
"author": "Met Office",
|
||||||
"license": "CC-BY",
|
"license": "CC-BY",
|
||||||
"copyrightHolder": "Met Office",
|
"price": 10,
|
||||||
"workExample": "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68",
|
|
||||||
"contentUrls": [
|
|
||||||
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip"
|
|
||||||
],
|
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"index": 0,
|
"index": 0,
|
||||||
"url": "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip",
|
"url": "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip",
|
||||||
"checksum": "085340abffh21495345af97c6b0e761",
|
"checksum": "085340abffh21495345af97c6b0e761",
|
||||||
"contentLength": 12324
|
"contentLength": "12324"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://testocnfiles.blob.core.windows.net/testfiles/testzkp2.zip"
|
"url": "https://testocnfiles.blob.core.windows.net/testfiles/testzkp2.zip"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
|
},
|
||||||
|
"curation": {
|
||||||
|
"rating": 0.93,
|
||||||
|
"numVotes": 123,
|
||||||
|
"schema": "Binary Voting"
|
||||||
|
},
|
||||||
|
"additionalInformation": {
|
||||||
|
"description": "Weather information of UK including temperature and humidity",
|
||||||
|
"copyrightHolder": "Met Office",
|
||||||
|
"workExample": "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68",
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"name": "Sample of Asset Data",
|
"name": "Sample of Asset Data",
|
||||||
@ -200,14 +197,6 @@
|
|||||||
"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": 10
|
|
||||||
},
|
|
||||||
"curation": {
|
|
||||||
"rating": 0.93,
|
|
||||||
"numVotes": 123,
|
|
||||||
"schema": "Binary Voting"
|
|
||||||
},
|
|
||||||
"additionalInformation": {
|
|
||||||
"updateFrequency": "yearly",
|
"updateFrequency": "yearly",
|
||||||
"structuredMarkup": [
|
"structuredMarkup": [
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"lib": ["es6", "es7"],
|
"lib": ["es6", "es7"],
|
||||||
"noUnusedLocals": true
|
"noUnusedLocals": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { assert, expect, spy, use } from 'chai'
|
import { assert, expect, spy, use } from 'chai'
|
||||||
import * as spies from 'chai-spies'
|
import spies from 'chai-spies'
|
||||||
|
|
||||||
import { SubscribableObserver } from '../../src/utils/SubscribableObserver'
|
import { SubscribableObserver } from '../../src/utils/SubscribableObserver'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { assert, expect, spy, use } from 'chai'
|
import { assert, expect, spy, use } from 'chai'
|
||||||
import * as spies from 'chai-spies'
|
import spies from 'chai-spies'
|
||||||
|
|
||||||
import { SubscribablePromise } from '../../src/utils/SubscribablePromise'
|
import { SubscribablePromise } from '../../src/utils/SubscribablePromise'
|
||||||
|
|
||||||
@ -7,15 +7,15 @@ use(spies)
|
|||||||
|
|
||||||
describe('SubscribablePromise', () => {
|
describe('SubscribablePromise', () => {
|
||||||
it('should work', async () => {
|
it('should work', async () => {
|
||||||
const subscribible = new SubscribablePromise(() => {})
|
const subscribable = new SubscribablePromise(() => null)
|
||||||
|
|
||||||
assert.isDefined(subscribible)
|
assert.isDefined(subscribable)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#subscribe()', () => {
|
describe('#subscribe()', () => {
|
||||||
it('should return a subscription', async () => {
|
it('should return a subscription', async () => {
|
||||||
const subscribible = new SubscribablePromise(() => {})
|
const subscribable = new SubscribablePromise(() => null)
|
||||||
const subscription = subscribible.subscribe(() => {})
|
const subscription = subscribable.subscribe(() => null)
|
||||||
|
|
||||||
assert.isDefined(subscription)
|
assert.isDefined(subscription)
|
||||||
assert.isDefined(subscription.unsubscribe)
|
assert.isDefined(subscription.unsubscribe)
|
||||||
@ -24,11 +24,11 @@ describe('SubscribablePromise', () => {
|
|||||||
|
|
||||||
it('should listen the next values', done => {
|
it('should listen the next values', done => {
|
||||||
const onNextSpy = spy()
|
const onNextSpy = spy()
|
||||||
const subscribible = new SubscribablePromise(observer => {
|
const subscribable = new SubscribablePromise(observer => {
|
||||||
setTimeout(() => observer.next('test'), 10)
|
setTimeout(() => observer.next('test'), 10)
|
||||||
setTimeout(() => observer.next('test'), 20)
|
setTimeout(() => observer.next('test'), 20)
|
||||||
})
|
})
|
||||||
subscribible.subscribe(onNextSpy)
|
subscribable.subscribe(onNextSpy)
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
expect(onNextSpy).to.has.been.called.with('test')
|
expect(onNextSpy).to.has.been.called.with('test')
|
||||||
@ -42,12 +42,12 @@ describe('SubscribablePromise', () => {
|
|||||||
it('should resolve', done => {
|
it('should resolve', done => {
|
||||||
const onCompleteSpy = spy()
|
const onCompleteSpy = spy()
|
||||||
const onFinallySpy = spy()
|
const onFinallySpy = spy()
|
||||||
const subscribible = new SubscribablePromise(observer => {
|
const subscribable = new SubscribablePromise(observer => {
|
||||||
setTimeout(() => observer.next('test'), 10)
|
setTimeout(() => observer.next('test'), 10)
|
||||||
setTimeout(() => observer.complete('test'), 20)
|
setTimeout(() => observer.complete('test'), 20)
|
||||||
})
|
})
|
||||||
|
|
||||||
subscribible.then(onCompleteSpy).finally(onFinallySpy)
|
subscribable.then(onCompleteSpy).finally(onFinallySpy)
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
expect(onCompleteSpy).to.has.been.called.with('test')
|
expect(onCompleteSpy).to.has.been.called.with('test')
|
||||||
@ -62,12 +62,12 @@ describe('SubscribablePromise', () => {
|
|||||||
it('should catch the error', done => {
|
it('should catch the error', done => {
|
||||||
const onErrorSpy = spy()
|
const onErrorSpy = spy()
|
||||||
const onFinallySpy = spy()
|
const onFinallySpy = spy()
|
||||||
const subscribible = new SubscribablePromise(observer => {
|
const subscribable = new SubscribablePromise(observer => {
|
||||||
setTimeout(() => observer.next('test'), 10)
|
setTimeout(() => observer.next('test'), 10)
|
||||||
setTimeout(() => observer.error('test'), 20)
|
setTimeout(() => observer.error('test'), 20)
|
||||||
})
|
})
|
||||||
|
|
||||||
subscribible.catch(onErrorSpy).finally(onFinallySpy)
|
subscribable.catch(onErrorSpy).finally(onFinallySpy)
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
expect(onErrorSpy).to.has.been.called.with('test')
|
expect(onErrorSpy).to.has.been.called.with('test')
|
||||||
@ -80,13 +80,13 @@ describe('SubscribablePromise', () => {
|
|||||||
|
|
||||||
it('should be able to subscribe and wait for a promise', async () => {
|
it('should be able to subscribe and wait for a promise', async () => {
|
||||||
const onNextSpy = spy()
|
const onNextSpy = spy()
|
||||||
const subscribible = new SubscribablePromise(observer => {
|
const subscribable = new SubscribablePromise(observer => {
|
||||||
setTimeout(() => observer.next('test'), 10)
|
setTimeout(() => observer.next('test'), 10)
|
||||||
setTimeout(() => observer.next('test'), 20)
|
setTimeout(() => observer.next('test'), 20)
|
||||||
setTimeout(() => observer.complete('completed'), 30)
|
setTimeout(() => observer.complete('completed'), 30)
|
||||||
})
|
})
|
||||||
|
|
||||||
const result = await subscribible.next(onNextSpy)
|
const result = await subscribable.next(onNextSpy)
|
||||||
|
|
||||||
expect(onNextSpy).to.has.been.called.with('test')
|
expect(onNextSpy).to.has.been.called.with('test')
|
||||||
expect(onNextSpy).to.has.been.called.exactly(2)
|
expect(onNextSpy).to.has.been.called.exactly(2)
|
||||||
@ -96,7 +96,7 @@ describe('SubscribablePromise', () => {
|
|||||||
|
|
||||||
it('should use the result of a the promise as executor to complete the observer', async () => {
|
it('should use the result of a the promise as executor to complete the observer', async () => {
|
||||||
const onNextSpy = spy()
|
const onNextSpy = spy()
|
||||||
const subscribible = new SubscribablePromise(async observer => {
|
const subscribable = new SubscribablePromise(async observer => {
|
||||||
await new Promise(resolve => setTimeout(resolve, 10))
|
await new Promise(resolve => setTimeout(resolve, 10))
|
||||||
observer.next('test')
|
observer.next('test')
|
||||||
await new Promise(resolve => setTimeout(resolve, 10))
|
await new Promise(resolve => setTimeout(resolve, 10))
|
||||||
@ -105,7 +105,7 @@ describe('SubscribablePromise', () => {
|
|||||||
return 'completed'
|
return 'completed'
|
||||||
})
|
})
|
||||||
|
|
||||||
const result = await subscribible.next(onNextSpy)
|
const result = await subscribable.next(onNextSpy)
|
||||||
|
|
||||||
expect(onNextSpy).to.has.been.called.with('test')
|
expect(onNextSpy).to.has.been.called.with('test')
|
||||||
expect(onNextSpy).to.has.been.called.exactly(2)
|
expect(onNextSpy).to.has.been.called.exactly(2)
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
"lib": ["es2017", "es6", "es7", "dom"],
|
"lib": ["es2017", "es6", "es7", "dom"],
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
Loading…
Reference in New Issue
Block a user