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 { DDO } from "../ddo/DDO"
import Config from "../models/Config"
import DID from "../ocean/DID"
import LoggerInstance from "../utils/Logger"
import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider"
import { SearchQuery } from "./query/SearchQuery"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
const apiPath = "/api/v1/aquarius/assets/ddo"
@ -12,11 +11,14 @@ const apiPath = "/api/v1/aquarius/assets/ddo"
* Provides a interface with Aquarius.
* Aquarius provides an off-chain database store for metadata about data assets.
*/
export default class Aquarius {
private url: string
export class Aquarius extends Instantiable {
private get url() {
return this.config.aquariusUri
}
constructor(config: Config) {
this.url = config.aquariusUri
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
}
public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
@ -26,15 +28,15 @@ export default class Aquarius {
if (response.ok) {
return response.text()
}
LoggerInstance.error("Failed: ", response.status, response.statusText)
this.logger.error("Failed: ", response.status, response.statusText)
return null
})
.then((consumptionUrl: string): string => {
LoggerInstance.error("Success accessing consume endpoint: ", consumptionUrl)
this.logger.error("Success accessing consume endpoint: ", consumptionUrl)
return consumptionUrl
})
.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
})
@ -53,7 +55,7 @@ export default class Aquarius {
if (response.ok) {
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[]
})
.then((ddos) => {
@ -62,7 +64,7 @@ export default class Aquarius {
})
})
.catch((error) => {
LoggerInstance.error("Error fetching querying metadata: ", error)
this.logger.error("Error fetching querying metadata: ", error)
return [] as DDO[]
})
@ -86,7 +88,7 @@ export default class Aquarius {
if (response.ok) {
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[]
})
.then((ddos) => {
@ -95,7 +97,7 @@ export default class Aquarius {
})
})
.catch((error) => {
LoggerInstance.error("Error fetching querying metadata by text: ", error)
this.logger.error("Error fetching querying metadata by text: ", error)
return [] as DDO[]
})
@ -115,14 +117,14 @@ export default class Aquarius {
if (response.ok) {
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
})
.then((response: DDO) => {
return new DDO(response) as DDO
})
.catch((error) => {
LoggerInstance.error("Error fetching querying metadata: ", error)
this.logger.error("Error fetching querying metadata: ", error)
return null as DDO
})
@ -142,14 +144,14 @@ export default class Aquarius {
if (response.ok) {
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
})
.then((response: DDO) => {
return new DDO(response) as DDO
})
.catch((error) => {
LoggerInstance.error("Error fetching querying metadata: ", error)
this.logger.error("Error fetching querying metadata: ", error)
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 { File } from "../ddo/MetaData"
import Config from "../models/Config"
import Account from "../ocean/Account"
import LoggerInstance from "../utils/Logger"
import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
const apiPath = "/api/v1/brizo/services"
@ -11,11 +10,14 @@ const apiPath = "/api/v1/brizo/services"
* Provides a interface with Brizo.
* Brizo is the technical component executed by the Publishers allowing to them to provide extended data services.
*/
export default class Brizo {
private url: string
export class Brizo extends Instantiable {
private get url() {
return this.config.brizoUri
}
constructor(config: Config) {
this.url = config.brizoUri
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
}
public getPurchaseEndpoint() {
@ -55,7 +57,7 @@ export default class Brizo {
decodeURI(JSON.stringify(args)),
)
} catch (e) {
LoggerInstance.error(e)
this.logger.error(e)
throw new Error("HTTP request failed")
}
}
@ -81,8 +83,8 @@ export default class Brizo {
destination,
)
} catch (e) {
LoggerInstance.error("Error consuming assets")
LoggerInstance.error(e)
this.logger.error("Error consuming assets")
this.logger.error(e)
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 LoggerInstance from "../utils/Logger"
import * as signatureHelpers from "../utils/SignatureHelpers"
@ -88,7 +89,6 @@ export class DDO {
* @return {string[]} DDO checksum.
*/
public getChecksum(): string {
const web3 = Web3Provider.getWeb3()
const {metadata} = this.findServiceByType("Metadata")
const {files, name, author, license} = metadata.base
@ -102,19 +102,20 @@ export class DDO {
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.
* @param {Web3} web3 Web3 instance.
* @param {string} publicKey Public key to be used on personal sign.
* @param {string} password Password if it's requirted.
* @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 signature = await signatureHelpers.signText(checksum, publicKey, password)
const signature = await signatureHelpers.signText(web3, checksum, publicKey, password)
return {
created: (new Date()).toISOString(),
@ -138,14 +139,15 @@ export class 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} password Password if it's requirted.
* @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) {
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 LoggerInstance from "../utils/Logger"
import Keeper from "./Keeper"
import Web3Provider from "./Web3Provider"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
export default class ContractHandler {
export default class ContractHandler extends Instantiable {
public static async get(what: string): Promise<Contract> {
const where = (await (await Keeper.getInstance()).getNetworkName()).toLowerCase()
try {
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)
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
}
private static contracts: Map<string, Contract> = new Map<string, Contract>()
private static async load(what: string, where: string): Promise<Contract> {
const web3 = Web3Provider.getWeb3()
LoggerInstance.debug("Loading", what, "from", where)
private static getHash(what: string, networkId: number): string {
return `${what}/#${networkId}`
}
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`)
// 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") {
// no code in the blockchain dude
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)
ContractHandler.contracts.set(what, contract)
return ContractHandler.contracts.get(what)
this.logger.debug("Getting instance of", what, "from", where, "at address", artifact.address)
ContractHandler.setContract(what, networkId, contract)
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 { Condition, LockRewardCondition, EscrowReward, AccessSecretStoreCondition } from "./contracts/conditions"
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.
@ -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.
* - 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.
* @return {Promise<Keeper>}
*/
public static async getInstance(): Promise<Keeper> {
if (Keeper.instance === null) {
Keeper.instance = new Keeper()
public static async getInstance(config: InstantiableConfig): Promise<Keeper> {
const keeper = new Keeper()
keeper.setInstanceConfig(config)
// Main contracts
Keeper.instance.dispenser = await Dispenser.getInstance()
Keeper.instance.token = await OceanToken.getInstance()
Keeper.instance.didRegistry = await DIDRegistry.getInstance()
// Adding keeper inside Ocean to prevent `Keeper not defined yet` error
config.ocean.keeper = keeper
// Managers
Keeper.instance.templateStoreManager = await TemplateStoreManager.getInstance()
// Main contracts
keeper.dispenser = await Dispenser.getInstance(config)
keeper.token = await OceanToken.getInstance(config)
keeper.didRegistry = await DIDRegistry.getInstance(config)
// Conditions
Keeper.instance.conditions = {
lockRewardCondition: await LockRewardCondition.getInstance(),
escrowReward: await EscrowReward.getInstance(),
accessSecretStoreCondition: await AccessSecretStoreCondition.getInstance(),
}
// Managers
keeper.templateStoreManager = await TemplateStoreManager.getInstance(config)
keeper.agreementStoreManager = await AgreementStoreManager.getInstance(config)
keeper.conditionStoreManager = await ConditionStoreManager.getInstance(config)
// Conditions
Keeper.instance.templates = {
escrowAccessSecretStoreTemplate: await EscrowAccessSecretStoreTemplate.getInstance(),
}
// Conditions
keeper.conditions = {
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),
}
/**
* Keeper instance.
* @type {Keeper}
*/
private static instance: Keeper = null
// Utils
keeper.utils = {
eventHandler: new EventHandler(config),
}
return keeper
}
/**
* Ocean Token smart contract instance.
@ -78,6 +83,18 @@ export class Keeper {
*/
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.
*/
@ -94,6 +111,13 @@ export class Keeper {
escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate,
}
/**
* Helpers for contracts.
*/
public utils: {
eventHandler: EventHandler
}
/**
* Returns a condition by address.
* @param {string} address Address of deployed condition.
@ -109,12 +133,20 @@ export class Keeper {
.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.
* @return {Promise<string>} Network name.
*/
public async getNetworkName(): Promise<string> {
return Web3Provider.getWeb3().eth.net.getId()
public getNetworkName(): Promise<string> {
return this.web3.eth.net.getId()
.then((networkId) => {
let network: string = "Unknown"

View File

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

View File

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

View File

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

View File

@ -1,10 +1,12 @@
import ContractBase from "./ContractBase"
import { InstantiableConfig } from "../../Instantiable.abstract"
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)
await contract.init()
await contract.init(config)
return contract
}

View File

@ -1,11 +1,12 @@
import BigNumber from "bignumber.js"
import ContractBase from "./ContractBase"
import { InstantiableConfig } from "../../Instantiable.abstract"
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")
await token.init()
await token.init(config)
return token
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
import LoggerInstance from "../../../utils/Logger"
import ContractBase from "../ContractBase"
import { zeroX } from "../../../utils"
import { InstantiableConfig } from "../../../Instantiable.abstract"
export interface AgreementData {
did: string
@ -13,9 +13,9 @@ export interface AgreementData {
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")
await templateStoreManeger.init()
await templateStoreManeger.init(config)
return templateStoreManeger
}

View File

@ -1,7 +1,7 @@
import LoggerInstance from "../../../utils/Logger"
import ContractBase from "../ContractBase"
import { ConditionState } from "../conditions/Condition.abstract"
import { zeroX } from "../../../utils"
import { InstantiableConfig } from "../../../Instantiable.abstract"
export interface ConditionData {
typeRef: string
@ -15,9 +15,9 @@ export interface ConditionData {
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")
await templateStoreManeger.init()
await templateStoreManeger.init(config)
return templateStoreManeger
}

View File

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

View File

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

View File

@ -3,13 +3,14 @@ import { LockRewardCondition, EscrowReward, AccessSecretStoreCondition } from ".
import DIDRegistry from "../DIDRegistry"
import { DDO } from "../../../ddo/DDO"
import { generateId, zeroX } from "../../../utils"
import { InstantiableConfig } from "../../../Instantiable.abstract"
import { escrowAccessSecretStoreTemplateServiceAgreementTemplate } from "./EscrowAccessSecretStoreTemplate.serviceAgreementTemplate"
export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
public static async getInstance(): Promise<EscrowAccessSecretStoreTemplate> {
return AgreementTemplate.getInstance("EscrowAccessSecretStoreTemplate", EscrowAccessSecretStoreTemplate)
public static async getInstance(config: InstantiableConfig): Promise<EscrowAccessSecretStoreTemplate> {
return AgreementTemplate.getInstance(config, "EscrowAccessSecretStoreTemplate", EscrowAccessSecretStoreTemplate)
}
public async getServiceAgreementTemplate() {
@ -89,11 +90,9 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
}
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 lockRewardCondition = await LockRewardCondition.getInstance()
const escrowReward = await EscrowReward.getInstance()
const {accessSecretStoreCondition, lockRewardCondition, escrowReward} = conditions
const publisher = await didRegistry.getDIDOwner(did)

View File

@ -1,17 +1,21 @@
import BigNumber from "bignumber.js"
import * as EthJsUtils from "ethereumjs-util"
import Keeper from "../keeper/Keeper"
import Web3Provider from "../keeper/Web3Provider"
import Balance from "../models/Balance"
import LoggerInstance from "../utils/Logger"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/**
* Account information.
*/
export default class Account {
export default class Account extends Instantiable {
private password?: string
constructor(private id: string = "0x0") { }
constructor(private id: string = "0x0", config?: InstantiableConfig) {
super()
if (config) {
this.setInstanceConfig(config)
}
}
public getId() {
return this.id
@ -42,7 +46,7 @@ export default class Account {
* @return {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())
}
@ -51,13 +55,10 @@ export default class Account {
* @return {Promise<number>}
*/
public async getEtherBalance(): Promise<number> {
// Logger.log("getting balance for", account);
return Web3Provider
.getWeb3()
return this.web3
.eth
.getBalance(this.id, "latest")
.then((balance: string): number => {
// Logger.log("balance", balance);
return new BigNumber(balance).toNumber()
})
}
@ -80,11 +81,11 @@ export default class Account {
*/
public async requestTokens(amount: number): Promise<number> {
try {
await (await Keeper.getInstance())
await this.ocean.keeper
.dispenser
.requestTokens(amount, this.id)
} catch (e) {
LoggerInstance.error(e)
this.logger.error(e)
throw new Error("Error requesting tokens")
}
@ -96,11 +97,8 @@ export default class Account {
* @return {Promise<string>}
*/
public async getPublicKey(): Promise<string> {
const web3 = Web3Provider.getWeb3()
const msg = web3.utils.sha3(this.getId())
const sig = await web3.eth.sign(msg, this.getId())
const msg = this.web3.utils.sha3(this.getId())
const sig = await this.web3.eth.sign(msg, this.getId())
const {v, r, s} = EthJsUtils.fromRpcSig(sig)
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 { OceanAgreements } from "./OceanAgreements"
import { OceanAssets } from "./OceanAssets"
import { OceanSecretStore } from "./OceanSecretStore"
import { OceanTokens } from "./OceanTokens"
import AquariusProvider from "../aquarius/AquariusProvider"
import { SearchQuery } from "../aquarius/query/SearchQuery"
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 { Aquarius } from "../aquarius/Aquarius"
import { Brizo } from "../brizo/Brizo"
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.
*/
export class Ocean {
export class Ocean extends Instantiable {
/**
* Returns the instance of Ocean.
@ -35,33 +24,46 @@ export class Ocean {
* @return {Promise<Ocean>}
*/
public static async getInstance(config: Config): Promise<Ocean> {
ConfigProvider.setConfig(config)
const instance = new Ocean()
if (!Ocean.instance) {
Ocean.instance = new Ocean()
Ocean.instance.keeper = await Keeper.getInstance()
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()
const instanceConfig = {
...generateIntantiableConfigFromConfig(config),
ocean: instance,
}
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.
* @type {Keeper}
*/
public keeper: Keeper
/**
* Brizo instance.
* @type {Brizo}
*/
public brizo: Brizo
/**
* Aquarius instance.
* @type {Aquarius}
*/
public aquarius: Aquarius
/**
* Ocean account submodule
* @type {OceanAccounts}
@ -92,158 +94,7 @@ export class Ocean {
*/
public tokens: OceanTokens
private constructor() { }
/**
* 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)
private constructor() {
super()
}
}

View File

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

View File

@ -1,32 +1,22 @@
import Keeper from "../keeper/Keeper"
import Account from "./Account"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/**
* Agreements Conditions submodule of Ocean Protocol.
*/
export class OceanAgreementsConditions {
export class OceanAgreementsConditions extends Instantiable {
/**
* Returns the instance of OceanAgreementsConditions.
* @return {Promise<OceanAgreementsConditions>}
*/
public static async getInstance(): Promise<OceanAgreementsConditions> {
if (!OceanAgreementsConditions.instance) {
OceanAgreementsConditions.instance = new OceanAgreementsConditions()
OceanAgreementsConditions.instance.keeper = await Keeper.getInstance()
}
public static async getInstance(config: InstantiableConfig): Promise<OceanAgreementsConditions> {
const instance = new OceanAgreementsConditions()
instance.setInstanceConfig(config)
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.
* 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 {Account} from Account of sender.
*/
public async lockReward(agreementId: string, amount: number, from: Account = new Account()) {
const {lockRewardCondition, escrowReward} = this.keeper.conditions
public async lockReward(agreementId: string, amount: number, from?: Account) {
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
}
@ -50,10 +40,10 @@ export class OceanAgreementsConditions {
* @param {string} grantee Consumer address.
* @param {Account} from Account of sender.
*/
public async grantAccess(agreementId: string, did: string, grantee: string, from: Account = new Account()) {
const {accessSecretStoreCondition} = this.keeper.conditions
public async grantAccess(agreementId: string, did: string, grantee: string, from?: Account) {
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
}
@ -76,9 +66,9 @@ export class OceanAgreementsConditions {
did: string,
consumer: 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 conditionIdLock = await lockRewardCondition.generateIdHash(agreementId, escrowReward.getAddress(), amount)
@ -90,7 +80,7 @@ export class OceanAgreementsConditions {
consumer,
conditionIdLock,
conditionIdAccess,
from.getId(),
from && from.getId(),
)
return !!receipt.events.Fulfilled
}

View File

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

View File

@ -1,29 +1,24 @@
import SecretStoreProvider from "../secretstore/SecretStoreProvider"
import Account from "./Account"
import { noDidPrefixed } from "../utils"
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
/**
* SecretStore submodule of Ocean Protocol.
*/
export class OceanSecretStore {
export class OceanSecretStore extends Instantiable {
/**
* Returns the instance of OceanSecretStore.
* @return {Promise<OceanSecretStore>}
*/
public static async getInstance(): Promise<OceanSecretStore> {
if (!OceanSecretStore.instance) {
OceanSecretStore.instance = new OceanSecretStore()
}
public static async getInstance(config: InstantiableConfig): Promise<OceanSecretStore> {
const 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`.
* 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.
* @return {Promise<string>} Encrypted text.
*/
public async encrypt(did: string, content: any, publisher: Account): Promise<string> {
return await this.getSecretStoreByAccount(publisher)
// TODO did to id
.encryptDocument(did, content)
public async encrypt(did: string, content: any, publisher?: Account, secretStoreUrl?: string): Promise<string> {
return await this.getSecretStoreByAccount(publisher, secretStoreUrl)
.encryptDocument(noDidPrefixed(did), content)
}
/**
@ -46,17 +40,22 @@ export class OceanSecretStore {
* @param {string} consumer cONSUMER account.
* @return {Promise<string>} Encrypted text.
*/
public async decrypt(did: string, content: string, consumer: Account): Promise<any> {
return await this.getSecretStoreByAccount(consumer)
// TODO did to id
.decryptDocument(did, content)
public async decrypt(did: string, content: string, consumer?: Account, secretStoreUrl?: string): Promise<any> {
return await this.getSecretStoreByAccount(consumer, secretStoreUrl)
.decryptDocument(noDidPrefixed(did), content)
}
private getSecretStoreByAccount(account: Account) {
const config: any = {address: account.getId()}
if (account.getPassword()) {
private getSecretStoreByAccount(account: Account, secretStoreUrl?: string) {
const config: any = {...this.config}
if (account) {
config.address = account.getId()
}
if (account && account.getPassword()) {
config.password = account.getPassword()
}
if (secretStoreUrl) {
config.secretStoreUri = secretStoreUrl
}
return SecretStoreProvider.getSecretStore(config)
}
}

View File

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

View File

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

View File

@ -1,42 +1,22 @@
import SecretStore from "@oceanprotocol/secret-store-client"
import SecretStoreConfig from "@oceanprotocol/secret-store-client/dist/models/SecretStoreConfig"
import ConfigProvider from "../ConfigProvider"
import Config from "../models/Config"
export default class SecretStoreProvider {
public static setSecretStore(secretStore: SecretStore) {
SecretStoreProvider.secretStore = secretStore
}
public static getSecretStore(config?: Partial<SecretStoreConfig>): SecretStore {
config = {...config}
public static getSecretStore(config: SecretStoreConfig): SecretStore {
const {secretStoreUri, parityUri, password, address, threshold} = config
config = {secretStoreUri, parityUri, password, address, threshold}
// Cleaning undefined parameters
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) {
if (!SecretStoreProvider.secretStore) {
SecretStoreProvider.secretStore = new SecretStore(ConfigProvider.getConfig())
}
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)
const configRef = JSON.stringify(config)
if (!SecretStoreProvider.secretStoreWithConfig.get(configRef)) {
SecretStoreProvider.secretStoreWithConfig.set(configRef, new SecretStore({...config}))
}
return SecretStoreProvider.secretStoreWithConfig.get(configRef)
}
private static secretStore: 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 DID from "./ocean/DID"
import { Ocean } from "./ocean/Ocean"
import LoggerInstance from "./utils/Logger"
import { LoggerInstance as Logger} from "./utils/Logger"
import WebServiceConnectorProvider from "./utils/WebServiceConnectorProvider"
import Keeper from "./keeper/Keeper"
import EventListener from "./keeper/EventListener"
@ -24,9 +24,8 @@ export {
Account,
Config,
DID,
EventListener,
Logger,
Keeper,
LoggerInstance,
WebServiceConnectorProvider,
conditions,

View File

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

View File

@ -1,9 +1,8 @@
import Web3Provider from "../keeper/Web3Provider"
import * as Web3 from "web3"
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 {
return await web3.eth.personal.sign(text, publicKey, password)
} 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> {
const web3 = Web3Provider.getWeb3()
export async function verifyText(web3: Web3, text: string, signature: string): Promise<string> {
return await web3.eth.personal.ecRecover(text, signature)
}

View File

@ -1,5 +1,5 @@
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 { DDO } from "../../src/ddo/DDO"
import DID from "../../src/ocean/DID"
@ -9,7 +9,7 @@ import WebServiceConnectorMock from "../mocks/WebServiceConnector.mock"
describe("Aquarius", () => {
const aquarius: Aquarius = new Aquarius(config)
const aquarius: Aquarius = new Aquarius(<any>{config})
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 {
aquariusUri: "http://localhost:5000",

View File

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

View File

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

View File

@ -1,10 +1,8 @@
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import DIDRegistry from "../../src/keeper/contracts/DIDRegistry"
import Account from "../../src/ocean/Account"
import { Ocean } from "../../src/ocean/Ocean"
import { generateId } from "../../src/utils/GeneratorHelpers"
import Logger from "../../src/utils/Logger"
import config from "../config"
import TestContractHandler from "./TestContractHandler"
@ -14,16 +12,15 @@ let didRegistry: DIDRegistry
describe("DIDRegistry", () => {
before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts()
ocean = await Ocean.getInstance(config)
didRegistry = await DIDRegistry.getInstance()
didRegistry = ocean.keeper.didRegistry
})
describe("#registerAttribute()", () => {
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 data = "my nice provider, is nice"
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 () => {
const ownerAccount: Account = (await ocean.getAccounts())[0]
const ownerAccount: Account = (await ocean.accounts.list())[0]
const did = generateId()
{
// register the first attribute
@ -53,7 +50,7 @@ describe("DIDRegistry", () => {
// describe("#getOwner()", () => {
// 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 data = "my nice provider, is nice"
// await didRegistry.registerAttribute(did, "0123456789abcdef", data, ownerAccount.getId())
@ -73,7 +70,7 @@ describe("DIDRegistry", () => {
// describe("#getUpdateAt()", () => {
// 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 data = "my nice provider, is nice"
// 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 ConfigProvider from "../../src/ConfigProvider"
import Keeper from "../../src/keeper/Keeper"
import config from "../config"
import TestContractHandler from "./TestContractHandler"
import Keeper from "../../src/keeper/Keeper"
import { Ocean } from "../../src/ocean/Ocean"
let keeper: Keeper
describe("Keeper", () => {
before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts()
keeper = await Keeper.getInstance()
const ocean = await Ocean.getInstance(config)
keeper = ocean.keeper
})
describe("public interface", () => {

View File

@ -2,13 +2,16 @@ import Contract from "web3-eth-contract"
import ContractHandler from "../../src/keeper/ContractHandler"
import Web3Provider from "../../src/keeper/Web3Provider"
import Logger from "../../src/utils/Logger"
import config from "../config"
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]
this.networkId = await web3.eth.net.getId()
// deploy contracts
await TestContractHandler.deployContracts(deployerAddress)
@ -79,13 +82,17 @@ export default class TestContractHandler extends ContractHandler {
args: any[] = [],
tokens: {[name: string]: string} = {},
): Promise<Contract & {$initialized: boolean}> {
const where = this.networkId
// dont redeploy if there is already something loaded
if (ContractHandler.has(name)) {
return {...await ContractHandler.get(name), $initialized: true}
if (TestContractHandler.hasContract(name, where)) {
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
try {
@ -117,7 +124,8 @@ export default class TestContractHandler extends ContractHandler {
if (isZos) {
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);
} catch (err) {
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 ConfigProvider from "../../../src/ConfigProvider"
import { AccessSecretStoreCondition } from "../../../src/keeper/contracts/conditions"
import Keeper from "../../../src/keeper/Keeper"
import { Ocean } from "../../../src/ocean/Ocean"
import config from "../../config"
import TestContractHandler from "../TestContractHandler"
@ -10,14 +9,12 @@ let condition: AccessSecretStoreCondition
describe("AccessSecretStoreCondition", () => {
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)}`
before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts()
condition = (await Keeper.getInstance()).conditions.accessSecretStoreCondition
condition = (await Ocean.getInstance(config)).keeper.conditions.accessSecretStoreCondition
})
describe("#hashValues()", () => {

View File

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

View File

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

View File

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

View File

@ -4,4 +4,4 @@
--bail
--exit
--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 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 {

View File

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

View File

@ -1,5 +1,4 @@
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import Web3Provider from "../../src/keeper/Web3Provider"
import Account from "../../src/ocean/Account"
import { Ocean } from "../../src/ocean/Ocean"
@ -12,11 +11,9 @@ let accounts: Account[]
describe("Account", () => {
before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts()
ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts()
accounts = await ocean.accounts.list()
})
describe("#getOceanBalance()", () => {
@ -25,17 +22,17 @@ describe("Account", () => {
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 () => {
const amount: number = 100
const account: Account = accounts[0]
const initialBalance = await account.getOceanBalance()
await account.requestTokens(amount)
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 * as spies from "chai-spies"
import AquariusProvider from "../../src/aquarius/AquariusProvider"
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 { Service } from "../../src/ddo/Service"
import Account from "../../src/ocean/Account"
import { Ocean } from "../../src/ocean/Ocean"
import SecretStoreProvider from "../../src/secretstore/SecretStoreProvider"
import * as signatureHelpers from "../../src/utils/SignatureHelpers"
import WebServiceConnectorProvider from "../../src/utils/WebServiceConnectorProvider"
import config from "../config"
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"
use(spies)
@ -30,10 +20,6 @@ describe("Ocean", () => {
const metadata = metadataMock
before(async () => {
ConfigProvider.setConfig(config)
})
beforeEach(async () => {
spy.on(signatureHelpers, "signText", () => `0x${"a".repeat(130)}`)
})
@ -42,13 +28,9 @@ describe("Ocean", () => {
})
before(async () => {
ConfigProvider.setConfig(config)
AquariusProvider.setAquarius(new AquariusMock(config))
BrizoProvider.setBrizo(new BrizoMock(config))
SecretStoreProvider.setSecretStore(new SecretStoreMock(config))
await TestContractHandler.prepareContracts()
ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts()
accounts = await ocean.accounts.list()
testPublisher = accounts[0]
})
@ -65,7 +47,7 @@ describe("Ocean", () => {
describe("#getAccounts()", () => {
it("should list accounts", async () => {
const accs: Account[] = await ocean.getAccounts()
const accs: Account[] = await ocean.accounts.list()
assert(10 === accs.length)
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()", () => {
it("should search for assets", async () => {
const query = {
@ -109,7 +69,7 @@ describe("Ocean", () => {
text: "Office",
} as SearchQuery
const assets: any[] = await ocean.searchAssets(query)
const assets: any[] = await ocean.assets.query(query)
assert(assets)
})
@ -118,33 +78,9 @@ describe("Ocean", () => {
describe("#searchAssetsByText()", () => {
it("should search for assets", async () => {
const text = "office"
const assets: any[] = await ocean.searchAssetsByText(text)
const assets: any[] = await ocean.assets.search(text)
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 * as spies from "chai-spies"
import config from "../config"
import Account from "../../src/ocean/Account"
import { Ocean } from "../../src/ocean/Ocean"
import { OceanAccounts } from "../../src/ocean/OceanAccounts"
use(spies)
@ -11,21 +13,13 @@ describe("OceanAccounts", () => {
let oceanAccounts: OceanAccounts
before(async () => {
oceanAccounts = await OceanAccounts.getInstance()
oceanAccounts = (await Ocean.getInstance(config)).accounts
})
afterEach(() => {
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()", () => {
it("should return the list of accounts", async () => {
const accounts = await oceanAccounts.list()

View File

@ -1,7 +1,6 @@
import { assert, expect, spy, use } from "chai"
import * as spies from "chai-spies"
import ConfigProvider from "../../src/ConfigProvider"
import Account from "../../src/ocean/Account"
import { Ocean } from "../../src/ocean/Ocean"
import { OceanSecretStore } from "../../src/ocean/OceanSecretStore"
@ -15,37 +14,27 @@ describe("OceanSecretStore", () => {
let oceanSecretStore: OceanSecretStore
let accounts: Account[]
const did = `did:op:${"a".repeat(64)}`
const did = "a".repeat(64)
before(async () => {
oceanSecretStore = await OceanSecretStore.getInstance()
ConfigProvider.setConfig(config)
const ocean = await Ocean.getInstance(config)
accounts = await ocean.getAccounts()
oceanSecretStore = ocean.secretStore
accounts = await ocean.accounts.list()
})
afterEach(() => {
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()", () => {
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 secretStoreProviderGetInstanceSpy = spy.on(SecretStoreProvider, "getSecretStore", () => secretStoreToSpy)
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")
assert.equal(result, "encryptedResult", "Result doesn't match")
@ -54,13 +43,13 @@ describe("OceanSecretStore", () => {
describe("#decrypt()", () => {
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 secretStoreProviderGetInstanceSpy = spy.on(SecretStoreProvider, "getSecretStore", () => secretStoreToSpy)
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")
assert.equal(result, "decryptedResult", "Result doesn't match")

View File

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

View File

@ -1,10 +1,8 @@
import { assert, expect, spy, use } from "chai"
import * as spies from "chai-spies"
import ConfigProvider from "../../src/ConfigProvider"
import Web3Provider from "../../src/keeper/Web3Provider"
import { signText, verifyText } from "../../src/utils/SignatureHelpers"
import config from "../config"
use(spies)
@ -13,10 +11,8 @@ describe("SignatureHelpers", () => {
const publicKey = `0x${"a".repeat(40)}`
const text = "0123456789abcde"
const signature = `0x${"a".repeat(130)}`
let web3
before(async () => {
ConfigProvider.setConfig(config)
})
afterEach(() => {
spy.restore()
})
@ -25,19 +21,19 @@ describe("SignatureHelpers", () => {
let personalSignSpy
beforeEach(() => {
const web3 = Web3Provider.getWeb3()
web3 = Web3Provider.getWeb3()
personalSignSpy = spy.on(web3.eth.personal, "sign", () => signature)
})
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)
expect(personalSignSpy).to.have.been.called.with(text, publicKey)
})
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)
expect(personalSignSpy).to.have.been.called.with(text, publicKey, "test")
@ -49,7 +45,7 @@ describe("SignatureHelpers", () => {
const web3 = Web3Provider.getWeb3()
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)
expect(personalRecoverSpy).to.have.been.called.with(text, signature)