Merge pull request #354 from oceanprotocol/decouple-aquarius-from-ocean

Decouple aquarius from ocean
This commit is contained in:
pfmescher 2020-01-23 09:17:23 +01:00 committed by GitHub
commit 1862913f1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 108 additions and 43 deletions

View File

@ -73,6 +73,19 @@ const ocean: Ocean = await Ocean.getInstance({
For an overview of endpoint configurations making up various Ocean networks, please refer to [`.env.local.example`](https://github.com/oceanprotocol/commons/blob/master/client/.env.local.example) from commons.
Optionally, you can initialize an Aquarius connection without relying on the rest of Ocean to be loaded. This is useful for outputting asset metadata stored in Aquarius without the need to configure Web3 and all other Ocean Protocol network connections.
```js
import { Ocean, Aquarius, Logger } from 'squid'
const aquarius = new Aquarius('http://localhost:5000', Logger)
const asset = aquarius.retrieveDDO('did:op:e6fda48e8d814d5d9655645aac3c046cc87528dbc1a9449799e579d7b83d1360')
const ocean = await Ocean.getInstance({ ... })
// Aquarius will still be available under ocean.aquarius, just later
const asset = ocean.aquarius.retrieveDDO('did:op:e6fda48e8d814d5d9655645aac3c046cc87528dbc1a9449799e579d7b83d1360')
```
### Examples
You can see how `squid-js` is used on:

View File

@ -1,7 +1,8 @@
import { URL } from 'whatwg-url'
import { DDO } from '../ddo/DDO'
import DID from '../ocean/DID'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import { Logger } from '../utils'
import { WebServiceConnector } from '../ocean/utils/WebServiceConnector'
const apiPath = '/api/v1/aquarius/assets/ddo'
@ -21,25 +22,35 @@ export interface SearchQuery {
}
/**
* Provides a interface with Aquarius.
* Provides an interface with Aquarius.
* Aquarius provides an off-chain database store for metadata about data assets.
*/
export class Aquarius extends Instantiable {
export class Aquarius {
public fetch: WebServiceConnector
private logger: Logger
private aquariusUri: string
private get url() {
return this.config.aquariusUri
return this.aquariusUri
}
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
/**
* Instantiate Aquarius (independently of Ocean) for off-chain interaction.
* @param {String} aquariusUri
* @param {Logger} logger
*/
constructor(aquariusUri: string, logger: Logger) {
this.fetch = new WebServiceConnector(logger)
this.logger = logger
this.aquariusUri = aquariusUri
}
public async getVersionInfo() {
return (await this.ocean.utils.fetch.get(this.url)).json()
return (await this.fetch.get(this.url)).json()
}
public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
const accessUrl: string = await this.ocean.utils.fetch
const accessUrl: string = await this.fetch
.post(`${accessToken.service_endpoint}/${accessToken.resource_id}`, payload)
.then((response: any): string => {
if (response.ok) {
@ -69,7 +80,7 @@ export class Aquarius extends Instantiable {
* @return {Promise<QueryResult>}
*/
public async queryMetadata(query: SearchQuery): Promise<QueryResult> {
const result: QueryResult = await this.ocean.utils.fetch
const result: QueryResult = await this.fetch
.post(`${this.url}${apiPath}/query`, JSON.stringify(query))
.then((response: any) => {
if (response.ok) {
@ -107,7 +118,8 @@ export class Aquarius extends Instantiable {
)
fullUrl.searchParams.append('offset', query.offset.toString())
fullUrl.searchParams.append('page', query.page.toString())
const result: QueryResult = await this.ocean.utils.fetch
const result: QueryResult = await this.fetch
.get(fullUrl)
.then((response: any) => {
if (response.ok) {
@ -138,7 +150,7 @@ export class Aquarius extends Instantiable {
*/
public async storeDDO(ddo: DDO): Promise<DDO> {
const fullUrl = `${this.url}${apiPath}`
const result: DDO = await this.ocean.utils.fetch
const result: DDO = await this.fetch
.post(fullUrl, DDO.serialize(ddo))
.then((response: any) => {
if (response.ok) {
@ -174,7 +186,7 @@ export class Aquarius extends Instantiable {
): Promise<DDO> {
did = did && DID.parse(did)
const fullUrl = metadataServiceEndpoint || `${this.url}${apiPath}/${did.getDid()}`
const result = await this.ocean.utils.fetch
const result = await this.fetch
.get(fullUrl)
.then((response: any) => {
if (response.ok) {

View File

@ -37,10 +37,14 @@ export class Ocean extends Instantiable {
}
instance.setInstanceConfig(instanceConfig)
instance.utils = await OceanUtils.getInstance(instanceConfig)
instance.keeper = await Keeper.getInstance(instanceConfig)
instance.brizo = new Brizo(instanceConfig)
instance.aquarius = new Aquarius(instanceConfig)
instance.aquarius = new Aquarius(
instanceConfig.config.aquariusUri,
instanceConfig.logger
)
instance.accounts = await OceanAccounts.getInstance(instanceConfig)
instance.auth = await OceanAuth.getInstance(instanceConfig)
@ -50,8 +54,6 @@ export class Ocean extends Instantiable {
instance.tokens = await OceanTokens.getInstance(instanceConfig)
instance.versions = await OceanVersions.getInstance(instanceConfig)
instance.utils = await OceanUtils.getInstance(instanceConfig)
return instance
}

View File

@ -16,9 +16,13 @@ export class OceanUtils extends Instantiable {
const instance = new OceanUtils()
instance.setInstanceConfig(config)
instance.agreements = new ServiceAgreement(config)
instance.signature = new SignatureUtils(config)
instance.fetch = new WebServiceConnector(config)
instance.agreements = new ServiceAgreement(
config.ocean,
config.logger,
config.web3
)
instance.signature = new SignatureUtils(config.web3, config.logger)
instance.fetch = new WebServiceConnector(config.logger)
return instance
}

View File

@ -2,13 +2,18 @@ import { ServiceAgreementTemplateCondition } from '../../ddo/ServiceAgreementTem
import { DDO } from '../../ddo/DDO'
import { ServiceAccess } from '../../ddo/Service'
import Account from '../Account'
import { zeroX } from '../../utils'
import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
import { zeroX, Logger } from '../../utils'
import { Ocean } from '../../squid'
import Web3 from 'web3'
export class ServiceAgreement extends Instantiable {
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
export class ServiceAgreement {
private ocean: Ocean
private logger: Logger
private web3: Web3
constructor(ocean: Ocean, logger: Logger, web3: Web3) {
this.ocean = ocean
this.logger = logger
this.web3 = web3
}
public async signServiceAgreement(

View File

@ -1,9 +1,13 @@
import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
import Web3 from 'web3'
import { Logger } from '../../utils'
export class SignatureUtils extends Instantiable {
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
export class SignatureUtils {
private web3: Web3
private logger: Logger
constructor(web3: Web3, logger: Logger) {
this.web3 = web3
this.logger = logger
}
public async signText(

View File

@ -1,6 +1,6 @@
import { BodyInit, RequestInit, Response } from 'node-fetch'
import fs from 'fs'
import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
import { Logger } from '../../utils'
const fetch = require('node-fetch')
import save = require('save-file')
@ -8,10 +8,10 @@ import save = require('save-file')
/**
* Provides a common interface to web services.
*/
export class WebServiceConnector extends Instantiable {
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
export class WebServiceConnector {
public logger: Logger
constructor(logger: Logger) {
this.logger = logger
}
public post(url: string, payload: BodyInit): Promise<Response> {

View File

@ -4,6 +4,7 @@ import DID from './ocean/DID'
import { Ocean } from './ocean/Ocean'
import { LoggerInstance as Logger } from './utils/Logger'
import Keeper from './keeper/Keeper'
import { Aquarius } from './aquarius/Aquarius'
import * as templates from './keeper/contracts/templates'
import * as conditions from './keeper/contracts/conditions'
@ -23,4 +24,15 @@ export {
export { Condition, ConditionState } from './keeper/contracts/conditions'
export { Ocean, Account, Config, DID, Logger, Keeper, conditions, templates, utils }
export {
Ocean,
Account,
Config,
DID,
Logger,
Keeper,
Aquarius,
conditions,
templates,
utils
}

View File

@ -5,6 +5,7 @@ import { Aquarius, SearchQuery } from '../../src/aquarius/Aquarius'
import { DDO } from '../../src/ddo/DDO'
import DID from '../../src/ocean/DID'
import config from '../config'
import { LoggerInstance } from '../../src/utils'
use(spies)
@ -53,7 +54,7 @@ describe('Aquarius', () => {
} as SearchQuery
it('should query metadata', async () => {
spy.on(ocean.utils.fetch, 'post', () => reponsify(getResults([new DDO()])))
spy.on(aquarius.fetch, 'post', () => reponsify(getResults([new DDO()])))
const result = await aquarius.queryMetadata(query)
assert.typeOf(result.results, 'array')
@ -64,7 +65,7 @@ describe('Aquarius', () => {
})
it('should query metadata and return real ddo', async () => {
spy.on(ocean.utils.fetch, 'post', () => reponsify(getResults([new DDO()])))
spy.on(aquarius.fetch, 'post', () => reponsify(getResults([new DDO()])))
const result = await aquarius.queryMetadata(query)
assert.typeOf(result.results, 'array')
@ -87,7 +88,7 @@ describe('Aquarius', () => {
} as SearchQuery
it('should query metadata by text', async () => {
spy.on(ocean.utils.fetch, 'get', () => reponsify(getResults([new DDO()])))
spy.on(aquarius.fetch, 'get', () => reponsify(getResults([new DDO()])))
const result = await aquarius.queryMetadataByText(query)
assert.typeOf(result.results, 'array')
@ -97,8 +98,20 @@ describe('Aquarius', () => {
assert.equal(result.totalResults, 1)
})
it('should query metadata by text with a new instance', async () => {
const aquariusNew = new Aquarius(config.aquariusUri, LoggerInstance)
spy.on(aquariusNew.fetch, 'get', () => reponsify(getResults([new DDO()])))
const result = await aquariusNew.queryMetadataByText(query)
assert.typeOf(result.results, 'array')
assert.lengthOf(result.results, 1)
assert.equal(result.page, 0)
assert.equal(result.totalPages, 1)
assert.equal(result.totalResults, 1)
})
it('should query metadata and return real ddo', async () => {
spy.on(ocean.utils.fetch, 'get', () => reponsify(getResults([new DDO()])))
spy.on(aquarius.fetch, 'get', () => reponsify(getResults([new DDO()])))
const result = await aquarius.queryMetadataByText(query)
assert.typeOf(result.results, 'array')
@ -114,7 +127,7 @@ describe('Aquarius', () => {
id: did.getId()
})
spy.on(ocean.utils.fetch, 'post', () => reponsify(ddo))
spy.on(aquarius.fetch, 'post', () => reponsify(ddo))
const result: DDO = await aquarius.storeDDO(ddo)
assert(result)
@ -129,8 +142,8 @@ describe('Aquarius', () => {
id: did.getId()
})
spy.on(ocean.utils.fetch, 'post', () => reponsify(ddo))
spy.on(ocean.utils.fetch, 'get', () => reponsify(ddo))
spy.on(aquarius.fetch, 'post', () => reponsify(ddo))
spy.on(aquarius.fetch, 'get', () => reponsify(ddo))
const storageResult: DDO = await aquarius.storeDDO(ddo)
assert(storageResult)