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

Be able to create different Ocean instances with different config.

This commit is contained in:
Pedro Gutiérrez 2019-03-21 02:56:58 +01:00 committed by Pedro Gutiérrez
parent ea16729d86
commit 7a13ad8daa
68 changed files with 898 additions and 1147 deletions

View File

@ -1,34 +0,0 @@
import Config from "./models/Config"
import LoggerInstance, { LogLevel } from "./utils/Logger"
/**
* Stores the configuration of the library.
*/
export default class ConfigProvider {
/**
* @return {Config} Library config.
*/
public static getConfig(): Config {
return ConfigProvider.config
}
/**
* @param {Config} Library config.
*/
public static setConfig(config: Config) {
LoggerInstance.setLevel(
typeof config.verbose !== "number"
? (config.verbose ? LogLevel.Log : LogLevel.None)
: config.verbose as LogLevel,
)
ConfigProvider.config = config
}
/**
* Library config.
* @type {Config}
*/
private static config: Config
}

View File

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

View File

@ -1,10 +1,9 @@
import { URL } from "whatwg-url" import { URL } from "whatwg-url"
import { DDO } from "../ddo/DDO" import { DDO } from "../ddo/DDO"
import Config from "../models/Config"
import DID from "../ocean/DID" import DID from "../ocean/DID"
import LoggerInstance from "../utils/Logger"
import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider" import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider"
import { SearchQuery } from "./query/SearchQuery" import { SearchQuery } from "./query/SearchQuery"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
const apiPath = "/api/v1/aquarius/assets/ddo" const apiPath = "/api/v1/aquarius/assets/ddo"
@ -12,11 +11,14 @@ const apiPath = "/api/v1/aquarius/assets/ddo"
* Provides a interface with Aquarius. * Provides a interface with Aquarius.
* Aquarius provides an off-chain database store for metadata about data assets. * Aquarius provides an off-chain database store for metadata about data assets.
*/ */
export default class Aquarius { export class Aquarius extends Instantiable {
private url: string private get url() {
return this.config.aquariusUri
}
constructor(config: Config) { constructor(config: InstantiableConfig) {
this.url = config.aquariusUri super()
this.setInstanceConfig(config)
} }
public async getAccessUrl(accessToken: any, payload: any): Promise<string> { public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
@ -26,15 +28,15 @@ export default class Aquarius {
if (response.ok) { if (response.ok) {
return response.text() return response.text()
} }
LoggerInstance.error("Failed: ", response.status, response.statusText) this.logger.error("Failed: ", response.status, response.statusText)
return null return null
}) })
.then((consumptionUrl: string): string => { .then((consumptionUrl: string): string => {
LoggerInstance.error("Success accessing consume endpoint: ", consumptionUrl) this.logger.error("Success accessing consume endpoint: ", consumptionUrl)
return consumptionUrl return consumptionUrl
}) })
.catch((error) => { .catch((error) => {
LoggerInstance.error("Error fetching the data asset consumption url: ", error) this.logger.error("Error fetching the data asset consumption url: ", error)
return null return null
}) })
@ -53,7 +55,7 @@ export default class Aquarius {
if (response.ok) { if (response.ok) {
return response.json() as DDO[] return response.json() as DDO[]
} }
LoggerInstance.error("queryMetadata failed:", response.status, response.statusText) this.logger.error("queryMetadata failed:", response.status, response.statusText)
return [] as DDO[] return [] as DDO[]
}) })
.then((ddos) => { .then((ddos) => {
@ -62,7 +64,7 @@ export default class Aquarius {
}) })
}) })
.catch((error) => { .catch((error) => {
LoggerInstance.error("Error fetching querying metadata: ", error) this.logger.error("Error fetching querying metadata: ", error)
return [] as DDO[] return [] as DDO[]
}) })
@ -86,7 +88,7 @@ export default class Aquarius {
if (response.ok) { if (response.ok) {
return response.json() as DDO[] return response.json() as DDO[]
} }
LoggerInstance.log("queryMetadataByText failed:", response.status, response.statusText) this.logger.log("queryMetadataByText failed:", response.status, response.statusText)
return [] as DDO[] return [] as DDO[]
}) })
.then((ddos) => { .then((ddos) => {
@ -95,7 +97,7 @@ export default class Aquarius {
}) })
}) })
.catch((error) => { .catch((error) => {
LoggerInstance.error("Error fetching querying metadata by text: ", error) this.logger.error("Error fetching querying metadata by text: ", error)
return [] as DDO[] return [] as DDO[]
}) })
@ -115,14 +117,14 @@ export default class Aquarius {
if (response.ok) { if (response.ok) {
return response.json() return response.json()
} }
LoggerInstance.error("storeDDO failed:", response.status, response.statusText, ddo) this.logger.error("storeDDO failed:", response.status, response.statusText, ddo)
return null as DDO return null as DDO
}) })
.then((response: DDO) => { .then((response: DDO) => {
return new DDO(response) as DDO return new DDO(response) as DDO
}) })
.catch((error) => { .catch((error) => {
LoggerInstance.error("Error fetching querying metadata: ", error) this.logger.error("Error fetching querying metadata: ", error)
return null as DDO return null as DDO
}) })
@ -142,14 +144,14 @@ export default class Aquarius {
if (response.ok) { if (response.ok) {
return response.json() return response.json()
} }
LoggerInstance.log("retrieveDDO failed:", response.status, response.statusText, did) this.logger.log("retrieveDDO failed:", response.status, response.statusText, did)
return null as DDO return null as DDO
}) })
.then((response: DDO) => { .then((response: DDO) => {
return new DDO(response) as DDO return new DDO(response) as DDO
}) })
.catch((error) => { .catch((error) => {
LoggerInstance.error("Error fetching querying metadata: ", error) this.logger.error("Error fetching querying metadata: ", error)
return null as DDO return null as DDO
}) })

View File

@ -1,33 +0,0 @@
import ConfigProvider from "../ConfigProvider"
import Aquarius from "./Aquarius"
/**
* Provides the Aquarius instance.
*/
export default class AquariusProvider {
/**
* Set an Aquarius instance.
* @param {Aquarius} aquarius New Aquarius instance.
*/
public static setAquarius(aquarius: Aquarius) {
AquariusProvider.aquarius = aquarius
}
/**
* Returns Acuarius instance. It creates a new one if it's not defined.
* @returns {Aquarius} Aquarius instance.
*/
public static getAquarius() {
if (!AquariusProvider.aquarius) {
AquariusProvider.aquarius = new Aquarius(ConfigProvider.getConfig())
}
return AquariusProvider.aquarius
}
/**
* Aquarius instance.
* @type {Aquarius}
*/
private static aquarius: Aquarius = null
}

View File

@ -1,9 +1,8 @@
import save = require("save-file") import save = require("save-file")
import { File } from "../ddo/MetaData" import { File } from "../ddo/MetaData"
import Config from "../models/Config"
import Account from "../ocean/Account" import Account from "../ocean/Account"
import LoggerInstance from "../utils/Logger"
import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider" import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
const apiPath = "/api/v1/brizo/services" const apiPath = "/api/v1/brizo/services"
@ -11,11 +10,14 @@ const apiPath = "/api/v1/brizo/services"
* Provides a interface with Brizo. * Provides a interface with Brizo.
* Brizo is the technical component executed by the Publishers allowing to them to provide extended data services. * Brizo is the technical component executed by the Publishers allowing to them to provide extended data services.
*/ */
export default class Brizo { export class Brizo extends Instantiable {
private url: string private get url() {
return this.config.brizoUri
}
constructor(config: Config) { constructor(config: InstantiableConfig) {
this.url = config.brizoUri super()
this.setInstanceConfig(config)
} }
public getPurchaseEndpoint() { public getPurchaseEndpoint() {
@ -55,7 +57,7 @@ export default class Brizo {
decodeURI(JSON.stringify(args)), decodeURI(JSON.stringify(args)),
) )
} catch (e) { } catch (e) {
LoggerInstance.error(e) this.logger.error(e)
throw new Error("HTTP request failed") throw new Error("HTTP request failed")
} }
} }
@ -81,8 +83,8 @@ export default class Brizo {
destination, destination,
) )
} catch (e) { } catch (e) {
LoggerInstance.error("Error consuming assets") this.logger.error("Error consuming assets")
LoggerInstance.error(e) this.logger.error(e)
throw new Error("Error consuming assets") throw new Error("Error consuming assets")
} }
}) })

View File

@ -1,33 +0,0 @@
import ConfigProvider from "../ConfigProvider"
import Brizo from "./Brizo"
/**
* Provides the Brizo instance.
*/
export default class BrizoProvider {
/**
* Set an Brizo instance.
* @param {Brizo} brizo New Brizo instance.
*/
public static setBrizo(brizo: Brizo) {
BrizoProvider.brizo = brizo
}
/**
* Returns Acuarius instance. It creates a new one if it's not defined.
* @returns {Brizo} brizo instance.
*/
public static getBrizo() {
if (!BrizoProvider.brizo) {
BrizoProvider.brizo = new Brizo(ConfigProvider.getConfig())
}
return BrizoProvider.brizo
}
/**
* Brizo instance.
* @type {Brizo}
*/
private static brizo: Brizo = null
}

View File

@ -1,3 +1,4 @@
import * as Web3 from "web3"
import Web3Provider from "../keeper/Web3Provider" import Web3Provider from "../keeper/Web3Provider"
import LoggerInstance from "../utils/Logger" import LoggerInstance from "../utils/Logger"
import * as signatureHelpers from "../utils/SignatureHelpers" import * as signatureHelpers from "../utils/SignatureHelpers"
@ -88,7 +89,6 @@ export class DDO {
* @return {string[]} DDO checksum. * @return {string[]} DDO checksum.
*/ */
public getChecksum(): string { public getChecksum(): string {
const web3 = Web3Provider.getWeb3()
const {metadata} = this.findServiceByType("Metadata") const {metadata} = this.findServiceByType("Metadata")
const {files, name, author, license} = metadata.base const {files, name, author, license} = metadata.base
@ -102,19 +102,20 @@ export class DDO {
this.id, this.id,
] ]
return web3.utils.sha3(values.join("")).replace(/^0x([a-f0-9]{32}).+$/i, "$1") return Web3Provider.getWeb3().utils.sha3(values.join("")).replace(/^0x([a-f0-9]{32}).+$/i, "$1")
} }
/** /**
* Generates proof using personal sing. * Generates proof using personal sing.
* @param {Web3} web3 Web3 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 requirted.
* @return {Promise<Proof>} Proof object. * @return {Promise<Proof>} Proof object.
*/ */
public async generateProof(publicKey: string, password?: string): Promise<Proof> { public async generateProof(web3: Web3, publicKey: string, password?: string): Promise<Proof> {
const checksum = this.getChecksum() const checksum = this.getChecksum()
const signature = await signatureHelpers.signText(checksum, publicKey, password) const signature = await signatureHelpers.signText(web3, checksum, publicKey, password)
return { return {
created: (new Date()).toISOString(), created: (new Date()).toISOString(),
@ -138,14 +139,15 @@ export class DDO {
/** /**
* 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 {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 requirted.
* @return {Promise<Proof>} Proof object. * @return {Promise<Proof>} Proof object.
*/ */
public async addProof(publicKey: string, password?: string): Promise<void> { public async addProof(web3: Web3, publicKey: string, password?: string): Promise<void> {
if (this.proof) { if (this.proof) {
throw new Error("Proof already exists") throw new Error("Proof already exists")
} }
this.proof = await this.generateProof(publicKey, password) this.proof = await this.generateProof(web3, publicKey, password)
} }
} }

View File

@ -0,0 +1,49 @@
import ContractBase from "./contracts/ContractBase"
interface EventEmitter {
subscribe: Function
unsubscribe: Function
}
export interface ContractEventSubscription {
unsubscribe: Function
}
export class ContractEvent {
constructor(
private eventEmitter: EventEmitter,
private contract: ContractBase,
private eventName: string,
private filter: {[key: string]: any},
) { }
subscribe(callback: (events: any[]) => void): ContractEventSubscription {
const onEvent = async blockNumber => {
const events = await this.contract.getEventData(this.eventName, {
filter: this.filter,
fromBlock: blockNumber,
toBlock: "latest",
})
if (events.length) {
callback(events)
}
}
this.eventEmitter.subscribe(onEvent)
return {
unsubscribe: () => this.eventEmitter.unsubscribe(onEvent),
}
}
once(callback?: (events: any[]) => void) {
return new Promise(resolve => {
const subscription = this.subscribe(events => {
subscription.unsubscribe()
if (callback) {
callback(events)
}
resolve(events)
})
})
}
}

View File

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

View File

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

View File

@ -1,61 +0,0 @@
import LoggerInstance from "../utils/Logger"
import GenericContract from "./contracts/GenericContract"
import EventListener from "./EventListener"
import Web3Provider from "./Web3Provider"
export default class Event {
private poller = null
private lastBlock: number = 0
private interval: number = 200
constructor(private contractName: string,
private eventName: string,
private filter: any) {
}
public stopListen() {
clearInterval(this.poller)
this.poller = null
}
public async listen(callback: any) {
this.lastBlock = await Web3Provider.getWeb3().eth.getBlockNumber() + 1
this.poller = setInterval(
() => this.handler(callback),
this.interval)
}
public listenOnce(callback: any) {
this.listen((events: any[]) => {
if (events) {
EventListener.unsubscribe(this)
callback(events[0])
}
})
}
private async handler(callback: any) {
const contract = await GenericContract.getInstance(this.contractName)
if (this.lastBlock > await Web3Provider.getWeb3().eth.getBlockNumber()) {
return
}
try {
const events = await contract.getEventData(this.eventName, {
filter: this.filter,
fromBlock: this.lastBlock,
toBlock: "latest",
})
if (events.length > 0) {
this.lastBlock = events[events.length - 1].blockNumber + 1
callback(events)
}
} catch (err) {
LoggerInstance.log(err)
}
}
}

View File

@ -0,0 +1,62 @@
import { ContractEvent } from "./ContractEvent"
import ContractBase from "./contracts/ContractBase"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
export class EventHandler extends Instantiable {
private events = new Set<(blockNumber) => void>()
private lastBlock: number
private interval = 200
private polling: boolean = false
private lastTimeout: NodeJS.Timeout
get count() {
return this.events.size
}
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
}
private async checkBlock(isInterval?: boolean, n = 0) {
const blockNumber = await this.web3.eth.getBlockNumber()
if ((this.polling && !isInterval) || !this.count) {
return
}
this.polling = true
if (!this.lastBlock) {
this.lastBlock = blockNumber
}
if (this.lastBlock !== blockNumber) {
this.events.forEach(fn => fn(this.lastBlock + 1))
this.lastBlock = blockNumber
}
this.lastTimeout = setTimeout(() => this.checkBlock(true, n++), this.interval)
}
public subscribe(callback: (number) => void) {
this.events.add(callback)
this.checkBlock()
return {
unsubscribe: () => this.unsubscribe(callback),
}
}
public unsubscribe(callback: (number) => void) {
this.events.delete(callback)
if (!this.count) {
clearTimeout(this.lastTimeout)
delete this.lastBlock
this.polling = false
}
}
public getEvent(contract: ContractBase, eventName: string, filter: {[key: string]: any}) {
return new ContractEvent(this, contract, eventName, filter)
}
}

View File

@ -1,29 +0,0 @@
import Event from "./Event"
export default class EventListener {
public static subscribe(contractName: string,
eventName: string,
filter: any): Event {
const event = new Event(contractName, eventName, filter)
EventListener.events.push(event)
return event
}
public static unsubscribe(event): boolean {
event.stopListen()
const i = EventListener.events.indexOf(event)
if (i > -1) {
EventListener.events.splice(i, 1)
}
return true
}
public static count() {
return EventListener.events.length
}
private static events: Event[] = []
}

View File

@ -3,9 +3,11 @@ import Dispenser from "./contracts/Dispenser"
import OceanToken from "./contracts/Token" import OceanToken from "./contracts/Token"
import { Condition, LockRewardCondition, EscrowReward, AccessSecretStoreCondition } from "./contracts/conditions" import { Condition, LockRewardCondition, EscrowReward, AccessSecretStoreCondition } from "./contracts/conditions"
import { AgreementTemplate, EscrowAccessSecretStoreTemplate } from "./contracts/templates" import { AgreementTemplate, EscrowAccessSecretStoreTemplate } from "./contracts/templates"
import { TemplateStoreManager } from "./contracts/managers" import { TemplateStoreManager, AgreementStoreManager, ConditionStoreManager } from "./contracts/managers"
import Web3Provider from "./Web3Provider" import { EventHandler } from "./EventHandler"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/** /**
* Interface with Ocean Keeper contracts. * Interface with Ocean Keeper contracts.
@ -14,45 +16,48 @@ import Web3Provider from "./Web3Provider"
* - Ocean Tokens: the intrinsic tokens circulated inside Ocean network, which is used in the voting of TCRs. * - Ocean Tokens: the intrinsic tokens circulated inside Ocean network, which is used in the voting of TCRs.
* - Marketplace: the core marketplace where people can transact with each other with Ocean tokens. * - Marketplace: the core marketplace where people can transact with each other with Ocean tokens.
*/ */
export class Keeper { export class Keeper extends Instantiable {
/** /**
* Returns Keeper instance. * Returns Keeper instance.
* @return {Promise<Keeper>} * @return {Promise<Keeper>}
*/ */
public static async getInstance(): Promise<Keeper> { public static async getInstance(config: InstantiableConfig): Promise<Keeper> {
if (Keeper.instance === null) { const keeper = new Keeper()
Keeper.instance = new Keeper() keeper.setInstanceConfig(config)
// Main contracts // Adding keeper inside Ocean to prevent `Keeper not defined yet` error
Keeper.instance.dispenser = await Dispenser.getInstance() config.ocean.keeper = keeper
Keeper.instance.token = await OceanToken.getInstance()
Keeper.instance.didRegistry = await DIDRegistry.getInstance()
// Managers // Main contracts
Keeper.instance.templateStoreManager = await TemplateStoreManager.getInstance() keeper.dispenser = await Dispenser.getInstance(config)
keeper.token = await OceanToken.getInstance(config)
keeper.didRegistry = await DIDRegistry.getInstance(config)
// Conditions // Managers
Keeper.instance.conditions = { keeper.templateStoreManager = await TemplateStoreManager.getInstance(config)
lockRewardCondition: await LockRewardCondition.getInstance(), keeper.agreementStoreManager = await AgreementStoreManager.getInstance(config)
escrowReward: await EscrowReward.getInstance(), keeper.conditionStoreManager = await ConditionStoreManager.getInstance(config)
accessSecretStoreCondition: await AccessSecretStoreCondition.getInstance(),
}
// Conditions // Conditions
Keeper.instance.templates = { keeper.conditions = {
escrowAccessSecretStoreTemplate: await EscrowAccessSecretStoreTemplate.getInstance(), lockRewardCondition: await LockRewardCondition.getInstance(config),
} escrowReward: await EscrowReward.getInstance(config),
accessSecretStoreCondition: await AccessSecretStoreCondition.getInstance(config),
} }
return Keeper.instance // Conditions
} keeper.templates = {
escrowAccessSecretStoreTemplate: await EscrowAccessSecretStoreTemplate.getInstance(config),
}
/** // Utils
* Keeper instance. keeper.utils = {
* @type {Keeper} eventHandler: new EventHandler(config),
*/ }
private static instance: Keeper = null
return keeper
}
/** /**
* Ocean Token smart contract instance. * Ocean Token smart contract instance.
@ -78,6 +83,18 @@ export class Keeper {
*/ */
public templateStoreManager: TemplateStoreManager public templateStoreManager: TemplateStoreManager
/**
* Template store manager smart contract instance.
* @type {AgreementStoreManager}
*/
public agreementStoreManager: AgreementStoreManager
/**
* Template store manager smart contract instance.
* @type {ConditionStoreManager}
*/
public conditionStoreManager: ConditionStoreManager
/** /**
* Conditions instances. * Conditions instances.
*/ */
@ -94,6 +111,13 @@ export class Keeper {
escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate, escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate,
} }
/**
* Helpers for contracts.
*/
public utils: {
eventHandler: EventHandler
}
/** /**
* Returns a condition by address. * Returns a condition by address.
* @param {string} address Address of deployed condition. * @param {string} address Address of deployed condition.
@ -109,12 +133,20 @@ export class Keeper {
.find((template) => template.contractName === name) .find((template) => template.contractName === name)
} }
/**
* Returns network id.
* @return {Promise<number>} Network ID.
*/
public getNetworkId(): Promise<number> {
return this.web3.eth.net.getId()
}
/** /**
* Returns the network by name. * Returns the network by name.
* @return {Promise<string>} Network name. * @return {Promise<string>} Network name.
*/ */
public async getNetworkName(): Promise<string> { public getNetworkName(): Promise<string> {
return Web3Provider.getWeb3().eth.net.getId() return this.web3.eth.net.getId()
.then((networkId) => { .then((networkId) => {
let network: string = "Unknown" let network: string = "Unknown"

View File

@ -1,5 +1,5 @@
import * as Web3 from "web3" import * as Web3 from "web3"
import ConfigProvider from "../ConfigProvider" import Config from "../models/Config"
export default class Web3Provider { export default class Web3Provider {
@ -7,18 +7,14 @@ export default class Web3Provider {
* Returns Web3 instance. * Returns Web3 instance.
* @return {Web3} * @return {Web3}
*/ */
public static getWeb3(): Web3 { public static getWeb3(config: Partial<Config> = {}): Web3 {
if (Web3Provider.web3 === null) { if (!this.instances.has(config.nodeUri)) {
const config = ConfigProvider.getConfig()
const web3Provider = config.web3Provider || new Web3.providers.HttpProvider(config.nodeUri) const web3Provider = config.web3Provider || new Web3.providers.HttpProvider(config.nodeUri)
Web3Provider.web3 = new Web3(Web3.givenProvider || web3Provider) this.instances.set(config.nodeUri, new Web3(Web3.givenProvider || web3Provider))
} }
return Web3Provider.web3
return this.instances.get(config.nodeUri)
} }
/** private static instances = new Map<string, Web3>()
* Web3 instance.
* @type {Web3}
*/
private static web3: Web3 = null
} }

View File

@ -1,10 +1,10 @@
import { Contract } from "web3-eth-contract" import { Contract } from "web3-eth-contract"
import { TransactionReceipt } from "web3-core" import { TransactionReceipt } from "web3-core"
import LoggerInstance from "../../utils/Logger"
import ContractHandler from "../ContractHandler" import ContractHandler from "../ContractHandler"
import Web3Provider from "../Web3Provider"
export default abstract class ContractBase { import { Instantiable, InstantiableConfig } from "../../Instantiable.abstract"
export default abstract class ContractBase extends Instantiable {
protected static instance = null protected static instance = null
public contractName: string public contractName: string
@ -12,6 +12,7 @@ export default abstract class ContractBase {
private contract: Contract = null private contract: Contract = null
constructor(contractName) { constructor(contractName) {
super()
this.contractName = contractName this.contractName = contractName
} }
@ -36,13 +37,15 @@ export default abstract class ContractBase {
return foundMethod.inputs return foundMethod.inputs
} }
protected async init() { protected async init(config: InstantiableConfig) {
this.contract = await ContractHandler.get(this.contractName) this.setInstanceConfig(config)
const contractHandler = new ContractHandler(config)
this.contract = await contractHandler.get(this.contractName)
} }
protected async getFromAddress(from?: string): Promise<string> { protected async getFromAddress(from?: string): Promise<string> {
if (!from) { if (!from) {
from = (await Web3Provider.getWeb3().eth.getAccounts())[0] from = (await this.web3.eth.getAccounts())[0]
} }
return from return from
} }
@ -75,12 +78,12 @@ export default abstract class ContractBase {
value: args[i], value: args[i],
} }
}) })
LoggerInstance.error("-".repeat(40)) this.logger.error("-".repeat(40))
LoggerInstance.error(`Sending transaction "${name}" on contract "${this.contractName}" failed.`) this.logger.error(`Sending transaction "${name}" on contract "${this.contractName}" failed.`)
LoggerInstance.error(`Error: ${err.message}`) this.logger.error(`Error: ${err.message}`)
LoggerInstance.error(`From: ${from}`) this.logger.error(`From: ${from}`)
LoggerInstance.error(`Parameters: ${JSON.stringify(mappedArgs, null, 2)}`) this.logger.error(`Parameters: ${JSON.stringify(mappedArgs, null, 2)}`)
LoggerInstance.error("-".repeat(40)) this.logger.error("-".repeat(40))
throw err throw err
} }
} }
@ -94,7 +97,7 @@ export default abstract class ContractBase {
const method = this.contract.methods[name](...args) const method = this.contract.methods[name](...args)
return method.call(from ? {from} : null) return method.call(from ? {from} : null)
} catch (err) { } catch (err) {
LoggerInstance.error(`Calling method "${name}" on contract "${this.contractName}" failed. Args: ${args}`, err) this.logger.error(`Calling method "${name}" on contract "${this.contractName}" failed. Args: ${args}`, err)
throw err throw err
} }
} }
@ -109,4 +112,11 @@ export default abstract class ContractBase {
} }
return foundMethod return foundMethod
} }
protected getEvent(eventName: string, filter: {[key: string]: any}) {
if (!this.contract.events[eventName]) {
throw new Error(`Event ${eventName} is not part of contract ${this.contractName}`)
}
return this.ocean.keeper.utils.eventHandler.getEvent(this, eventName, filter)
}
} }

View File

@ -1,12 +1,13 @@
import Web3Provider from "../Web3Provider" import Web3Provider from "../Web3Provider"
import ContractBase from "./ContractBase" import ContractBase from "./ContractBase"
import { zeroX } from "../../utils" import { zeroX } from "../../utils"
import { InstantiableConfig } from "../../Instantiable.abstract"
export default class DIDRegistry extends ContractBase { export default class DIDRegistry extends ContractBase {
public static async getInstance(): Promise<DIDRegistry> { public static async getInstance(config: InstantiableConfig): Promise<DIDRegistry> {
const didRegistry: DIDRegistry = new DIDRegistry("DIDRegistry") const didRegistry: DIDRegistry = new DIDRegistry("DIDRegistry")
await didRegistry.init() await didRegistry.init(config)
return didRegistry return didRegistry
} }

View File

@ -1,11 +1,12 @@
import ContractBase from "./ContractBase" import ContractBase from "./ContractBase"
import { InstantiableConfig } from "../../Instantiable.abstract"
export default class Dispenser extends ContractBase { export default class Dispenser extends ContractBase {
public static async getInstance(): Promise<Dispenser> { public static async getInstance(config: InstantiableConfig): Promise<Dispenser> {
const market: Dispenser = new Dispenser("Dispenser") const dispenser: Dispenser = new Dispenser("Dispenser")
await market.init() await dispenser.init(config)
return market return dispenser
} }
public async requestTokens(amount: number, receiverAddress: string) { public async requestTokens(amount: number, receiverAddress: string) {

View File

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

View File

@ -1,11 +1,12 @@
import BigNumber from "bignumber.js" import BigNumber from "bignumber.js"
import ContractBase from "./ContractBase" import ContractBase from "./ContractBase"
import { InstantiableConfig } from "../../Instantiable.abstract"
export default class OceanToken extends ContractBase { export default class OceanToken extends ContractBase {
public static async getInstance(): Promise<OceanToken> { public static async getInstance(config: InstantiableConfig): Promise<OceanToken> {
const token: OceanToken = new OceanToken("OceanToken") const token: OceanToken = new OceanToken("OceanToken")
await token.init() await token.init(config)
return token return token
} }

View File

@ -1,10 +1,11 @@
import { Condition } from "./Condition.abstract" import { Condition } from "./Condition.abstract"
import { zeroX, didZeroX } from "../../../utils" import { zeroX, didZeroX } from "../../../utils"
import { InstantiableConfig } from "../../../Instantiable.abstract"
export class AccessSecretStoreCondition extends Condition { export class AccessSecretStoreCondition extends Condition {
public static async getInstance(): Promise<AccessSecretStoreCondition> { public static async getInstance(config: InstantiableConfig): Promise<AccessSecretStoreCondition> {
return Condition.getInstance("AccessSecretStoreCondition", AccessSecretStoreCondition) return Condition.getInstance(config, "AccessSecretStoreCondition", AccessSecretStoreCondition)
} }
public hashValues(did: string, grantee: string) { public hashValues(did: string, grantee: string) {

View File

@ -1,7 +1,6 @@
import ContractBase from "../ContractBase" import ContractBase from "../ContractBase"
import { zeroX } from "../../../utils" import { zeroX } from "../../../utils"
import EventListener from "../../../keeper/EventListener" import { InstantiableConfig } from "../../../Instantiable.abstract"
import Event from "../../../keeper/Event"
export enum ConditionState { export enum ConditionState {
Uninitialized = 0, Uninitialized = 0,
@ -14,9 +13,9 @@ export const conditionStateNames = ["Uninitialized", "Unfulfilled", "Fulfilled",
export abstract class Condition extends ContractBase { export abstract class Condition extends ContractBase {
public static async getInstance(conditionName: string, conditionsClass: any): Promise<Condition & any> { public static async getInstance(config: InstantiableConfig, conditionName: string, conditionsClass: any): Promise<Condition & any> {
const condition: Condition = new (conditionsClass as any)(conditionName) const condition: Condition = new (conditionsClass as any)(conditionName)
await condition.init() await condition.init(config)
return condition return condition
} }
@ -45,12 +44,7 @@ export abstract class Condition extends ContractBase {
return this.sendFrom("abortByTimeOut", [zeroX(agreementId)], from) return this.sendFrom("abortByTimeOut", [zeroX(agreementId)], from)
} }
public getConditionFulfilledEvent(agreementId: string): Event { public getConditionFulfilledEvent(agreementId: string) {
return EventListener return this.getEvent("Fulfilled", {agreementId: zeroX(agreementId)})
.subscribe(
this.contractName,
"Fulfilled",
{agreementId: zeroX(agreementId)},
)
} }
} }

View File

@ -1,10 +1,11 @@
import { Condition } from "./Condition.abstract" import { Condition } from "./Condition.abstract"
import { zeroX } from "../../../utils" import { zeroX } from "../../../utils"
import { InstantiableConfig } from "../../../Instantiable.abstract"
export class EscrowReward extends Condition { export class EscrowReward extends Condition {
public static async getInstance(): Promise<EscrowReward> { public static async getInstance(config: InstantiableConfig): Promise<EscrowReward> {
return Condition.getInstance("EscrowReward", EscrowReward) return Condition.getInstance(config, "EscrowReward", EscrowReward)
} }
public hashValues(amount: number, receiver: string, sender: string, lockCondition: string, releaseCondition: string) { public hashValues(amount: number, receiver: string, sender: string, lockCondition: string, releaseCondition: string) {

View File

@ -1,10 +1,11 @@
import { Condition } from "./Condition.abstract" import { Condition } from "./Condition.abstract"
import { zeroX } from "../../../utils" import { zeroX } from "../../../utils"
import { InstantiableConfig } from "../../../Instantiable.abstract"
export class LockRewardCondition extends Condition { export class LockRewardCondition extends Condition {
public static async getInstance(): Promise<LockRewardCondition> { public static async getInstance(config: InstantiableConfig): Promise<LockRewardCondition> {
return Condition.getInstance("LockRewardCondition", LockRewardCondition) return Condition.getInstance(config, "LockRewardCondition", LockRewardCondition)
} }
public hashValues(rewardAddress: string, amount: number) { public hashValues(rewardAddress: string, amount: number) {

View File

@ -1,6 +1,6 @@
import LoggerInstance from "../../../utils/Logger"
import ContractBase from "../ContractBase" import ContractBase from "../ContractBase"
import { zeroX } from "../../../utils" import { zeroX } from "../../../utils"
import { InstantiableConfig } from "../../../Instantiable.abstract"
export interface AgreementData { export interface AgreementData {
did: string did: string
@ -13,9 +13,9 @@ export interface AgreementData {
export class AgreementStoreManager extends ContractBase { export class AgreementStoreManager extends ContractBase {
public static async getInstance(): Promise<AgreementStoreManager> { public static async getInstance(config: InstantiableConfig): Promise<AgreementStoreManager> {
const templateStoreManeger: AgreementStoreManager = new AgreementStoreManager("AgreementStoreManager") const templateStoreManeger: AgreementStoreManager = new AgreementStoreManager("AgreementStoreManager")
await templateStoreManeger.init() await templateStoreManeger.init(config)
return templateStoreManeger return templateStoreManeger
} }

View File

@ -1,7 +1,7 @@
import LoggerInstance from "../../../utils/Logger"
import ContractBase from "../ContractBase" import ContractBase from "../ContractBase"
import { ConditionState } from "../conditions/Condition.abstract" import { ConditionState } from "../conditions/Condition.abstract"
import { zeroX } from "../../../utils" import { zeroX } from "../../../utils"
import { InstantiableConfig } from "../../../Instantiable.abstract"
export interface ConditionData { export interface ConditionData {
typeRef: string typeRef: string
@ -15,9 +15,9 @@ export interface ConditionData {
export class ConditionStoreManager extends ContractBase { export class ConditionStoreManager extends ContractBase {
public static async getInstance(): Promise<ConditionStoreManager> { public static async getInstance(config: InstantiableConfig): Promise<ConditionStoreManager> {
const templateStoreManeger: ConditionStoreManager = new ConditionStoreManager("ConditionStoreManager") const templateStoreManeger: ConditionStoreManager = new ConditionStoreManager("ConditionStoreManager")
await templateStoreManeger.init() await templateStoreManeger.init(config)
return templateStoreManeger return templateStoreManeger
} }

View File

@ -1,6 +1,7 @@
import LoggerInstance from "../../../utils/Logger"
import ContractBase from "../ContractBase" import ContractBase from "../ContractBase"
import { zeroX } from "../../../utils" import { zeroX } from "../../../utils"
import { InstantiableConfig } from "../../../Instantiable.abstract"
export enum TemplateState { export enum TemplateState {
Uninitialized = 0, Uninitialized = 0,
@ -18,9 +19,9 @@ export interface TemplateMetadata {
export class TemplateStoreManager extends ContractBase { export class TemplateStoreManager extends ContractBase {
public static async getInstance(): Promise<TemplateStoreManager> { public static async getInstance(config: InstantiableConfig): Promise<TemplateStoreManager> {
const templateStoreManeger: TemplateStoreManager = new TemplateStoreManager("TemplateStoreManager") const templateStoreManeger: TemplateStoreManager = new TemplateStoreManager("TemplateStoreManager")
await templateStoreManeger.init() await templateStoreManeger.init(config)
return templateStoreManeger return templateStoreManeger
} }
@ -31,7 +32,7 @@ export class TemplateStoreManager extends ContractBase {
public async proposeTemplate(address: string, from?: string, ignoreExists?: boolean) { public async proposeTemplate(address: string, from?: string, ignoreExists?: boolean) {
const template = await this.getTemplate(address) const template = await this.getTemplate(address)
if (template.blockNumberUpdated !== 0) { if (template.blockNumberUpdated !== 0) {
LoggerInstance.warn(`Template "${address}" already exist.`) this.logger.warn(`Template "${address}" already exist.`)
if (!ignoreExists) { if (!ignoreExists) {
throw new Error("Template already exist.") throw new Error("Template already exist.")
} }
@ -43,7 +44,7 @@ export class TemplateStoreManager extends ContractBase {
public async approveTemplate(address: string, from?: string, ignoreApproved?: boolean) { public async approveTemplate(address: string, from?: string, ignoreApproved?: boolean) {
const template = await this.getTemplate(address) const template = await this.getTemplate(address)
if (template.state !== TemplateState.Proposed) { if (template.state !== TemplateState.Proposed) {
LoggerInstance.warn(`Template "${address}" is not in "proposed" state.`) this.logger.warn(`Template "${address}" is not in "proposed" state.`)
if (!ignoreApproved) { if (!ignoreApproved) {
throw new Error(`Template not in "proposed" state.`) throw new Error(`Template not in "proposed" state.`)
} }

View File

@ -1,18 +1,15 @@
import ContractBase from "../ContractBase" import ContractBase from "../ContractBase"
import { AgreementStoreManager, ConditionStoreManager } from "../managers"
import { Condition, ConditionState, conditionStateNames } from "../conditions/Condition.abstract" import { Condition, ConditionState, conditionStateNames } from "../conditions/Condition.abstract"
import Keeper from "../../Keeper"
import { DDO } from "../../../ddo/DDO" import { DDO } from "../../../ddo/DDO"
import { ServiceAgreementTemplate } from "../../../ddo/ServiceAgreementTemplate" import { ServiceAgreementTemplate } from "../../../ddo/ServiceAgreementTemplate"
import { zeroX, LoggerInstance } from "../../../utils" import { zeroX } from "../../../utils"
import EventListener from "../../../keeper/EventListener" import { InstantiableConfig } from "../../../Instantiable.abstract"
import Event from "../../../keeper/Event"
export abstract class AgreementTemplate extends ContractBase { export abstract class AgreementTemplate extends ContractBase {
public static async getInstance(conditionName: string, templateClass: any): Promise<AgreementTemplate & any> { public static async getInstance(config: InstantiableConfig, conditionName: string, templateClass: any): Promise<AgreementTemplate & any> {
const condition: AgreementTemplate = new (templateClass as any)(conditionName) const condition: AgreementTemplate = new (templateClass as any)(conditionName)
await condition.init() await condition.init(config)
return condition return condition
} }
@ -58,9 +55,8 @@ export abstract class AgreementTemplate extends ContractBase {
* @return {Promise<Condition[]>} Conditions contracts. * @return {Promise<Condition[]>} Conditions contracts.
*/ */
public async getConditions(): Promise<Condition[]> { public async getConditions(): Promise<Condition[]> {
const keeper = await Keeper.getInstance()
return (await this.getConditionTypes()) return (await this.getConditionTypes())
.map((address) => keeper.getConditionByAddress(address)) .map((address) => this.ocean.keeper.getConditionByAddress(address))
} }
/** /**
@ -117,14 +113,14 @@ export abstract class AgreementTemplate extends ContractBase {
blockedBy: string[], blockedBy: string[],
}, },
} | false> { } | false> {
const agreementStore = await AgreementStoreManager.getInstance() const agreementStore = this.ocean.keeper.agreementStoreManager
const conditionStore = await ConditionStoreManager.getInstance() const conditionStore = this.ocean.keeper.conditionStoreManager
const dependencies = await this.getServiceAgreementTemplateDependencies() const dependencies = await this.getServiceAgreementTemplateDependencies()
const {conditionIds} = await agreementStore.getAgreement(agreementId) const {conditionIds} = await agreementStore.getAgreement(agreementId)
if (!conditionIds.length) { if (!conditionIds.length) {
LoggerInstance.error(`Agreement not creeated yet: "${agreementId}"`) this.logger.error(`Agreement not creeated yet: "${agreementId}"`)
return false return false
} }
@ -167,25 +163,25 @@ export abstract class AgreementTemplate extends ContractBase {
public async printAgreementStatus(agreementId: string) { public async printAgreementStatus(agreementId: string) {
const status = await this.getAgreementStatus(agreementId) const status = await this.getAgreementStatus(agreementId)
LoggerInstance.bypass("-".repeat(80)) this.logger.bypass("-".repeat(80))
LoggerInstance.bypass("Template:", this.contractName) this.logger.bypass("Template:", this.contractName)
LoggerInstance.bypass("Agreement ID:", agreementId) this.logger.bypass("Agreement ID:", agreementId)
LoggerInstance.bypass("-".repeat(40)) this.logger.bypass("-".repeat(40))
if (!status) { if (!status) {
LoggerInstance.bypass("Agreement not created yet!") this.logger.bypass("Agreement not created yet!")
} }
Object.values(status || []) Object.values(status || [])
.forEach(({condition, contractName, state, blocked, blockedBy}, i) => { .forEach(({condition, contractName, state, blocked, blockedBy}, i) => {
if (i) { if (i) {
LoggerInstance.bypass("-".repeat(20)) this.logger.bypass("-".repeat(20))
} }
LoggerInstance.bypass(`${condition} (${contractName})`) this.logger.bypass(`${condition} (${contractName})`)
LoggerInstance.bypass(" Status:", state, `(${conditionStateNames[state]})`) this.logger.bypass(" Status:", state, `(${conditionStateNames[state]})`)
if (blocked) { if (blocked) {
LoggerInstance.bypass(" Blocked by:", blockedBy) this.logger.bypass(" Blocked by:", blockedBy)
} }
}) })
LoggerInstance.bypass("-".repeat(80)) this.logger.bypass("-".repeat(80))
} }
/** /**
@ -193,12 +189,7 @@ export abstract class AgreementTemplate extends ContractBase {
* @param {string} agreementId Agreement ID. * @param {string} agreementId Agreement ID.
* @return {Event} Agreement created event. * @return {Event} Agreement created event.
*/ */
public getAgreementCreatedEvent(agreementId: string): Event { public getAgreementCreatedEvent(agreementId: string) {
return EventListener return this.getEvent("AgreementCreated", {agreementId: zeroX(agreementId)})
.subscribe(
this.contractName,
"AgreementCreated",
{agreementId: zeroX(agreementId)},
)
} }
} }

View File

@ -3,13 +3,14 @@ import { LockRewardCondition, EscrowReward, AccessSecretStoreCondition } from ".
import DIDRegistry from "../DIDRegistry" import DIDRegistry from "../DIDRegistry"
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 { escrowAccessSecretStoreTemplateServiceAgreementTemplate } from "./EscrowAccessSecretStoreTemplate.serviceAgreementTemplate" import { escrowAccessSecretStoreTemplateServiceAgreementTemplate } from "./EscrowAccessSecretStoreTemplate.serviceAgreementTemplate"
export class EscrowAccessSecretStoreTemplate extends AgreementTemplate { export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
public static async getInstance(): Promise<EscrowAccessSecretStoreTemplate> { public static async getInstance(config: InstantiableConfig): Promise<EscrowAccessSecretStoreTemplate> {
return AgreementTemplate.getInstance("EscrowAccessSecretStoreTemplate", EscrowAccessSecretStoreTemplate) return AgreementTemplate.getInstance(config, "EscrowAccessSecretStoreTemplate", EscrowAccessSecretStoreTemplate)
} }
public async getServiceAgreementTemplate() { public async getServiceAgreementTemplate() {
@ -89,11 +90,9 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
} }
private async createFullAgreementData(agreementId: string, did: string, amount: number, consumer: string) { private async createFullAgreementData(agreementId: string, did: string, amount: number, consumer: string) {
const didRegistry = await DIDRegistry.getInstance() const {didRegistry, conditions} = this.ocean.keeper
const accessSecretStoreCondition = await AccessSecretStoreCondition.getInstance() const {accessSecretStoreCondition, lockRewardCondition, escrowReward} = conditions
const lockRewardCondition = await LockRewardCondition.getInstance()
const escrowReward = await EscrowReward.getInstance()
const publisher = await didRegistry.getDIDOwner(did) const publisher = await didRegistry.getDIDOwner(did)

View File

@ -1,17 +1,21 @@
import BigNumber from "bignumber.js" import BigNumber from "bignumber.js"
import * as EthJsUtils from "ethereumjs-util" import * as EthJsUtils from "ethereumjs-util"
import Keeper from "../keeper/Keeper"
import Web3Provider from "../keeper/Web3Provider"
import Balance from "../models/Balance" import Balance from "../models/Balance"
import LoggerInstance from "../utils/Logger"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/** /**
* Account information. * Account information.
*/ */
export default class Account { export default class Account extends Instantiable {
private password?: string private password?: string
constructor(private id: string = "0x0") { } constructor(private id: string = "0x0", config?: InstantiableConfig) {
super()
if (config) {
this.setInstanceConfig(config)
}
}
public getId() { public getId() {
return this.id return this.id
@ -42,7 +46,7 @@ export default class Account {
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async getOceanBalance(): Promise<number> { public async getOceanBalance(): Promise<number> {
const token = (await Keeper.getInstance()).token const token = this.ocean.keeper.token
return await token.balanceOf(this.id) / (10 ** await token.decimals()) return await token.balanceOf(this.id) / (10 ** await token.decimals())
} }
@ -51,13 +55,10 @@ export default class Account {
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async getEtherBalance(): Promise<number> { public async getEtherBalance(): Promise<number> {
// Logger.log("getting balance for", account); return this.web3
return Web3Provider
.getWeb3()
.eth .eth
.getBalance(this.id, "latest") .getBalance(this.id, "latest")
.then((balance: string): number => { .then((balance: string): number => {
// Logger.log("balance", balance);
return new BigNumber(balance).toNumber() return new BigNumber(balance).toNumber()
}) })
} }
@ -80,11 +81,11 @@ export default class Account {
*/ */
public async requestTokens(amount: number): Promise<number> { public async requestTokens(amount: number): Promise<number> {
try { try {
await (await Keeper.getInstance()) await this.ocean.keeper
.dispenser .dispenser
.requestTokens(amount, this.id) .requestTokens(amount, this.id)
} catch (e) { } catch (e) {
LoggerInstance.error(e) this.logger.error(e)
throw new Error("Error requesting tokens") throw new Error("Error requesting tokens")
} }
@ -96,11 +97,8 @@ export default class Account {
* @return {Promise<string>} * @return {Promise<string>}
*/ */
public async getPublicKey(): Promise<string> { public async getPublicKey(): Promise<string> {
const msg = this.web3.utils.sha3(this.getId())
const web3 = Web3Provider.getWeb3() const sig = await this.web3.eth.sign(msg, this.getId())
const msg = web3.utils.sha3(this.getId())
const sig = await web3.eth.sign(msg, this.getId())
const {v, r, s} = EthJsUtils.fromRpcSig(sig) const {v, r, s} = EthJsUtils.fromRpcSig(sig)
return EthJsUtils.ecrecover(EthJsUtils.toBuffer(msg), v, r, s).toString("hex") return EthJsUtils.ecrecover(EthJsUtils.toBuffer(msg), v, r, s).toString("hex")

View File

@ -1,33 +1,22 @@
import deprecated from "deprecated-decorator"
import { OceanAccounts } from "./OceanAccounts" import { OceanAccounts } from "./OceanAccounts"
import { OceanAgreements } from "./OceanAgreements" import { OceanAgreements } from "./OceanAgreements"
import { OceanAssets } from "./OceanAssets" import { OceanAssets } from "./OceanAssets"
import { OceanSecretStore } from "./OceanSecretStore" import { OceanSecretStore } from "./OceanSecretStore"
import { OceanTokens } from "./OceanTokens" import { OceanTokens } from "./OceanTokens"
import AquariusProvider from "../aquarius/AquariusProvider" import { Aquarius } from "../aquarius/Aquarius"
import { SearchQuery } from "../aquarius/query/SearchQuery" import { Brizo } from "../brizo/Brizo"
import BrizoProvider from "../brizo/BrizoProvider"
import ConfigProvider from "../ConfigProvider"
import { DDO } from "../ddo/DDO"
import { MetaData } from "../ddo/MetaData"
import { Service } from "../ddo/Service"
import ContractEvent from "../keeper/Event"
import Config from "../models/Config"
import SecretStoreProvider from "../secretstore/SecretStoreProvider"
import { LoggerInstance, LogLevel } from "../utils/Logger"
import Account from "./Account"
import DID from "./DID"
import ServiceAgreement from "./ServiceAgreements/ServiceAgreement"
import Keeper from "../keeper/Keeper" import Keeper from "../keeper/Keeper"
import EventListener from "../keeper/EventListener"
import { Config } from "../models/Config"
import { Instantiable, generateIntantiableConfigFromConfig } from "../Instantiable.abstract"
/** /**
* Main interface for Ocean Protocol. * Main interface for Ocean Protocol.
*/ */
export class Ocean { export class Ocean extends Instantiable {
/** /**
* Returns the instance of Ocean. * Returns the instance of Ocean.
@ -35,33 +24,46 @@ export class Ocean {
* @return {Promise<Ocean>} * @return {Promise<Ocean>}
*/ */
public static async getInstance(config: Config): Promise<Ocean> { public static async getInstance(config: Config): Promise<Ocean> {
ConfigProvider.setConfig(config) const instance = new Ocean()
if (!Ocean.instance) { const instanceConfig = {
Ocean.instance = new Ocean() ...generateIntantiableConfigFromConfig(config),
Ocean.instance.keeper = await Keeper.getInstance() ocean: instance,
Ocean.instance.accounts = await OceanAccounts.getInstance()
Ocean.instance.assets = await OceanAssets.getInstance()
Ocean.instance.agreements = await OceanAgreements.getInstance()
Ocean.instance.secretStore = await OceanSecretStore.getInstance()
Ocean.instance.tokens = await OceanTokens.getInstance()
} }
instance.setInstanceConfig(instanceConfig)
return Ocean.instance instance.keeper = await Keeper.getInstance(instanceConfig)
instance.brizo = new Brizo(instanceConfig)
instance.aquarius = new Aquarius(instanceConfig)
instance.accounts = await OceanAccounts.getInstance(instanceConfig)
instance.assets = await OceanAssets.getInstance(instanceConfig)
instance.agreements = await OceanAgreements.getInstance(instanceConfig)
instance.secretStore = await OceanSecretStore.getInstance(instanceConfig)
instance.tokens = await OceanTokens.getInstance(instanceConfig)
return instance
} }
/**
* Ocean instance.
* @type {Ocean}
*/
private static instance: Ocean = null
/** /**
* Keeper instance. * Keeper instance.
* @type {Keeper} * @type {Keeper}
*/ */
public keeper: Keeper public keeper: Keeper
/**
* Brizo instance.
* @type {Brizo}
*/
public brizo: Brizo
/**
* Aquarius instance.
* @type {Aquarius}
*/
public aquarius: Aquarius
/** /**
* Ocean account submodule * Ocean account submodule
* @type {OceanAccounts} * @type {OceanAccounts}
@ -92,158 +94,7 @@ export class Ocean {
*/ */
public tokens: OceanTokens public tokens: OceanTokens
private constructor() { } private constructor() {
super()
/**
* Returns the list of accounts.
* @deprecated Replace by [Ocean.accounts.list]{@link #OceanAccounts.list}
* @return {Promise<Account[]>}
*/
@deprecated("OceanAccounts.list")
public async getAccounts(): Promise<Account[]> {
return await this.accounts.list()
}
/**
* Returns a DDO by DID.
* @deprecated Replace by [Ocean.assets.resolve]{@link #OceanAssets.resolve}
* @param {string} did Decentralized ID.
* @return {Promise<DDO>}
*/
@deprecated("OceanAssets.resolve")
public async resolveDID(did: string): Promise<DDO> {
return await this.assets.resolve(did)
}
/**
* Returns a DDO by DID.
* @deprecated Replace by [Ocean.assets.resolve]{@link #OceanAssets.resolve}
* @param {string} did Decentralized ID.
* @return {Promise<DDO>}
*/
@deprecated("OceanAssets.resolve")
public async resolveAssetDID(did: string): Promise<DDO> {
return await this.assets.resolve(did)
}
/**
* Registers a new DDO.
* @deprecated Replace by [Ocean.assets.create]{@link #OceanAssets.create}
* @param {MetaData} metadata DDO metadata.
* @param {Account} publisher Publisher account.
* @return {Promise<DDO>}
*/
@deprecated("OceanAssets.create")
public async registerAsset(metadata: MetaData, publisher: Account, services?: Service[]): Promise<DDO> {
return await this.assets.create(metadata, publisher, services)
}
/**
* Signs a service agreement by DID.
* @deprecated Replace by [Ocean.agreement.prepare]{@link #OceanAgreement.prepare}
* @param {string} did Decentralized ID.
* @param {string} serviceDefinitionId Service definition ID.
* @param {Account} consumer Consumer account.
* @return {Promise<any>}
*
*/
@deprecated("OceanAgreement.prepare")
public async signServiceAgreement(
did: string,
serviceDefinitionId: string,
consumer: Account,
) {
return await this.agreements.prepare(did, serviceDefinitionId, consumer)
}
/**
* Signs a service agreement by DID.
* @deprecated Replace by [Ocean.assets.order]{@link #OceanAssets.order}
* @param {string} did Decentralized ID.
* @param {string} serviceDefinitionId Service definition ID.
* @param {Account} consumer Consumer account.
* @return {Promise<any>}
*/
@deprecated("OceanAssets.order")
public async purchaseAssetService(
did: string,
serviceDefinitionId: string,
consumer: Account,
): Promise<any> {
return await this.assets.order(did, serviceDefinitionId, consumer)
}
/**
* Creates a new service agreement.
* @deprecated Replace by [Ocean.assets.consume]{@link #OceanAssets.consume}
* @param {string} did Decentralized ID.
* @param {string} serviceDefinitionId Service definition ID.
* @param {string} serviceAgreementId Service agreement ID.
* @param {string} serviceAgreementSignature Service agreement signature.
* @param {Function} cb Callback executen when the access is granted.
* @param {Account} consumer Consumer account.
*/
@deprecated("OceanAssets.consume")
public async initializeServiceAgreement(
did: string,
serviceDefinitionId: string,
serviceAgreementId: string,
serviceAgreementSignature: string,
cb: (files: string[]) => void,
consumer: Account,
) {
return await this.assets.consume(serviceAgreementId, did, serviceDefinitionId, consumer)
}
/**
* Executes a service agreement.
* @deprecated Replace by [Ocean.agreements.create]{@link #OceanAgreements.create}
* @param {string} did Decentralized ID.
* @param {string} serviceDefinitionId Service definition ID.
* @param {string} serviceAgreementId Service agreement ID.
* @param {string} serviceAgreementSignature Service agreement signature.
* @param {Account} consumer Consumer account.
* @param {Account} publisher Publisher account.
* @return {Promise<ServiceAgreement>}
*/
@deprecated("OceanAgreements.create")
public async executeServiceAgreement(
did: string,
serviceDefinitionId: string,
serviceAgreementId: string,
serviceAgreementSignature: string,
consumer: Account,
publisher: Account,
): Promise<ServiceAgreement> {
return await this.agreements
.create(did,
serviceDefinitionId,
serviceAgreementId,
serviceAgreementSignature,
consumer,
publisher,
)
}
/**
* Search over the assets using a query.
* @deprecated Replace by [Ocean.assets.query]{@link #OceanAssets.query}
* @param {SearchQuery} query Query to filter the assets.
* @return {Promise<DDO[]>}
*/
@deprecated("OceanAssets.query")
public async searchAssets(query: SearchQuery): Promise<DDO[]> {
return await this.assets.query(query)
}
/**
* Search over the assets using a keyword.
* @deprecated Replace by [Ocean.assets.search]{@link #OceanAssets.search}
* @param {string} text Text to filter the assets.
* @return {Promise<DDO[]>}
*/
@deprecated("OceanAssets.search")
public async searchAssetsByText(text: string): Promise<DDO[]> {
return await this.assets.search(text)
} }
} }

View File

@ -1,30 +1,23 @@
import Web3Provider from "../keeper/Web3Provider"
import Balance from "../models/Balance" import Balance from "../models/Balance"
import Account from "./Account" import Account from "./Account"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/** /**
* Account submodule of Ocean Protocol. * Account submodule of Ocean Protocol.
*/ */
export class OceanAccounts { 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(): Promise<OceanAccounts> { public static async getInstance(config: InstantiableConfig): Promise<OceanAccounts> {
if (!OceanAccounts.instance) { const instance = new OceanAccounts()
OceanAccounts.instance = new OceanAccounts() instance.setInstanceConfig(config)
}
return OceanAccounts.instance return instance
} }
/**
* OceanAccounts instance.
* @type {OceanAccounts}
*/
private static instance: OceanAccounts = null
/** /**
* Returns the list of accounts. * Returns the list of accounts.
* @return {Promise<Account[]>} * @return {Promise<Account[]>}
@ -32,9 +25,9 @@ export class OceanAccounts {
public async list(): Promise<Account[]> { public async list(): Promise<Account[]> {
// retrieve eth accounts // retrieve eth accounts
const ethAccounts = await Web3Provider.getWeb3().eth.getAccounts() const ethAccounts = await this.web3.eth.getAccounts()
return ethAccounts.map((address: string) => new Account(address)) return ethAccounts.map((address: string) => new Account(address, this.instanceConfig))
} }
/** /**

View File

@ -1,11 +1,9 @@
import AquariusProvider from "../aquarius/AquariusProvider"
import BrizoProvider from "../brizo/BrizoProvider"
import { generateId } from "../utils/GeneratorHelpers" import { generateId } from "../utils/GeneratorHelpers"
import Account from "./Account" import Account from "./Account"
import DID from "./DID" import DID from "./DID"
import ServiceAgreement from "./ServiceAgreements/ServiceAgreement" import ServiceAgreement from "./ServiceAgreements/ServiceAgreement"
import { Keeper } from "../keeper/Keeper"
import { zeroX, didPrefixed } from "../utils" import { zeroX, didPrefixed } from "../utils"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
import { OceanAgreementsConditions } from "./OceanAgreementsConditions" import { OceanAgreementsConditions } from "./OceanAgreementsConditions"
@ -17,27 +15,20 @@ export interface AgreementPrepareResult {
/** /**
* Agreements submodule of Ocean Protocol. * Agreements submodule of Ocean Protocol.
*/ */
export class OceanAgreements { export class OceanAgreements extends Instantiable {
/** /**
* Returns the instance of OceanAgreements. * Returns the instance of OceanAgreements.
* @return {Promise<OceanAgreements>} * @return {Promise<OceanAgreements>}
*/ */
public static async getInstance(): Promise<OceanAgreements> { public static async getInstance(config: InstantiableConfig): Promise<OceanAgreements> {
if (!OceanAgreements.instance) { const instance = new OceanAgreements()
OceanAgreements.instance = new OceanAgreements() instance.setInstanceConfig(config)
OceanAgreements.instance.conditions = await OceanAgreementsConditions.getInstance() instance.conditions = await OceanAgreementsConditions.getInstance(config)
}
return OceanAgreements.instance return instance
} }
/**
* OceanAgreements instance.
* @type {OceanAgreements}
*/
private static instance: OceanAgreements = null
/** /**
* Agreements Conditions submodule. * Agreements Conditions submodule.
* @type {OceanAgreementsConditions} * @type {OceanAgreementsConditions}
@ -58,16 +49,16 @@ export class OceanAgreements {
): Promise<AgreementPrepareResult> { ): Promise<AgreementPrepareResult> {
const d: DID = DID.parse(did as string) const d: DID = DID.parse(did as string)
const ddo = await AquariusProvider.getAquarius().retrieveDDO(d) const ddo = await this.ocean.aquarius.retrieveDDO(d)
const agreementId: string = generateId() const agreementId: string = generateId()
const keeper = await Keeper.getInstance()
const templateName = ddo.findServiceByType("Access").serviceAgreementTemplate.contractName const templateName = ddo.findServiceByType("Access").serviceAgreementTemplate.contractName
const agreementConditionsIds = await keeper const agreementConditionsIds = await this.ocean.keeper
.getTemplateByName(templateName) .getTemplateByName(templateName)
.getAgreementIdsFromDDO(agreementId, ddo, consumer.getId(), consumer.getId()) .getAgreementIdsFromDDO(agreementId, ddo, consumer.getId(), consumer.getId())
const signature = await ServiceAgreement.signServiceAgreement( const signature = await ServiceAgreement.signServiceAgreement(
this.web3,
ddo, ddo,
serviceDefinitionId, serviceDefinitionId,
agreementId, agreementId,
@ -93,8 +84,7 @@ export class OceanAgreements {
consumer: Account, consumer: Account,
): Promise<void> { ): Promise<void> {
const result = await BrizoProvider const result = await this.ocean.brizo
.getBrizo()
.initializeServiceAgreement( .initializeServiceAgreement(
didPrefixed(did), didPrefixed(did),
zeroX(agreementId), zeroX(agreementId),
@ -128,13 +118,11 @@ export class OceanAgreements {
consumer: Account, consumer: Account,
publisher: Account, publisher: Account,
) { ) {
const keeper = await Keeper.getInstance()
const d: DID = DID.parse(did) const d: DID = DID.parse(did)
const ddo = await AquariusProvider.getAquarius().retrieveDDO(d) const ddo = await this.ocean.aquarius.retrieveDDO(d)
const templateName = ddo.findServiceById<"Access">(serviceDefinitionId).serviceAgreementTemplate.contractName const templateName = ddo.findServiceById<"Access">(serviceDefinitionId).serviceAgreementTemplate.contractName
await keeper await this.ocean.keeper
.getTemplateByName(templateName) .getTemplateByName(templateName)
.createAgreementFromDDO(agreementId, ddo, consumer.getId(), publisher.getId()) .createAgreementFromDDO(agreementId, ddo, consumer.getId(), publisher.getId())

View File

@ -1,32 +1,22 @@
import Keeper from "../keeper/Keeper"
import Account from "./Account" import Account from "./Account"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/** /**
* Agreements Conditions submodule of Ocean Protocol. * Agreements Conditions submodule of Ocean Protocol.
*/ */
export class OceanAgreementsConditions { export class OceanAgreementsConditions extends Instantiable {
/** /**
* Returns the instance of OceanAgreementsConditions. * Returns the instance of OceanAgreementsConditions.
* @return {Promise<OceanAgreementsConditions>} * @return {Promise<OceanAgreementsConditions>}
*/ */
public static async getInstance(): Promise<OceanAgreementsConditions> { public static async getInstance(config: InstantiableConfig): Promise<OceanAgreementsConditions> {
if (!OceanAgreementsConditions.instance) { const instance = new OceanAgreementsConditions()
OceanAgreementsConditions.instance = new OceanAgreementsConditions() instance.setInstanceConfig(config)
OceanAgreementsConditions.instance.keeper = await Keeper.getInstance()
}
return OceanAgreementsConditions.instance return instance
} }
/**
* OceanAgreementsConditions instance.
* @type {OceanAgreementsConditions}
*/
private static instance: OceanAgreementsConditions = null
private keeper: Keeper
/** /**
* Transfers tokens to the EscrowRewardCondition contract as an escrow payment. * Transfers tokens to the EscrowRewardCondition contract as an escrow payment.
* This is required before access can be given to the asset data. * This is required before access can be given to the asset data.
@ -34,12 +24,12 @@ export class OceanAgreementsConditions {
* @param {number} amount Asset amount. * @param {number} amount Asset amount.
* @param {Account} from Account of sender. * @param {Account} from Account of sender.
*/ */
public async lockReward(agreementId: string, amount: number, from: Account = new Account()) { public async lockReward(agreementId: string, amount: number, from?: Account) {
const {lockRewardCondition, escrowReward} = this.keeper.conditions const {lockRewardCondition, escrowReward} = this.ocean.keeper.conditions
await this.keeper.token.approve(lockRewardCondition.getAddress(), amount, from.getId()) await this.ocean.keeper.token.approve(lockRewardCondition.getAddress(), amount, from.getId())
const receipt = await lockRewardCondition.fulfill(agreementId, escrowReward.getAddress(), amount, from.getId()) const receipt = await lockRewardCondition.fulfill(agreementId, escrowReward.getAddress(), amount, from && from.getId())
return !!receipt.events.Fulfilled return !!receipt.events.Fulfilled
} }
@ -50,10 +40,10 @@ export class OceanAgreementsConditions {
* @param {string} grantee Consumer address. * @param {string} grantee Consumer address.
* @param {Account} from Account of sender. * @param {Account} from Account of sender.
*/ */
public async grantAccess(agreementId: string, did: string, grantee: string, from: Account = new Account()) { public async grantAccess(agreementId: string, did: string, grantee: string, from?: Account) {
const {accessSecretStoreCondition} = this.keeper.conditions const {accessSecretStoreCondition} = this.ocean.keeper.conditions
const receipt = await accessSecretStoreCondition.fulfill(agreementId, did, grantee, from.getId()) const receipt = await accessSecretStoreCondition.fulfill(agreementId, did, grantee, from && from.getId())
return !!receipt.events.Fulfilled return !!receipt.events.Fulfilled
} }
@ -76,9 +66,9 @@ export class OceanAgreementsConditions {
did: string, did: string,
consumer: string, consumer: string,
publisher: string, publisher: string,
from: Account = new Account(), from?: Account,
) { ) {
const {escrowReward, accessSecretStoreCondition, lockRewardCondition} = this.keeper.conditions const {escrowReward, accessSecretStoreCondition, lockRewardCondition} = this.ocean.keeper.conditions
const conditionIdAccess = await accessSecretStoreCondition.generateIdHash(agreementId, did, consumer) const conditionIdAccess = await accessSecretStoreCondition.generateIdHash(agreementId, did, consumer)
const conditionIdLock = await lockRewardCondition.generateIdHash(agreementId, escrowReward.getAddress(), amount) const conditionIdLock = await lockRewardCondition.generateIdHash(agreementId, escrowReward.getAddress(), amount)
@ -90,7 +80,7 @@ export class OceanAgreementsConditions {
consumer, consumer,
conditionIdLock, conditionIdLock,
conditionIdAccess, conditionIdAccess,
from.getId(), from && from.getId(),
) )
return !!receipt.events.Fulfilled return !!receipt.events.Fulfilled
} }

View File

@ -1,41 +1,28 @@
import AquariusProvider from "../aquarius/AquariusProvider"
import { SearchQuery } from "../aquarius/query/SearchQuery" import { SearchQuery } from "../aquarius/query/SearchQuery"
import BrizoProvider from "../brizo/BrizoProvider"
import ConfigProvider from "../ConfigProvider"
import { DDO } from "../ddo/DDO" import { DDO } from "../ddo/DDO"
import { MetaData } from "../ddo/MetaData" import { MetaData } from "../ddo/MetaData"
import { ServiceAgreementTemplateCondition } from "../ddo/ServiceAgreementTemplate"
import { Service, ServiceAuthorization } from "../ddo/Service" import { Service, ServiceAuthorization } from "../ddo/Service"
import Keeper from "../keeper/Keeper"
import SecretStoreProvider from "../secretstore/SecretStoreProvider"
import { LoggerInstance, fillConditionsWithDDO } from "../utils"
import Account from "./Account" import Account from "./Account"
import DID from "./DID" import DID from "./DID"
import { OceanAgreements } from "./OceanAgreements" import { fillConditionsWithDDO } from "../utils"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/** /**
* Assets submodule of Ocean Protocol. * Assets submodule of Ocean Protocol.
*/ */
export class OceanAssets { 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(): Promise<OceanAssets> { public static async getInstance(config: InstantiableConfig): Promise<OceanAssets> {
if (!OceanAssets.instance) { const instance = new OceanAssets()
OceanAssets.instance = new OceanAssets() instance.setInstanceConfig(config)
}
return OceanAssets.instance return instance
} }
/**
* OceanAssets instance.
* @type {OceanAssets}
*/
private static instance: OceanAssets = null
/** /**
* Returns a DDO by DID. * Returns a DDO by DID.
* @param {string} did Decentralized ID. * @param {string} did Decentralized ID.
@ -43,7 +30,7 @@ export class OceanAssets {
*/ */
public async resolve(did: string): Promise<DDO> { public async resolve(did: string): Promise<DDO> {
const d: DID = DID.parse(did) const d: DID = DID.parse(did)
return AquariusProvider.getAquarius().retrieveDDO(d) return this.ocean.aquarius.retrieveDDO(d)
} }
/** /**
@ -53,24 +40,19 @@ export class OceanAssets {
* @return {Promise<DDO>} * @return {Promise<DDO>}
*/ */
public async create(metadata: MetaData, publisher: Account, services: Service[] = []): Promise<DDO> { public async create(metadata: MetaData, publisher: Account, services: Service[] = []): Promise<DDO> {
const {secretStoreUri} = ConfigProvider.getConfig() const {secretStoreUri} = this.config
const {didRegistry, templates} = await Keeper.getInstance() const {didRegistry, templates} = this.ocean.keeper
const aquarius = AquariusProvider.getAquarius()
const brizo = BrizoProvider.getBrizo()
const did: DID = DID.generate() const did: DID = DID.generate()
const authorizationService = (services.find(({type}) => type === "Authorization") || {}) as ServiceAuthorization const authorizationService = (services.find(({type}) => type === "Authorization") || {}) as ServiceAuthorization
const secretStoreUrl = authorizationService.service === "SecretStore" && authorizationService.serviceEndpoint const secretStoreUrl = authorizationService.service === "SecretStore" && authorizationService.serviceEndpoint
const secretStoreConfig = {
secretStoreUri: secretStoreUrl,
}
const encryptedFiles = await SecretStoreProvider.getSecretStore(secretStoreConfig).encryptDocument(did.getId(), metadata.base.files) const encryptedFiles = await this.ocean.secretStore.encrypt(did.getId(), metadata.base.files, null, secretStoreUrl)
const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate() const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate()
const serviceEndpoint = aquarius.getServiceEndpoint(did) const serviceEndpoint = this.ocean.aquarius.getServiceEndpoint(did)
let serviceDefinitionIdCount = 0 let serviceDefinitionIdCount = 0
// create ddo itself // create ddo itself
@ -91,15 +73,15 @@ export class OceanAssets {
service: [ service: [
{ {
type: "Access", type: "Access",
purchaseEndpoint: brizo.getPurchaseEndpoint(), purchaseEndpoint: this.ocean.brizo.getPurchaseEndpoint(),
serviceEndpoint: brizo.getConsumeEndpoint(), serviceEndpoint: this.ocean.brizo.getConsumeEndpoint(),
serviceDefinitionId: String(serviceDefinitionIdCount++), serviceDefinitionId: String(serviceDefinitionIdCount++),
templateId: templates.escrowAccessSecretStoreTemplate.getAddress(), templateId: templates.escrowAccessSecretStoreTemplate.getAddress(),
serviceAgreementTemplate, serviceAgreementTemplate,
}, },
{ {
type: "Compute", type: "Compute",
serviceEndpoint: brizo.getComputeEndpoint(publisher.getId(), String(serviceDefinitionIdCount), "xxx", "xxx"), serviceEndpoint: this.ocean.brizo.getComputeEndpoint(publisher.getId(), String(serviceDefinitionIdCount), "xxx", "xxx"),
serviceDefinitionId: String(serviceDefinitionIdCount++), serviceDefinitionId: String(serviceDefinitionIdCount++),
}, },
{ {
@ -148,9 +130,9 @@ export class OceanAssets {
serviceAgreementTemplate.conditions = conditions serviceAgreementTemplate.conditions = conditions
ddo.addChecksum() ddo.addChecksum()
await ddo.addProof(publisher.getId(), publisher.getPassword()) await ddo.addProof(this.web3, publisher.getId(), publisher.getPassword())
const storedDdo = await aquarius.storeDDO(ddo) const storedDdo = await this.ocean.aquarius.storeDDO(ddo)
await didRegistry.registerAttribute( await didRegistry.registerAttribute(
did.getId(), did.getId(),
ddo.getChecksum(), ddo.getChecksum(),
@ -172,7 +154,6 @@ export class OceanAssets {
resultPath?: string, resultPath?: string,
): Promise<string | true> { ): Promise<string | true> {
const brizo = BrizoProvider.getBrizo()
const ddo = await this.resolve(did) const ddo = await this.resolve(did)
const {metadata} = ddo.findServiceByType("Metadata") const {metadata} = ddo.findServiceByType("Metadata")
@ -188,27 +169,23 @@ export class OceanAssets {
} }
const secretStoreUrl = authorizationService.service === "SecretStore" && authorizationService.serviceEndpoint const secretStoreUrl = authorizationService.service === "SecretStore" && authorizationService.serviceEndpoint
const secretStoreConfig = {
secretStoreUri: secretStoreUrl,
}
LoggerInstance.log("Decrypting files") this.logger.log("Decrypting files")
const decryptedFiles = await SecretStoreProvider const decryptedFiles = await this.ocean.secretStore
.getSecretStore(secretStoreConfig) .decrypt(did, files, consumerAccount, secretStoreUrl)
.decryptDocument(DID.parse(did).getId(), files) this.logger.log("Files decrypted")
LoggerInstance.log("Files decrypted")
LoggerInstance.log("Consuming files") this.logger.log("Consuming files")
resultPath = resultPath ? `${resultPath}/datafile.${ddo.shortId()}.${agreementId}/` : undefined resultPath = resultPath ? `${resultPath}/datafile.${ddo.shortId()}.${agreementId}/` : undefined
await brizo.consumeService( await this.ocean.brizo.consumeService(
agreementId, agreementId,
serviceEndpoint, serviceEndpoint,
consumerAccount, consumerAccount,
decryptedFiles, decryptedFiles,
resultPath, resultPath,
) )
LoggerInstance.log("Files consumed") this.logger.log("Files consumed")
if (resultPath) { if (resultPath) {
return resultPath return resultPath
@ -230,53 +207,54 @@ export class OceanAssets {
consumer: Account, consumer: Account,
): Promise<string> { ): Promise<string> {
const oceanAgreements = await OceanAgreements.getInstance() const oceanAgreements = this.ocean.agreements
LoggerInstance.log("Asking for agreement signature") this.logger.log("Asking for agreement signature")
const {agreementId, signature} = await oceanAgreements.prepare(did, serviceDefinitionId, consumer) const {agreementId, signature} = await oceanAgreements.prepare(did, serviceDefinitionId, consumer)
LoggerInstance.log(`Agreement ${agreementId} signed`) this.logger.log(`Agreement ${agreementId} signed`)
const ddo = await this.resolve(did) const ddo = await this.resolve(did)
const keeper = await Keeper.getInstance() const keeper = this.ocean.keeper
const templateName = ddo.findServiceByType("Access").serviceAgreementTemplate.contractName const templateName = ddo.findServiceByType("Access").serviceAgreementTemplate.contractName
const template = keeper.getTemplateByName(templateName) const template = keeper.getTemplateByName(templateName)
const accessCondition = keeper.conditions.accessSecretStoreCondition const accessCondition = keeper.conditions.accessSecretStoreCondition
const paymentFlow = new Promise((resolve, reject) => { const paymentFlow = new Promise(async (resolve, reject) => {
template await template.getAgreementCreatedEvent(agreementId).once()
.getAgreementCreatedEvent(agreementId)
.listenOnce(async (...args) => {
LoggerInstance.log("Agreement initialized")
const {metadata} = ddo.findServiceByType("Metadata") this.logger.log("Agreement initialized")
LoggerInstance.log("Locking payment") const {metadata} = ddo.findServiceByType("Metadata")
const paid = await oceanAgreements.conditions.lockReward(agreementId, metadata.base.price, consumer) this.logger.log("Locking payment")
if (paid) { const paid = await oceanAgreements.conditions.lockReward(agreementId, metadata.base.price, consumer)
LoggerInstance.log("Payment was OK")
} else {
LoggerInstance.error("Payment was KO")
LoggerInstance.error("Agreement ID: ", agreementId)
LoggerInstance.error("DID: ", ddo.id)
reject("Error on payment")
}
})
accessCondition if (paid) {
.getConditionFulfilledEvent(agreementId) this.logger.log("Payment was OK")
.listenOnce(async (...args) => { } else {
LoggerInstance.log("Access granted") this.logger.error("Payment was KO")
resolve() this.logger.error("Agreement ID: ", agreementId)
}) this.logger.error("DID: ", ddo.id)
reject("Error on payment")
}
await accessCondition.getConditionFulfilledEvent(agreementId).once()
this.logger.log("Access granted")
resolve()
}) })
LoggerInstance.log("Sending agreement request") this.logger.log("Sending agreement request")
await oceanAgreements.send(did, agreementId, serviceDefinitionId, signature, consumer) await oceanAgreements.send(did, agreementId, serviceDefinitionId, signature, consumer)
this.logger.log("Agreement request sent")
await paymentFlow try {
await paymentFlow
} catch(e) {
throw new Error("Error paying the asset.")
}
return agreementId return agreementId
} }
@ -287,7 +265,7 @@ export class OceanAssets {
* @return {Promise<DDO[]>} * @return {Promise<DDO[]>}
*/ */
public async query(query: SearchQuery): Promise<DDO[]> { public async query(query: SearchQuery): Promise<DDO[]> {
return AquariusProvider.getAquarius().queryMetadataByText(query) return this.ocean.aquarius.queryMetadataByText(query)
} }
/** /**
@ -296,7 +274,7 @@ export class OceanAssets {
* @return {Promise<DDO[]>} * @return {Promise<DDO[]>}
*/ */
public async search(text: string): Promise<DDO[]> { public async search(text: string): Promise<DDO[]> {
return AquariusProvider.getAquarius().queryMetadataByText({ return this.ocean.aquarius.queryMetadataByText({
text, text,
page: 0, page: 0,
offset: 100, offset: 100,

View File

@ -1,29 +1,24 @@
import SecretStoreProvider from "../secretstore/SecretStoreProvider" import SecretStoreProvider from "../secretstore/SecretStoreProvider"
import Account from "./Account" import Account from "./Account"
import { noDidPrefixed } from "../utils"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/** /**
* SecretStore submodule of Ocean Protocol. * SecretStore submodule of Ocean Protocol.
*/ */
export class OceanSecretStore { export class OceanSecretStore extends Instantiable {
/** /**
* Returns the instance of OceanSecretStore. * Returns the instance of OceanSecretStore.
* @return {Promise<OceanSecretStore>} * @return {Promise<OceanSecretStore>}
*/ */
public static async getInstance(): Promise<OceanSecretStore> { public static async getInstance(config: InstantiableConfig): Promise<OceanSecretStore> {
if (!OceanSecretStore.instance) { const instance = new OceanSecretStore()
OceanSecretStore.instance = new OceanSecretStore() instance.setInstanceConfig(config)
}
return OceanSecretStore.instance return instance
} }
/**
* OceanSecretStore instance.
* @type {OceanSecretStore}
*/
private static instance: OceanSecretStore = null
/** /**
* Encrypt the given text and store the encryption keys using the `did`. * Encrypt the given text and store the encryption keys using the `did`.
* The encrypted text can be decrypted using the same keys identified by the `did`. * The encrypted text can be decrypted using the same keys identified by the `did`.
@ -32,10 +27,9 @@ export class OceanSecretStore {
* @param {string} publisher Publisher account. * @param {string} publisher Publisher account.
* @return {Promise<string>} Encrypted text. * @return {Promise<string>} Encrypted text.
*/ */
public async encrypt(did: string, content: any, publisher: Account): Promise<string> { public async encrypt(did: string, content: any, publisher?: Account, secretStoreUrl?: string): Promise<string> {
return await this.getSecretStoreByAccount(publisher) return await this.getSecretStoreByAccount(publisher, secretStoreUrl)
// TODO did to id .encryptDocument(noDidPrefixed(did), content)
.encryptDocument(did, content)
} }
/** /**
@ -46,17 +40,22 @@ export class OceanSecretStore {
* @param {string} consumer cONSUMER account. * @param {string} consumer cONSUMER account.
* @return {Promise<string>} Encrypted text. * @return {Promise<string>} Encrypted text.
*/ */
public async decrypt(did: string, content: string, consumer: Account): Promise<any> { public async decrypt(did: string, content: string, consumer?: Account, secretStoreUrl?: string): Promise<any> {
return await this.getSecretStoreByAccount(consumer) return await this.getSecretStoreByAccount(consumer, secretStoreUrl)
// TODO did to id .decryptDocument(noDidPrefixed(did), content)
.decryptDocument(did, content)
} }
private getSecretStoreByAccount(account: Account) { private getSecretStoreByAccount(account: Account, secretStoreUrl?: string) {
const config: any = {address: account.getId()} const config: any = {...this.config}
if (account.getPassword()) { if (account) {
config.address = account.getId()
}
if (account && account.getPassword()) {
config.password = account.getPassword() config.password = account.getPassword()
} }
if (secretStoreUrl) {
config.secretStoreUri = secretStoreUrl
}
return SecretStoreProvider.getSecretStore(config) return SecretStoreProvider.getSecretStore(config)
} }
} }

View File

@ -1,29 +1,23 @@
import Keeper from "../keeper/Keeper" import Keeper from "../keeper/Keeper"
import Account from "./Account" import Account from "./Account"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/** /**
* Tokens submodule of Ocean Protocol. * Tokens submodule of Ocean Protocol.
*/ */
export class OceanTokens { 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(): Promise<OceanTokens> { public static async getInstance(config: InstantiableConfig): Promise<OceanTokens> {
if (!OceanTokens.instance) { const instance = new OceanTokens()
OceanTokens.instance = new OceanTokens() instance.setInstanceConfig(config)
}
return OceanTokens.instance return instance
} }
/**
* OceanTokens instance.
* @type {OceanTokens}
*/
private static instance: OceanTokens = null
/** /**
* 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 account.
@ -32,7 +26,7 @@ export class OceanTokens {
* @return {Promise<boolean>} Success, * @return {Promise<boolean>} Success,
*/ */
public async transfer(to: string, amount: number, from: Account): Promise<boolean> { public async transfer(to: string, amount: number, from: Account): Promise<boolean> {
(await Keeper.getInstance()) this.ocean.keeper
.token .token
.transfer(to, amount, from.getId()) .transfer(to, amount, from.getId())
return true return true

View File

@ -1,9 +1,9 @@
import * as Web3 from "web3"
import { ServiceAgreementTemplateCondition } from "../../ddo/ServiceAgreementTemplate" import { ServiceAgreementTemplateCondition } from "../../ddo/ServiceAgreementTemplate"
import { DDO } from "../../ddo/DDO" import { DDO } from "../../ddo/DDO"
import { ServiceAccess } from "../../ddo/Service" import { ServiceAccess } from "../../ddo/Service"
import Web3Provider from "../../keeper/Web3Provider"
import ValuePair from "../../models/ValuePair"
import LoggerInstance from "../../utils/Logger" import LoggerInstance from "../../utils/Logger"
import Web3Provider from "../../keeper/Web3Provider"
import Account from "../Account" import Account from "../Account"
import { signText, zeroX } from "../../utils" import { signText, zeroX } from "../../utils"
@ -11,6 +11,7 @@ import { signText, zeroX } from "../../utils"
export default class ServiceAgreement { export default class ServiceAgreement {
public static async signServiceAgreement( public static async signServiceAgreement(
web3: Web3,
ddo: DDO, ddo: DDO,
serviceDefinitionId: string, serviceDefinitionId: string,
serviceAgreementId: string, serviceAgreementId: string,
@ -27,6 +28,7 @@ export default class ServiceAgreement {
} }
const serviceAgreementHashSignature = await ServiceAgreement.createHashSignature( const serviceAgreementHashSignature = await ServiceAgreement.createHashSignature(
web3,
service.templateId, service.templateId,
serviceAgreementId, serviceAgreementId,
agreementConditionsIds, agreementConditionsIds,
@ -41,6 +43,7 @@ export default class ServiceAgreement {
} }
public static async createHashSignature( public static async createHashSignature(
web3: Web3,
templateId: string, templateId: string,
serviceAgreementId: string, serviceAgreementId: string,
valueHashes: string[], valueHashes: string[],
@ -57,7 +60,7 @@ export default class ServiceAgreement {
timeoutValues, timeoutValues,
) )
const serviceAgreementHashSignature = await signText(serviceAgreementHash, consumer.getId(), consumer.getPassword()) const serviceAgreementHashSignature = await signText(web3, serviceAgreementHash, consumer.getId(), consumer.getPassword())
return serviceAgreementHashSignature return serviceAgreementHashSignature
} }

View File

@ -1,42 +1,22 @@
import SecretStore from "@oceanprotocol/secret-store-client" import SecretStore from "@oceanprotocol/secret-store-client"
import SecretStoreConfig from "@oceanprotocol/secret-store-client/dist/models/SecretStoreConfig" import SecretStoreConfig from "@oceanprotocol/secret-store-client/dist/models/SecretStoreConfig"
import ConfigProvider from "../ConfigProvider"
import Config from "../models/Config"
export default class SecretStoreProvider { export default class SecretStoreProvider {
public static setSecretStore(secretStore: SecretStore) { public static getSecretStore(config: SecretStoreConfig): SecretStore {
const {secretStoreUri, parityUri, password, address, threshold} = config
SecretStoreProvider.secretStore = secretStore config = {secretStoreUri, parityUri, password, address, threshold}
}
public static getSecretStore(config?: Partial<SecretStoreConfig>): SecretStore {
config = {...config}
// Cleaning undefined parameters // Cleaning undefined parameters
Object.keys(config) Object.keys(config)
.forEach((key) => config[key] || delete config[key]) .forEach((key) => config[key] || config[key] === 0 || delete config[key])
if (!Object.keys(config).length) { const configRef = JSON.stringify(config)
if (!SecretStoreProvider.secretStore) { if (!SecretStoreProvider.secretStoreWithConfig.get(configRef)) {
SecretStoreProvider.secretStore = new SecretStore(ConfigProvider.getConfig()) SecretStoreProvider.secretStoreWithConfig.set(configRef, new SecretStore({...config}))
}
return SecretStoreProvider.secretStore
} else {
const configRef = JSON.stringify(config)
if (!SecretStoreProvider.secretStoreWithConfig.get(configRef)) {
SecretStoreProvider.secretStoreWithConfig.set(configRef,
new SecretStore({
...ConfigProvider.getConfig(),
...config,
}),
)
}
return SecretStoreProvider.secretStoreWithConfig.get(configRef)
} }
return SecretStoreProvider.secretStoreWithConfig.get(configRef)
} }
private static secretStore: SecretStore
private static secretStoreWithConfig = new Map<string, SecretStore>() private static secretStoreWithConfig = new Map<string, SecretStore>()
} }

View File

@ -2,7 +2,7 @@ import Config from "./models/Config"
import Account from "./ocean/Account" import Account from "./ocean/Account"
import DID from "./ocean/DID" import DID from "./ocean/DID"
import { Ocean } from "./ocean/Ocean" import { Ocean } from "./ocean/Ocean"
import LoggerInstance from "./utils/Logger" import { LoggerInstance as Logger} from "./utils/Logger"
import WebServiceConnectorProvider from "./utils/WebServiceConnectorProvider" import WebServiceConnectorProvider from "./utils/WebServiceConnectorProvider"
import Keeper from "./keeper/Keeper" import Keeper from "./keeper/Keeper"
import EventListener from "./keeper/EventListener" import EventListener from "./keeper/EventListener"
@ -24,9 +24,8 @@ export {
Account, Account,
Config, Config,
DID, DID,
EventListener, Logger,
Keeper, Keeper,
LoggerInstance,
WebServiceConnectorProvider, WebServiceConnectorProvider,
conditions, conditions,

View File

@ -11,7 +11,6 @@ export class Logger {
constructor(private logLevel: LogLevel = LogLevel.Verbose) { } constructor(private logLevel: LogLevel = LogLevel.Verbose) { }
public setLevel(logLevel: LogLevel) { public setLevel(logLevel: LogLevel) {
this.warn("Logger.setLevel is deprecated")
this.logLevel = logLevel this.logLevel = logLevel
} }

View File

@ -1,9 +1,8 @@
import Web3Provider from "../keeper/Web3Provider" import * as Web3 from "web3"
import LoggerInstance from "./Logger" import LoggerInstance from "./Logger"
export async function signText(text: string, publicKey: string, password?: string): Promise<string> {
const web3 = Web3Provider.getWeb3()
export async function signText(web3: Web3, text: string, publicKey: string, password?: string): Promise<string> {
try { try {
return await web3.eth.personal.sign(text, publicKey, password) return await web3.eth.personal.sign(text, publicKey, password)
} catch (e) { } catch (e) {
@ -19,8 +18,6 @@ export async function signText(text: string, publicKey: string, password?: strin
} }
} }
export async function verifyText(text: string, signature: string): Promise<string> { export async function verifyText(web3: Web3, text: string, signature: string): Promise<string> {
const web3 = Web3Provider.getWeb3()
return await web3.eth.personal.ecRecover(text, signature) return await web3.eth.personal.ecRecover(text, signature)
} }

View File

@ -1,5 +1,5 @@
import * as assert from "assert" import * as assert from "assert"
import Aquarius from "../../src/aquarius/Aquarius" import { Aquarius } from "../../src/aquarius/Aquarius"
import { SearchQuery } from "../../src/aquarius/query/SearchQuery" import { SearchQuery } from "../../src/aquarius/query/SearchQuery"
import { DDO } from "../../src/ddo/DDO" import { DDO } from "../../src/ddo/DDO"
import DID from "../../src/ocean/DID" import DID from "../../src/ocean/DID"
@ -9,7 +9,7 @@ import WebServiceConnectorMock from "../mocks/WebServiceConnector.mock"
describe("Aquarius", () => { describe("Aquarius", () => {
const aquarius: Aquarius = new Aquarius(config) const aquarius: Aquarius = new Aquarius(<any>{config})
describe("#queryMetadata()", () => { describe("#queryMetadata()", () => {

View File

@ -1,4 +1,7 @@
import { Config, LogLevel} from "../src/models/Config" import { Config, LogLevel } from "../src/models/Config"
import { LoggerInstance } from "../src/utils"
LoggerInstance.setLevel(LogLevel.Error)
export default { export default {
aquariusUri: "http://localhost:5000", aquariusUri: "http://localhost:5000",

View File

@ -1,10 +1,11 @@
import { assert, expect, spy, use } from "chai" import { assert, expect, spy, use } from "chai"
import * as spies from "chai-spies" import * as spies from "chai-spies"
import * as Web3 from "web3"
import ConfigProvider from "../../src/ConfigProvider"
import { DDO } from "../../src/ddo/DDO" import { DDO } from "../../src/ddo/DDO"
import { Service } from "../../src/ddo/Service" import { Service } from "../../src/ddo/Service"
import * as signatureHelpers from "../../src/utils/SignatureHelpers" import * as signatureHelpers from "../../src/utils/SignatureHelpers"
import { Ocean } from "../../src/ocean/Ocean"
import config from "../config" import config from "../config"
import * as jsonDDO from "../testdata/ddo.json" import * as jsonDDO from "../testdata/ddo.json"
@ -162,8 +163,10 @@ describe("DDO", () => {
], ],
}) })
before(async () => { let web3: Web3
ConfigProvider.setConfig(config)
beforeEach(async () => {
web3 = (await Ocean.getInstance(config) as any).web3
}) })
afterEach(() => { afterEach(() => {
@ -254,7 +257,7 @@ describe("DDO", () => {
const signTextSpy = spy.on(signatureHelpers, "signText", () => signature) const signTextSpy = spy.on(signatureHelpers, "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(publicKey) const proof = await ddo.generateProof(web3, publicKey)
assert.include(proof as any, { assert.include(proof as any, {
creator: publicKey, creator: publicKey,
@ -278,7 +281,7 @@ describe("DDO", () => {
} as any } as any
const ddo = new DDO(testDDO) const ddo = new DDO(testDDO)
const generateProofSpy = spy.on(ddo, "generateProof", () => fakeProof) const generateProofSpy = spy.on(ddo, "generateProof", () => fakeProof)
await ddo.addProof(publicKey) 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)

View File

@ -1,5 +1,4 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
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"
@ -12,11 +11,10 @@ let accounts: Account[]
describe("ContractWrapperBase", () => { describe("ContractWrapperBase", () => {
before(async () => { before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
await wrappedContract.initMock()
const ocean: Ocean = await Ocean.getInstance(config) const ocean: Ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts() accounts = await ocean.accounts.list()
await wrappedContract.initMock((<any>ocean).instanceConfig)
}) })
describe("#call()", () => { describe("#call()", () => {

View File

@ -0,0 +1,97 @@
import { assert } from "chai"
import { EventHandler } from "../../src/keeper/EventHandler"
import { ContractEventSubscription } from "../../src/keeper/ContractEvent"
import { Ocean } from "../../src/ocean/Ocean"
import config from "../config"
import TestContractHandler from "./TestContractHandler"
describe("ContractEvent", () => {
let ocean: Ocean
let account: string
let eventHandler: EventHandler
let executeTransaction: () => Promise<any>
beforeEach(async () => {
await TestContractHandler.prepareContracts()
ocean = await Ocean.getInstance(config)
eventHandler = new EventHandler((<any>ocean).instanceConfig)
account = (await ocean.accounts.list())[0].getId()
executeTransaction = () => ocean.keeper.dispenser.requestTokens(10, account)
})
describe("#subscribe()", () => {
it("should listen the events", async () => {
const event = eventHandler.getEvent(ocean.keeper.token, "Transfer", {to: account})
let validResolve = false
let subscription: ContractEventSubscription
const waitUntilEvent = new Promise(resolve => {
subscription = event.subscribe(events => {
assert.isDefined(events)
assert.lengthOf(events, 2)
if (validResolve) {
resolve()
}
})
})
await Promise.all([
executeTransaction(),
executeTransaction(),
])
await new Promise(_ => setTimeout(_, 2000))
validResolve = true
await Promise.all([
executeTransaction(),
executeTransaction(),
])
await waitUntilEvent
subscription.unsubscribe()
})
})
describe("#once()", () => {
it("should listen only once", async () => {
const to = account
const event = eventHandler.getEvent(ocean.keeper.token, "Transfer", {to})
let canBeRejected = false
const waitUntilEvent = new Promise((resolve, reject) => {
event.once(events => {
if (canBeRejected) {
reject()
}
setTimeout(resolve, 600)
})
})
await executeTransaction()
await new Promise(_ => setTimeout(_, 2000))
canBeRejected = true
await executeTransaction()
await waitUntilEvent
})
it("should get the event like a promise", async () => {
const to = account
const event = eventHandler.getEvent(ocean.keeper.token, "Transfer", {to})
const waitUntilEvent = event.once()
await new Promise(_ => setTimeout(_, 400))
await executeTransaction()
await waitUntilEvent
})
})
})

View File

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

View File

@ -1,10 +1,8 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import DIDRegistry from "../../src/keeper/contracts/DIDRegistry" import DIDRegistry from "../../src/keeper/contracts/DIDRegistry"
import Account from "../../src/ocean/Account" import Account from "../../src/ocean/Account"
import { Ocean } from "../../src/ocean/Ocean" import { Ocean } from "../../src/ocean/Ocean"
import { generateId } from "../../src/utils/GeneratorHelpers" import { generateId } from "../../src/utils/GeneratorHelpers"
import Logger from "../../src/utils/Logger"
import config from "../config" import config from "../config"
import TestContractHandler from "./TestContractHandler" import TestContractHandler from "./TestContractHandler"
@ -14,16 +12,15 @@ let didRegistry: DIDRegistry
describe("DIDRegistry", () => { describe("DIDRegistry", () => {
before(async () => { before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
ocean = await Ocean.getInstance(config) ocean = await Ocean.getInstance(config)
didRegistry = await DIDRegistry.getInstance() didRegistry = ocean.keeper.didRegistry
}) })
describe("#registerAttribute()", () => { describe("#registerAttribute()", () => {
it("should register an attribute in a new did", async () => { it("should register an attribute in a new did", async () => {
const ownerAccount: Account = (await ocean.getAccounts())[0] const ownerAccount: Account = (await ocean.accounts.list())[0]
const did = generateId() const did = generateId()
const data = "my nice provider, is nice" const data = "my nice provider, is nice"
const receipt = await didRegistry.registerAttribute(did, `0123456789abcdef`, data, ownerAccount.getId()) const receipt = await didRegistry.registerAttribute(did, `0123456789abcdef`, data, ownerAccount.getId())
@ -32,7 +29,7 @@ describe("DIDRegistry", () => {
}) })
it("should register another attribute in the same did", async () => { it("should register another attribute in the same did", async () => {
const ownerAccount: Account = (await ocean.getAccounts())[0] const ownerAccount: Account = (await ocean.accounts.list())[0]
const did = generateId() const did = generateId()
{ {
// register the first attribute // register the first attribute
@ -53,7 +50,7 @@ describe("DIDRegistry", () => {
// describe("#getOwner()", () => { // describe("#getOwner()", () => {
// it("should get the owner of a did properly", async () => { // it("should get the owner of a did properly", async () => {
// const ownerAccount: Account = (await ocean.getAccounts())[0] // const ownerAccount: Account = (await ocean.accounts.list())[0]
// const did = generateId() // const did = generateId()
// const data = "my nice provider, is nice" // const data = "my nice provider, is nice"
// await didRegistry.registerAttribute(did, "0123456789abcdef", data, ownerAccount.getId()) // await didRegistry.registerAttribute(did, "0123456789abcdef", data, ownerAccount.getId())
@ -73,7 +70,7 @@ describe("DIDRegistry", () => {
// describe("#getUpdateAt()", () => { // describe("#getUpdateAt()", () => {
// it("should the block number of the last update of the did attribute", async () => { // it("should the block number of the last update of the did attribute", async () => {
// const ownerAccount: Account = (await ocean.getAccounts())[0] // const ownerAccount: Account = (await ocean.accounts.list())[0]
// const did = generateId() // const did = generateId()
// const data = "my nice provider, is nice" // const data = "my nice provider, is nice"
// await didRegistry.registerAttribute(did, "0123456789abcdef", data, ownerAccount.getId()) // await didRegistry.registerAttribute(did, "0123456789abcdef", data, ownerAccount.getId())

View File

@ -1,85 +0,0 @@
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import EventListener from "../../src/keeper/EventListener"
import Keeper from "../../src/keeper/Keeper"
import Account from "../../src/ocean/Account"
import { Ocean } from "../../src/ocean/Ocean"
import config from "../config"
import TestContractHandler from "./TestContractHandler"
let keeper: Keeper
let ocean: Ocean
let accounts: Account[]
describe("EventListener", () => {
before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts()
keeper = await Keeper.getInstance()
assert(keeper)
ocean = await Ocean.getInstance(config)
assert(ocean)
accounts = await ocean.getAccounts()
assert(accounts)
})
describe("#listen()", () => {
it("should listen to an event", (done) => {
const acc = accounts[1]
const event = EventListener.subscribe("OceanToken",
"Transfer",
{
to: acc.getId(),
})
let doneCalled: boolean
event.listen((events) => {
assert(events)
assert(events.length === 2)
EventListener.unsubscribe(event)
if (!doneCalled) {
doneCalled = true
done()
}
})
const {dispenser} = keeper
dispenser.requestTokens(10, acc.getId())
dispenser.requestTokens(10, acc.getId())
})
})
describe("#listenOnce()", () => {
it("should listen once", (done) => {
const acc = accounts[1]
const countBefore = EventListener.count()
const event = EventListener.subscribe("OceanToken",
"Transfer",
{
to: acc.getId(),
})
event.listenOnce(
(data: any) => {
assert(data)
assert(data.blockNumber)
assert(EventListener.count() === countBefore)
done()
})
const {dispenser} = keeper
dispenser.requestTokens(10, acc.getId())
})
})
})

View File

@ -0,0 +1,89 @@
import { assert, expect, spy, use } from "chai"
import * as spies from "chai-spies"
import { EventHandler } from "../../src/keeper/EventHandler"
import { Ocean } from "../../src/ocean/Ocean"
import config from "../config"
use(spies)
describe("EventHandler", () => {
let ocean: Ocean
let eventHandler: EventHandler
before(async () => {
ocean = await Ocean.getInstance(config)
eventHandler = new EventHandler((<any>ocean).instanceConfig)
})
afterEach(() => {
spy.restore()
})
describe("#subscribe()", () => {
it("should subscribe to an event", async () => {
const countBefore = eventHandler.count
const subscription = eventHandler.subscribe(() => {})
assert.isDefined(subscription)
const countAfter = eventHandler.count
assert.equal(countBefore + 1, countAfter, "The event seems not added.")
try {
// Not important in this test
subscription.unsubscribe()
} catch(e) { }
})
it("should unsubscribe using the subscription", async () => {
const countBefore = eventHandler.count
const subscription = eventHandler.subscribe(() => {})
assert.isDefined(subscription)
subscription.unsubscribe()
const countAfter = eventHandler.count
assert.equal(countBefore, countAfter, "The event seems not added.")
})
})
describe("#unsubscribe()", () => {
it("should unsubscribe from an event", async () => {
const countBefore = eventHandler.count
const callback = () => {}
eventHandler.subscribe(callback)
eventHandler.unsubscribe(callback)
const countAfter = eventHandler.count
assert.equal(countBefore, countAfter, "The event seems not removed.")
})
})
describe("#checkBlock()", () => {
it("should call the callback on each new block", async () => {
let blockNumber = 100000000000
const callbackSpy = spy()
spy.on((ocean as any).web3.eth, "getBlockNumber", () => blockNumber)
const subscription = eventHandler.subscribe(callbackSpy)
await new Promise(_ => setTimeout(_, 300))
expect(callbackSpy).not.to.has.been.called()
blockNumber++
await new Promise(_ => setTimeout(_, 300))
expect(callbackSpy).to.has.been.called.with(blockNumber)
try {
// Not important in this test
subscription.unsubscribe()
} catch(e) { }
})
})
})

View File

@ -1,69 +0,0 @@
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import EventListener from "../../src/keeper/EventListener"
import Keeper from "../../src/keeper/Keeper"
import Account from "../../src/ocean/Account"
import { Ocean } from "../../src/ocean/Ocean"
import config from "../config"
import TestContractHandler from "./TestContractHandler"
let keeper: Keeper
let ocean: Ocean
let accounts: Account[]
describe("EventListener", () => {
before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts()
keeper = await Keeper.getInstance()
assert(keeper)
ocean = await Ocean.getInstance(config)
assert(ocean)
accounts = await ocean.getAccounts()
assert(accounts)
})
describe("#subscribe()", () => {
it("should subscribe to an event", (done) => {
const acc = accounts[1]
const countBefore = EventListener.count()
const event = EventListener.subscribe("OceanToken",
"Transfer",
{
to: acc.getId(),
})
assert(event)
const countAfter = EventListener.count()
assert(countBefore + 1 === countAfter, `${countBefore}${countAfter}`)
EventListener.unsubscribe(event)
done()
})
})
describe("#unsubscribe()", () => {
it("should unsubscribe from an event", (done) => {
const countBefore = EventListener.count()
const event = EventListener.subscribe("OceanToken",
"Transfer",
{})
const count = EventListener.count()
const unsubscribed = EventListener.unsubscribe(event)
assert(unsubscribed)
const countAfter = EventListener.count()
assert(count > countBefore, `${count}${countAfter}`)
assert(countBefore === countAfter, `${countBefore}${countAfter}`)
done()
})
})
})

View File

@ -1,17 +1,17 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import Keeper from "../../src/keeper/Keeper"
import config from "../config" import config from "../config"
import TestContractHandler from "./TestContractHandler" import TestContractHandler from "./TestContractHandler"
import Keeper from "../../src/keeper/Keeper"
import { Ocean } from "../../src/ocean/Ocean"
let keeper: Keeper let keeper: Keeper
describe("Keeper", () => { describe("Keeper", () => {
before(async () => { before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
keeper = await Keeper.getInstance() const ocean = await Ocean.getInstance(config)
keeper = ocean.keeper
}) })
describe("public interface", () => { describe("public interface", () => {

View File

@ -2,13 +2,16 @@ 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"
export default class TestContractHandler extends ContractHandler { export default class TestContractHandler extends ContractHandler {
public static async prepareContracts() { private static networkId: number
const web3 = Web3Provider.getWeb3() public static async prepareContracts() {
const web3 = Web3Provider.getWeb3(config)
const deployerAddress = (await web3.eth.getAccounts())[0] const deployerAddress = (await web3.eth.getAccounts())[0]
this.networkId = await web3.eth.net.getId()
// deploy contracts // deploy contracts
await TestContractHandler.deployContracts(deployerAddress) await TestContractHandler.deployContracts(deployerAddress)
@ -79,13 +82,17 @@ export default class TestContractHandler extends ContractHandler {
args: any[] = [], args: any[] = [],
tokens: {[name: string]: string} = {}, tokens: {[name: string]: string} = {},
): Promise<Contract & {$initialized: boolean}> { ): Promise<Contract & {$initialized: boolean}> {
const where = this.networkId
// dont redeploy if there is already something loaded // dont redeploy if there is already something loaded
if (ContractHandler.has(name)) { if (TestContractHandler.hasContract(name, where)) {
return {...await ContractHandler.get(name), $initialized: true} const contract = await ContractHandler.getContract(name, where)
if (contract.testContract) {
return {...contract, $initialized: true}
}
} }
const web3 = Web3Provider.getWeb3() const web3 = Web3Provider.getWeb3(config)
let contractInstance: Contract let contractInstance: Contract
try { try {
@ -117,7 +124,8 @@ export default class TestContractHandler extends ContractHandler {
if (isZos) { if (isZos) {
await contractInstance.methods.initialize(...args).send(sendConfig) await contractInstance.methods.initialize(...args).send(sendConfig)
} }
TestContractHandler.set(name, contractInstance) contractInstance.testContract = true
ContractHandler.setContract(name, where, contractInstance)
// Logger.log("Deployed", name, "at", contractInstance.options.address); // Logger.log("Deployed", name, "at", contractInstance.options.address);
} catch (err) { } catch (err) {
Logger.error("Deployment failed for", name, "with args", JSON.stringify(args, null, 2), err.message) Logger.error("Deployment failed for", name, "with args", JSON.stringify(args, null, 2), err.message)

View File

@ -1,7 +1,6 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../../src/ConfigProvider"
import { AccessSecretStoreCondition } from "../../../src/keeper/contracts/conditions" import { AccessSecretStoreCondition } from "../../../src/keeper/contracts/conditions"
import Keeper from "../../../src/keeper/Keeper" import { Ocean } from "../../../src/ocean/Ocean"
import config from "../../config" import config from "../../config"
import TestContractHandler from "../TestContractHandler" import TestContractHandler from "../TestContractHandler"
@ -10,14 +9,12 @@ let condition: AccessSecretStoreCondition
describe("AccessSecretStoreCondition", () => { describe("AccessSecretStoreCondition", () => {
const agreementId = `0x${"a".repeat(64)}` const agreementId = `0x${"a".repeat(64)}`
const did = `0x${"a".repeat(64)}` const did = `did:op:${"a".repeat(64)}`
const address = `0x${"a".repeat(40)}` const address = `0x${"a".repeat(40)}`
before(async () => { before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
condition = (await Keeper.getInstance()).conditions.accessSecretStoreCondition condition = (await Ocean.getInstance(config)).keeper.conditions.accessSecretStoreCondition
}) })
describe("#hashValues()", () => { describe("#hashValues()", () => {

View File

@ -1,7 +1,6 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../../src/ConfigProvider"
import { EscrowReward } from "../../../src/keeper/contracts/conditions" import { EscrowReward } from "../../../src/keeper/contracts/conditions"
import Keeper from "../../../src/keeper/Keeper" import { Ocean } from "../../../src/ocean/Ocean"
import config from "../../config" import config from "../../config"
import TestContractHandler from "../TestContractHandler" import TestContractHandler from "../TestContractHandler"
@ -18,9 +17,9 @@ describe("EscrowReward", () => {
let releaseCondition let releaseCondition
before(async () => { before(async () => {
ConfigProvider.setConfig(config) const keeper = (await Ocean.getInstance(config)).keeper
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
const keeper = await Keeper.getInstance()
condition = keeper.conditions.escrowReward condition = keeper.conditions.escrowReward
lockCondition = await keeper.conditions.lockRewardCondition.generateIdHash(agreementId, publisher, amount) lockCondition = await keeper.conditions.lockRewardCondition.generateIdHash(agreementId, publisher, amount)

View File

@ -1,7 +1,6 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../../src/ConfigProvider"
import { LockRewardCondition } from "../../../src/keeper/contracts/conditions" import { LockRewardCondition } from "../../../src/keeper/contracts/conditions"
import Keeper from "../../../src/keeper/Keeper" import { Ocean } from "../../../src/ocean/Ocean"
import config from "../../config" import config from "../../config"
import TestContractHandler from "../TestContractHandler" import TestContractHandler from "../TestContractHandler"
@ -14,10 +13,8 @@ describe("LockRewardCondition", () => {
const amount = 15 const amount = 15
before(async () => { before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
condition = (await Keeper.getInstance()).conditions.lockRewardCondition condition = (await Ocean.getInstance(config)).keeper.conditions.lockRewardCondition
}) })
describe("#hashValues()", () => { describe("#hashValues()", () => {

View File

@ -1,18 +1,18 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../../src/ConfigProvider"
import { EscrowAccessSecretStoreTemplate } from "../../../src/keeper/contracts/templates" import { EscrowAccessSecretStoreTemplate } from "../../../src/keeper/contracts/templates"
import Keeper from "../../../src/keeper/Keeper"
import config from "../../config" import config from "../../config"
import TestContractHandler from "../TestContractHandler" import TestContractHandler from "../TestContractHandler"
import { Ocean } from "../../../src/ocean/Ocean"
let condition: EscrowAccessSecretStoreTemplate let condition: EscrowAccessSecretStoreTemplate
describe("EscrowAccessSecretStoreTemplate", () => { describe("EscrowAccessSecretStoreTemplate", () => {
before(async () => { before(async () => {
ConfigProvider.setConfig(config) const ocean: Ocean = await Ocean.getInstance(config)
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
condition = (await Keeper.getInstance()).templates.escrowAccessSecretStoreTemplate condition = ocean.keeper.templates.escrowAccessSecretStoreTemplate
}) })

View File

@ -4,4 +4,4 @@
--bail --bail
--exit --exit
--timeout 20000 --timeout 20000
test/**/*.test.ts test/config.ts test/**/*.test.ts

View File

@ -1,4 +1,4 @@
import Aquarius from "../../src/aquarius/Aquarius" import { Aquarius } from "../../src/aquarius/Aquarius"
import { DDO } from "../../src/ddo/DDO" import { DDO } from "../../src/ddo/DDO"
import DID from "../../src/ocean/DID" import DID from "../../src/ocean/DID"

View File

@ -1,4 +1,4 @@
import Brizo from "../../src/brizo/Brizo" import { Brizo } from "../../src/brizo/Brizo"
export default class BrizoMock extends Brizo { export default class BrizoMock extends Brizo {

View File

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

View File

@ -1,5 +1,4 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import Web3Provider from "../../src/keeper/Web3Provider" import Web3Provider from "../../src/keeper/Web3Provider"
import Account from "../../src/ocean/Account" import Account from "../../src/ocean/Account"
import { Ocean } from "../../src/ocean/Ocean" import { Ocean } from "../../src/ocean/Ocean"
@ -12,11 +11,9 @@ let accounts: Account[]
describe("Account", () => { describe("Account", () => {
before(async () => { before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
ocean = await Ocean.getInstance(config) ocean = await Ocean.getInstance(config)
accounts = await ocean.accounts.list()
accounts = await ocean.getAccounts()
}) })
describe("#getOceanBalance()", () => { describe("#getOceanBalance()", () => {
@ -25,17 +22,17 @@ describe("Account", () => {
const balance = await accounts[8].getOceanBalance() const balance = await accounts[8].getOceanBalance()
assert(0 === balance, `Expected 0 got ${balance}`) assert.equal(0, balance, `Expected 0 got ${balance}`)
}) })
it("should get the correct balance", async () => { it("should get the correct balance", async () => {
const amount: number = 100 const amount: number = 100
const account: Account = accounts[0] const account: Account = accounts[0]
const initialBalance = await account.getOceanBalance()
await account.requestTokens(amount) await account.requestTokens(amount)
const balance = await account.getOceanBalance() const balance = await account.getOceanBalance()
assert(amount === balance) assert.equal(balance, initialBalance + amount)
}) })
}) })

View File

@ -1,23 +1,13 @@
import { assert, spy, use } from "chai" import { assert, spy, use } from "chai"
import * as spies from "chai-spies" import * as spies from "chai-spies"
import AquariusProvider from "../../src/aquarius/AquariusProvider"
import { SearchQuery } from "../../src/aquarius/query/SearchQuery" import { SearchQuery } from "../../src/aquarius/query/SearchQuery"
import BrizoProvider from "../../src/brizo/BrizoProvider"
import ConfigProvider from "../../src/ConfigProvider"
import { DDO } from "../../src/ddo/DDO" import { DDO } from "../../src/ddo/DDO"
import { Service } from "../../src/ddo/Service"
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 SecretStoreProvider from "../../src/secretstore/SecretStoreProvider"
import * as signatureHelpers from "../../src/utils/SignatureHelpers" import * as signatureHelpers from "../../src/utils/SignatureHelpers"
import WebServiceConnectorProvider from "../../src/utils/WebServiceConnectorProvider"
import config from "../config" import config from "../config"
import TestContractHandler from "../keeper/TestContractHandler" import TestContractHandler from "../keeper/TestContractHandler"
import AquariusMock from "../mocks/Aquarius.mock"
import BrizoMock from "../mocks/Brizo.mock"
import SecretStoreMock from "../mocks/SecretStore.mock"
import WebServiceConnectorMock from "../mocks/WebServiceConnector.mock"
import { metadataMock } from "../testdata/MetaData" import { metadataMock } from "../testdata/MetaData"
use(spies) use(spies)
@ -30,10 +20,6 @@ describe("Ocean", () => {
const metadata = metadataMock const metadata = metadataMock
before(async () => {
ConfigProvider.setConfig(config)
})
beforeEach(async () => { beforeEach(async () => {
spy.on(signatureHelpers, "signText", () => `0x${"a".repeat(130)}`) spy.on(signatureHelpers, "signText", () => `0x${"a".repeat(130)}`)
}) })
@ -42,13 +28,9 @@ describe("Ocean", () => {
}) })
before(async () => { before(async () => {
ConfigProvider.setConfig(config)
AquariusProvider.setAquarius(new AquariusMock(config))
BrizoProvider.setBrizo(new BrizoMock(config))
SecretStoreProvider.setSecretStore(new SecretStoreMock(config))
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
ocean = await Ocean.getInstance(config) ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts() accounts = await ocean.accounts.list()
testPublisher = accounts[0] testPublisher = accounts[0]
}) })
@ -65,7 +47,7 @@ describe("Ocean", () => {
describe("#getAccounts()", () => { describe("#getAccounts()", () => {
it("should list accounts", async () => { it("should list accounts", async () => {
const accs: Account[] = await ocean.getAccounts() const accs: Account[] = await ocean.accounts.list()
assert(10 === accs.length) assert(10 === accs.length)
assert(0 === (await accs[5].getBalance()).ocn) assert(0 === (await accs[5].getBalance()).ocn)
@ -73,28 +55,6 @@ describe("Ocean", () => {
}) })
}) })
// TODO: ensure if it should fail or not
describe("#resolveDID()", () => {
it("should resolve a did to a ddo", async () => {
const ddo: DDO = await ocean.registerAsset(metadata, testPublisher)
const resolvedDDO: DDO = await ocean.resolveDID(ddo.id)
assert(resolvedDDO)
assert(resolvedDDO.id === ddo.id)
})
})
// TODO: ensure if it should fail or not
describe("#registerAsset()", () => {
it("should register an asset", async () => {
const ddo: DDO = await ocean.registerAsset(metadata, testPublisher)
assert(ddo)
assert(ddo.id.startsWith("did:op:"))
})
})
describe("#searchAssets()", () => { describe("#searchAssets()", () => {
it("should search for assets", async () => { it("should search for assets", async () => {
const query = { const query = {
@ -109,7 +69,7 @@ describe("Ocean", () => {
text: "Office", text: "Office",
} as SearchQuery } as SearchQuery
const assets: any[] = await ocean.searchAssets(query) const assets: any[] = await ocean.assets.query(query)
assert(assets) assert(assets)
}) })
@ -118,33 +78,9 @@ describe("Ocean", () => {
describe("#searchAssetsByText()", () => { describe("#searchAssetsByText()", () => {
it("should search for assets", async () => { it("should search for assets", async () => {
const text = "office" const text = "office"
const assets: any[] = await ocean.searchAssetsByText(text) const assets: any[] = await ocean.assets.search(text)
assert(assets) assert(assets)
}) })
}) })
describe("#signServiceAgreement()", () => {
it("should sign an service agreement", async () => {
const publisher = accounts[0]
const consumer = accounts[1]
const ddo: DDO = await ocean.registerAsset(metadata, publisher)
const service: Service = ddo.findServiceByType("Access")
// @ts-ignore
WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo))
await consumer.requestTokens(metadata.base.price)
const signServiceAgreementResult: any = await ocean.signServiceAgreement(ddo.id, service.serviceDefinitionId, consumer)
assert(signServiceAgreementResult)
assert(signServiceAgreementResult.agreementId, "no agreementId")
assert(signServiceAgreementResult.signature, "no signature")
assert(signServiceAgreementResult.signature.startsWith("0x"))
assert(signServiceAgreementResult.signature.length === 132)
})
})
}) })

View File

@ -1,7 +1,9 @@
import { assert, /*expect,*/ spy, use } from "chai" import { assert, /*expect,*/ spy, use } from "chai"
import * as spies from "chai-spies" import * as spies from "chai-spies"
import config from "../config"
import Account from "../../src/ocean/Account" import Account from "../../src/ocean/Account"
import { Ocean } from "../../src/ocean/Ocean"
import { OceanAccounts } from "../../src/ocean/OceanAccounts" import { OceanAccounts } from "../../src/ocean/OceanAccounts"
use(spies) use(spies)
@ -11,21 +13,13 @@ describe("OceanAccounts", () => {
let oceanAccounts: OceanAccounts let oceanAccounts: OceanAccounts
before(async () => { before(async () => {
oceanAccounts = await OceanAccounts.getInstance() oceanAccounts = (await Ocean.getInstance(config)).accounts
}) })
afterEach(() => { afterEach(() => {
spy.restore() spy.restore()
}) })
describe("#getInstance()", () => {
it("should get an instance of OceanAccounts", async () => {
const oceanAccountsInstance: OceanAccounts = await OceanAccounts.getInstance()
assert.instanceOf(oceanAccountsInstance, OceanAccounts, "No returned OceanAccounts instance")
})
})
describe("#list()", () => { describe("#list()", () => {
it("should return the list of accounts", async () => { it("should return the list of accounts", async () => {
const accounts = await oceanAccounts.list() const accounts = await oceanAccounts.list()

View File

@ -1,7 +1,6 @@
import { assert, expect, spy, use } from "chai" import { assert, expect, spy, use } from "chai"
import * as spies from "chai-spies" import * as spies from "chai-spies"
import ConfigProvider from "../../src/ConfigProvider"
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 { OceanSecretStore } from "../../src/ocean/OceanSecretStore" import { OceanSecretStore } from "../../src/ocean/OceanSecretStore"
@ -15,37 +14,27 @@ describe("OceanSecretStore", () => {
let oceanSecretStore: OceanSecretStore let oceanSecretStore: OceanSecretStore
let accounts: Account[] let accounts: Account[]
const did = `did:op:${"a".repeat(64)}` const did = "a".repeat(64)
before(async () => { before(async () => {
oceanSecretStore = await OceanSecretStore.getInstance()
ConfigProvider.setConfig(config)
const ocean = await Ocean.getInstance(config) const ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts() oceanSecretStore = ocean.secretStore
accounts = await ocean.accounts.list()
}) })
afterEach(() => { afterEach(() => {
spy.restore() spy.restore()
}) })
describe("#getInstance()", () => {
it("should get an instance of OceanSecretStore", async () => {
const oceanSecretStoreInstance: OceanSecretStore = await OceanSecretStore.getInstance()
assert.instanceOf(oceanSecretStoreInstance, OceanSecretStore, "No returned OceanSecretStore instance")
})
})
describe("#encrypt()", () => { describe("#encrypt()", () => {
it("should encrypt a content", async () => { it("should encrypt a content", async () => {
const secretStoreToSpy = SecretStoreProvider.getSecretStore() const secretStoreToSpy = SecretStoreProvider.getSecretStore({...config, address: accounts[0].getId()})
const secretStoreEncryptSpy = spy.on(secretStoreToSpy, "encryptDocument", () => "encryptedResult") const secretStoreEncryptSpy = spy.on(secretStoreToSpy, "encryptDocument", () => "encryptedResult")
const secretStoreProviderGetInstanceSpy = spy.on(SecretStoreProvider, "getSecretStore", () => secretStoreToSpy) const secretStoreProviderGetInstanceSpy = spy.on(SecretStoreProvider, "getSecretStore", () => secretStoreToSpy)
const result = await oceanSecretStore.encrypt(did, "test", accounts[0]) const result = await oceanSecretStore.encrypt(did, "test", accounts[0])
expect(secretStoreProviderGetInstanceSpy).to.have.been.called.with({address: accounts[0].getId()}) expect(secretStoreProviderGetInstanceSpy).to.have.been.called.with({...config, address: accounts[0].getId()})
expect(secretStoreEncryptSpy).to.have.been.called.with(did, "test") expect(secretStoreEncryptSpy).to.have.been.called.with(did, "test")
assert.equal(result, "encryptedResult", "Result doesn't match") assert.equal(result, "encryptedResult", "Result doesn't match")
@ -54,13 +43,13 @@ describe("OceanSecretStore", () => {
describe("#decrypt()", () => { describe("#decrypt()", () => {
it("should decrypt a content", async () => { it("should decrypt a content", async () => {
const secretStoreToSpy = SecretStoreProvider.getSecretStore() const secretStoreToSpy = SecretStoreProvider.getSecretStore({...config, address: accounts[0].getId()})
const secretStoreEncryptSpy = spy.on(secretStoreToSpy, "decryptDocument", () => "decryptedResult") const secretStoreEncryptSpy = spy.on(secretStoreToSpy, "decryptDocument", () => "decryptedResult")
const secretStoreProviderGetInstanceSpy = spy.on(SecretStoreProvider, "getSecretStore", () => secretStoreToSpy) const secretStoreProviderGetInstanceSpy = spy.on(SecretStoreProvider, "getSecretStore", () => secretStoreToSpy)
const result = await oceanSecretStore.decrypt(did, "encryptedContent", accounts[0]) const result = await oceanSecretStore.decrypt(did, "encryptedContent", accounts[0])
expect(secretStoreProviderGetInstanceSpy).to.have.been.called.with({address: accounts[0].getId()}) expect(secretStoreProviderGetInstanceSpy).to.have.been.called.with({...config, address: accounts[0].getId()})
expect(secretStoreEncryptSpy).to.have.been.called.with(did, "encryptedContent") expect(secretStoreEncryptSpy).to.have.been.called.with(did, "encryptedContent")
assert.equal(result, "decryptedResult", "Result doesn't match") assert.equal(result, "decryptedResult", "Result doesn't match")

View File

@ -1,5 +1,4 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import { DDO } from "../../src/ddo/DDO" import { DDO } from "../../src/ddo/DDO"
import Account from "../../src/ocean/Account" import Account from "../../src/ocean/Account"
import DID from "../../src/ocean/DID" import DID from "../../src/ocean/DID"
@ -18,10 +17,9 @@ describe("ServiceAgreement", () => {
let consumerAccount: Account let consumerAccount: Account
before(async () => { before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts() await TestContractHandler.prepareContracts()
ocean = await Ocean.getInstance(config) ocean = await Ocean.getInstance(config)
const accounts = await ocean.getAccounts() const accounts = await ocean.accounts.list()
publisherAccount = accounts[1] publisherAccount = accounts[1]
consumerAccount = accounts[2] consumerAccount = accounts[2]

View File

@ -1,10 +1,8 @@
import { assert, expect, spy, use } from "chai" import { assert, expect, spy, use } from "chai"
import * as spies from "chai-spies" import * as spies from "chai-spies"
import ConfigProvider from "../../src/ConfigProvider"
import Web3Provider from "../../src/keeper/Web3Provider" import Web3Provider from "../../src/keeper/Web3Provider"
import { signText, verifyText } from "../../src/utils/SignatureHelpers" import { signText, verifyText } from "../../src/utils/SignatureHelpers"
import config from "../config"
use(spies) use(spies)
@ -13,10 +11,8 @@ describe("SignatureHelpers", () => {
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
before(async () => {
ConfigProvider.setConfig(config)
})
afterEach(() => { afterEach(() => {
spy.restore() spy.restore()
}) })
@ -25,19 +21,19 @@ describe("SignatureHelpers", () => {
let personalSignSpy let personalSignSpy
beforeEach(() => { beforeEach(() => {
const web3 = Web3Provider.getWeb3() web3 = Web3Provider.getWeb3()
personalSignSpy = spy.on(web3.eth.personal, "sign", () => signature) personalSignSpy = spy.on(web3.eth.personal, "sign", () => signature)
}) })
it("should sign a text as expected", async () => { it("should sign a text as expected", async () => {
const signed = await signText(text, publicKey) const signed = await signText(web3, text, publicKey)
assert.equal(signed, signature) assert.equal(signed, signature)
expect(personalSignSpy).to.have.been.called.with(text, publicKey) expect(personalSignSpy).to.have.been.called.with(text, publicKey)
}) })
it("should sign a text as expected using password", async () => { it("should sign a text as expected using password", async () => {
const signed = await signText(text, publicKey, "test") const signed = await signText(web3, text, publicKey, "test")
assert.equal(signed, signature) assert.equal(signed, signature)
expect(personalSignSpy).to.have.been.called.with(text, publicKey, "test") expect(personalSignSpy).to.have.been.called.with(text, publicKey, "test")
@ -49,7 +45,7 @@ describe("SignatureHelpers", () => {
const web3 = Web3Provider.getWeb3() const web3 = Web3Provider.getWeb3()
const personalRecoverSpy = spy.on(web3.eth.personal, "ecRecover", () => publicKey) const personalRecoverSpy = spy.on(web3.eth.personal, "ecRecover", () => publicKey)
const verifiedPublicKey = await verifyText(text, signature) const verifiedPublicKey = await verifyText(web3, text, signature)
assert.equal(publicKey, verifiedPublicKey) assert.equal(publicKey, verifiedPublicKey)
expect(personalRecoverSpy).to.have.been.called.with(text, signature) expect(personalRecoverSpy).to.have.been.called.with(text, signature)