formatting and typings and lint fixes

This commit is contained in:
Matthias Kretschmann 2020-08-18 11:23:46 +02:00
parent ea5f505edf
commit 7b1403c854
Signed by: m
GPG Key ID: 606EEEF3C479A91F
81 changed files with 6748 additions and 6929 deletions

View File

@ -1,15 +0,0 @@
# https://editorconfig.org
root = true
[*]
charset = utf-8
indent_size = 4
end_of_line = lf
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{json,yml,yaml,md}]
indent_size = 2

View File

@ -1,6 +1,7 @@
{
"semi": false,
"singleQuote": true,
"printWidth": 90,
"trailingComma": "none"
"semi": false,
"singleQuote": true,
"printWidth": 90,
"trailingComma": "none",
"tabWidth": 2
}

View File

@ -5,12 +5,12 @@ const packageInfo = require('../package.json')
const execSync = require('child_process').execSync
process.stdout.write(
JSON.stringify(
{
version: require('../package.json').version,
commit: execSync(`git rev-parse HEAD`).toString().trim()
},
null,
' '
)
JSON.stringify(
{
version: require('../package.json').version,
commit: execSync(`git rev-parse HEAD`).toString().trim()
},
null,
' '
)
)

View File

@ -18,39 +18,39 @@ const files = ['./src/lib.ts']
const config = typescript.findConfigFile('./tsconfig.js', typescript.sys.fileExists)
const generateJson = () => {
const spinnerTypedoc = ora('Generating TypeDoc json...').start()
const spinnerTypedoc = ora('Generating TypeDoc json...').start()
// Setup our TypeDoc app
const app = new TypeDoc.Application()
app.options.addReader(new TypeDoc.TSConfigReader())
app.options.addReader(new TypeDoc.TypeDocReader())
// Setup our TypeDoc app
const app = new TypeDoc.Application()
app.options.addReader(new TypeDoc.TSConfigReader())
app.options.addReader(new TypeDoc.TypeDocReader())
app.bootstrap({
tsconfig: config
})
app.bootstrap({
tsconfig: config
})
const src = app.expandInputFiles(files)
const project = app.convert(src)
const src = app.expandInputFiles(files)
const project = app.convert(src)
// Generate the JSON file
app.generateJson(project, outPath)
// Generate the JSON file
app.generateJson(project, outPath)
// Parse and modify json output
const jsonOrig = JSON.parse(fs.readFileSync(outPath, 'utf8'))
// Parse and modify json output
const jsonOrig = JSON.parse(fs.readFileSync(outPath, 'utf8'))
const jsonFinal = {
info: {
title: 'Lib-js',
description,
version,
sourceUrl: 'https://github.com/oceanprotocol/ocean-lib-js/blob/master/'
},
...jsonOrig
}
const jsonFinal = {
info: {
title: 'Lib-js',
description,
version,
sourceUrl: 'https://github.com/oceanprotocol/ocean-lib-js/blob/master/'
},
...jsonOrig
}
fs.writeFileSync(outPath, JSON.stringify(jsonFinal, null, 4))
fs.writeFileSync(outPath, JSON.stringify(jsonFinal, null, 4))
spinnerTypedoc.succeed('Generated TypeDoc json.')
spinnerTypedoc.succeed('Generated TypeDoc json.')
}
generateJson()

View File

@ -1,48 +0,0 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"jsx": false
},
"project": [
"./tsconfig.json",
"./test/unit/tsconfig.json",
"./test/integration/tsconfig.json"
]
},
"extends": [
"oceanprotocol",
"prettier/standard",
"plugin:prettier/recommended",
"plugin:@typescript-eslint/recommended",
"prettier/@typescript-eslint"
],
"plugins": ["@typescript-eslint", "prettier"],
"rules": {
"@typescript-eslint/member-delimiter-style": [
"error",
{ "multiline": { "delimiter": "none" } }
],
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/indent": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-member-accessibility": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-object-literal-type-assertion": "off",
"@typescript-eslint/no-parameter-properties": "off",
"no-empty": ["error", { "allowEmptyCatch": true }],
"prefer-destructuring": ["warn"],
"no-dupe-class-members": ["warn"],
"no-useless-constructor": ["warn"]
},
"env": {
"es6": true,
"browser": true,
"mocha": true
}
}

View File

@ -4,89 +4,89 @@ import { Logger, LoggerInstance, LogLevel } from './utils'
import { Ocean } from './ocean/Ocean'
export interface InstantiableConfig {
ocean: Ocean
config?: Config
web3?: Web3
logger?: Logger
ocean: Ocean
config?: Config
web3?: Web3
logger?: Logger
}
export function generateIntantiableConfigFromConfig(
config: Config
config: Config
): Partial<InstantiableConfig> {
const logLevel =
typeof config.verbose !== 'number'
? config.verbose
? LogLevel.Log
: LogLevel.None
: (config.verbose as LogLevel)
return {
config,
web3: config.web3Provider,
logger: new Logger(logLevel)
}
const logLevel =
typeof config.verbose !== 'number'
? config.verbose
? LogLevel.Log
: LogLevel.None
: (config.verbose as LogLevel)
return {
config,
web3: config.web3Provider,
logger: new Logger(logLevel)
}
}
export abstract class Instantiable {
protected get ocean() {
if (!this._ocean) {
this.logger.error('Ocean instance is not defined.')
}
return this._ocean
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.')
}
return this._web3
protected get web3() {
if (!this._web3) {
this.logger.error('Web3 instance is not defined.')
}
return this._web3
}
protected get config() {
if (!this._config) {
this.logger.error('Config instance is not defined.')
}
return this._config
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 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 get instanceConfig(): InstantiableConfig {
const { ocean, web3, config, logger } = this
return { ocean, web3, config, logger }
}
public static async getInstance(...args: any[]): Promise<any>
public static async getInstance(...args: any[]): Promise<any>
public static async getInstance(config: InstantiableConfig): Promise<any> {
LoggerInstance.warn('getInstance() methods has needs to be added to child class.')
}
public static async getInstance(config: InstantiableConfig): Promise<any> {
LoggerInstance.warn('getInstance() methods has needs to be added to child class.')
}
protected static setInstanceConfig<T extends Instantiable>(
instance: T,
{ ocean, config, web3, logger }: InstantiableConfig
) {
instance._ocean = ocean
instance._config = config
instance._web3 = web3
instance._logger = 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
}
private _ocean: Ocean
private _ocean: Ocean
private _web3: Web3
private _web3: Web3
private _config: Config
private _config: Config
private _logger: Logger
private _logger: Logger
protected setInstanceConfig(config: InstantiableConfig) {
Instantiable.setInstanceConfig(this, config)
}
protected setInstanceConfig(config: InstantiableConfig) {
Instantiable.setInstanceConfig(this, config)
}
}

View File

@ -1,25 +1,26 @@
import { Pool } from './balancerlib'
import Web3 from 'web3'
export class OceanPool extends Pool {
/** Ocean related functions */
public oceanAddress: string = null
public dtAddress: string = null
/** Ocean related functions */
public oceanAddress: string = null
public dtAddress: string = null
constructor(
web3: any,
FactoryABI: any = null,
PoolABI: any = null,
factoryAddress: string = null,
oceanAddress: string = null,
gaslimit?: number
) {
super(web3, FactoryABI, PoolABI, factoryAddress, gaslimit)
if (oceanAddress) {
this.oceanAddress = oceanAddress
}
constructor(
web3: Web3,
FactoryABI: any = null,
PoolABI: any = null,
factoryAddress: string = null,
oceanAddress: string = null,
gaslimit?: number
) {
super(web3, FactoryABI, PoolABI, factoryAddress, gaslimit)
if (oceanAddress) {
this.oceanAddress = oceanAddress
}
}
/**
/**
* create DataToken pool
@param {String} account
* @param {String} token Data Token Address
@ -27,344 +28,336 @@ export class OceanPool extends Pool {
* @param {String} weight Data Token Weight
* @return {any}
*/
public async createDTPool(
account: string,
token: string,
amount: string,
weight: string,
fee: string,
finalize: boolean = true
): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
if (parseFloat(weight) > 9 || parseFloat(weight) < 1) {
console.error('Weight out of bounds (min 1, max9)')
return null
}
const address = await super.createPool(account)
const oceanWeight = 10 - parseFloat(weight)
const oceanAmount = (parseFloat(amount) * oceanWeight) / parseFloat(weight)
const tokens = [
{
address: token,
amount: String(amount),
weight: String(weight)
},
{
address: this.oceanAddress,
amount: String(oceanAmount),
weight: String(oceanWeight)
}
]
this.dtAddress = token
await super.addToPool(account, address, tokens)
await super.setSwapFee(account, address, fee)
if (finalize) await super.finalize(account, address)
return address
public async createDTPool(
account: string,
token: string,
amount: string,
weight: string,
fee: string,
finalize: boolean = true
): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
/* Get DataToken address of token in this pool
* @param {String} account
* @param {String} poolAddress
* @return {string}
*/
public async getDTAddress(account: string, poolAddress: string): Promise<string> {
this.dtAddress = null
const tokens = await this.getCurrentTokens(account, poolAddress)
let token
for (token of tokens) {
if (token !== this.oceanAddress) this.dtAddress = token
}
return this.dtAddress
if (parseFloat(weight) > 9 || parseFloat(weight) < 1) {
console.error('Weight out of bounds (min 1, max9)')
return null
}
const address = await super.createPool(account)
const oceanWeight = 10 - parseFloat(weight)
const oceanAmount = (parseFloat(amount) * oceanWeight) / parseFloat(weight)
const tokens = [
{
address: token,
amount: String(amount),
weight: String(weight)
},
{
address: this.oceanAddress,
amount: String(oceanAmount),
weight: String(oceanWeight)
}
]
this.dtAddress = token
await super.addToPool(account, address, tokens)
await super.setSwapFee(account, address, fee)
if (finalize) await super.finalize(account, address)
return address
}
/**
* Get Ocean Token balance of a pool
* @param {String} account
* @param {String} poolAddress
* @return {any}
*/
public async getOceanReserve(account: string, poolAddress: string): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
return super.getReserve(account, poolAddress, this.oceanAddress)
/* Get DataToken address of token in this pool
* @param {String} account
* @param {String} poolAddress
* @return {string}
*/
public async getDTAddress(account: string, poolAddress: string): Promise<string> {
this.dtAddress = null
const tokens = await this.getCurrentTokens(account, poolAddress)
let token
for (token of tokens) {
if (token !== this.oceanAddress) this.dtAddress = token
}
return this.dtAddress
}
/**
* Get Data Token balance of a pool
* @param {String} account
* @param {String} poolAddress
* @return {any}
*/
public async getDTReserve(account: string, poolAddress: string): Promise<any> {
await this.getDTAddress(account, poolAddress)
return super.getReserve(account, poolAddress, this.dtAddress)
/**
* Get Ocean Token balance of a pool
* @param {String} account
* @param {String} poolAddress
* @return {any}
*/
public async getOceanReserve(account: string, poolAddress: string): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
return super.getReserve(account, poolAddress, this.oceanAddress)
}
/**
* Buy Data Token from a pool
* @param {String} account
* @param {String} poolAddress
* @param {String} amount Data Token Amount
* @param {String} oceanAmount Ocean Token Amount payed
* @param {String} maxPrice Maximum Price to pay
* @return {any}
*/
public async buyDT(
account: string,
poolAddress: string,
amount: string,
oceanAmount: string,
maxPrice: string
): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
await this.getDTAddress(account, poolAddress)
/**
* Get Data Token balance of a pool
* @param {String} account
* @param {String} poolAddress
* @return {any}
*/
public async getDTReserve(account: string, poolAddress: string): Promise<any> {
await this.getDTAddress(account, poolAddress)
return super.getReserve(account, poolAddress, this.dtAddress)
}
// TODO - check balances first
await super.approve(
account,
this.oceanAddress,
poolAddress,
this.web3.utils.toWei(oceanAmount)
)
return this.swapExactAmountOut(
account,
poolAddress,
this.oceanAddress,
oceanAmount,
this.dtAddress,
amount,
maxPrice
)
/**
* Buy Data Token from a pool
* @param {String} account
* @param {String} poolAddress
* @param {String} amount Data Token Amount
* @param {String} oceanAmount Ocean Token Amount payed
* @param {String} maxPrice Maximum Price to pay
* @return {any}
*/
public async buyDT(
account: string,
poolAddress: string,
amount: string,
oceanAmount: string,
maxPrice: string
): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
await this.getDTAddress(account, poolAddress)
/**
* Sell Data Token
* @param {String} account
* @param {String} poolAddress
* @param {String} amount Data Token Amount
* @param {String} oceanAmount Ocean Token Amount expected
* @param {String} maxPrice Minimum Price to sell
* @return {any}
*/
public async sellDT(
account: string,
poolAddress: string,
amount: string,
oceanAmount: string,
minPrice: string
): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
await this.getDTAddress(account, poolAddress)
return this.swapExactAmountOut(
account,
poolAddress,
this.dtAddress,
amount,
this.oceanAddress,
oceanAmount,
minPrice
)
}
// TODO - check balances first
await super.approve(
account,
this.oceanAddress,
poolAddress,
this.web3.utils.toWei(oceanAmount)
)
/**
* Add Data Token amount to pool liquidity
* @param {String} account
* @param {String} poolAddress
* @param {String} amount Data Token Amount
* @return {any}
*/
public async addDTLiquidity(
account: string,
poolAddress: string,
amount: string
): Promise<any> {
await this.getDTAddress(account, poolAddress)
await super.approve(
account,
this.dtAddress,
poolAddress,
this.web3.utils.toWei(amount)
)
const result = await super.joinswapExternAmountIn(
account,
poolAddress,
this.dtAddress,
amount,
'0'
)
return result
}
return this.swapExactAmountOut(
account,
poolAddress,
this.oceanAddress,
oceanAmount,
this.dtAddress,
amount,
maxPrice
)
}
/**
* Remove Data Token amount from pool liquidity
* @param {String} account
* @param {String} poolAddress
* @param {String} amount pool Liquidity Amount
* @return {any}
*/
public async removeDTLiquidity(
account: string,
poolAddress: string,
amount: string,
maximumPoolShares: string
): Promise<any> {
await this.getDTAddress(account, poolAddress)
// TODO Check balance of PoolShares before doing exit
return this.exitswapExternAmountOut(
account,
poolAddress,
this.dtAddress,
amount,
maximumPoolShares
)
/**
* Sell Data Token
* @param {String} account
* @param {String} poolAddress
* @param {String} amount Data Token Amount
* @param {String} oceanAmount Ocean Token Amount expected
* @param {String} maxPrice Minimum Price to sell
* @return {any}
*/
public async sellDT(
account: string,
poolAddress: string,
amount: string,
oceanAmount: string,
minPrice: string
): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
await this.getDTAddress(account, poolAddress)
return this.swapExactAmountOut(
account,
poolAddress,
this.dtAddress,
amount,
this.oceanAddress,
oceanAmount,
minPrice
)
}
/**
* Add Ocean Token amount to pool liquidity
* @param {String} account
* @param {String} poolAddress
* @param {String} amount Data Token Amount
* @return {any}
*/
public async addOceanLiquidity(
account: string,
poolAddress: string,
amount: string
): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
await super.approve(
account,
this.oceanAddress,
poolAddress,
this.web3.utils.toWei(amount)
)
const result = await super.joinswapExternAmountIn(
account,
poolAddress,
this.oceanAddress,
amount,
'0'
)
return result
}
/**
* Add Data Token amount to pool liquidity
* @param {String} account
* @param {String} poolAddress
* @param {String} amount Data Token Amount
* @return {any}
*/
public async addDTLiquidity(
account: string,
poolAddress: string,
amount: string
): Promise<any> {
await this.getDTAddress(account, poolAddress)
await super.approve(
account,
this.dtAddress,
poolAddress,
this.web3.utils.toWei(amount)
)
const result = await super.joinswapExternAmountIn(
account,
poolAddress,
this.dtAddress,
amount,
'0'
)
return result
}
/**
* Remove Ocean Token amount from pool liquidity
* @param {String} account
* @param {String} poolAddress
* @param {String} amount pool Liquidity Amount
* @return {any}
*/
public removeOceanLiquidity(
account: string,
poolAddress: string,
amount: string,
maximumPoolShares: string
): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
// TODO Check balance of PoolShares before doing exit
return super.exitswapExternAmountOut(
account,
poolAddress,
this.oceanAddress,
amount,
maximumPoolShares
)
}
/**
* Remove Data Token amount from pool liquidity
* @param {String} account
* @param {String} poolAddress
* @param {String} amount pool Liquidity Amount
* @return {any}
*/
public async removeDTLiquidity(
account: string,
poolAddress: string,
amount: string,
maximumPoolShares: string
): Promise<any> {
await this.getDTAddress(account, poolAddress)
// TODO Check balance of PoolShares before doing exit
return this.exitswapExternAmountOut(
account,
poolAddress,
this.dtAddress,
amount,
maximumPoolShares
)
}
/**
* Get Data Token Price from pool
* @param {String} account
* @param {String} poolAddress
* @return {any}
*/
public async getDTPrice(account: string, poolAddress: string): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
await this.getDTAddress(account, poolAddress)
return super.getSpotPrice(account, poolAddress, this.dtAddress, this.oceanAddress)
/**
* Add Ocean Token amount to pool liquidity
* @param {String} account
* @param {String} poolAddress
* @param {String} amount Data Token Amount
* @return {any}
*/
public async addOceanLiquidity(
account: string,
poolAddress: string,
amount: string
): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
await super.approve(
account,
this.oceanAddress,
poolAddress,
this.web3.utils.toWei(amount)
)
const result = await super.joinswapExternAmountIn(
account,
poolAddress,
this.oceanAddress,
amount,
'0'
)
return result
}
/**
* Search all pools that have DT in their composition
* @param {String} account
* @param {String} dtAddress
* @return {String[]}
*/
public async searchPoolforDT(account: string, dtAddress: string): Promise<string[]> {
const result: string[] = []
const factory = new this.web3.eth.Contract(this.FactoryABI, this.factoryAddress, {
from: account
})
const events = await factory.getPastEvents('SPoolRegistered', {
filter: {},
fromBlock: 0,
toBlock: 'latest'
})
for (let i = 0; i < events.length; i++) {
const constituents = await super.getCurrentTokens(
account,
events[i].returnValues[0]
)
if (constituents.includes(dtAddress)) result.push(events[i].returnValues[0])
}
return result
/**
* Remove Ocean Token amount from pool liquidity
* @param {String} account
* @param {String} poolAddress
* @param {String} amount pool Liquidity Amount
* @return {any}
*/
public removeOceanLiquidity(
account: string,
poolAddress: string,
amount: string,
maximumPoolShares: string
): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
// TODO Check balance of PoolShares before doing exit
return super.exitswapExternAmountOut(
account,
poolAddress,
this.oceanAddress,
amount,
maximumPoolShares
)
}
public async getOceanNeeded(
account: string,
poolAddress: string,
dtRequired: string
): Promise<string> {
await this.getDTAddress(account, poolAddress)
const tokenBalanceIn = await this.getReserve(
account,
poolAddress,
this.oceanAddress
)
const tokenWeightIn = await this.getDenormalizedWeight(
account,
poolAddress,
this.oceanAddress
)
const tokenBalanceOut = await this.getReserve(
account,
poolAddress,
this.dtAddress
)
const tokenWeightOut = await this.getDenormalizedWeight(
account,
poolAddress,
this.dtAddress
)
const swapFee = await this.getSwapFee(account, poolAddress)
return super.calcInGivenOut(
tokenBalanceIn,
tokenWeightIn,
tokenBalanceOut,
tokenWeightOut,
dtRequired,
swapFee
)
/**
* Get Data Token Price from pool
* @param {String} account
* @param {String} poolAddress
* @return {any}
*/
public async getDTPrice(account: string, poolAddress: string): Promise<any> {
if (this.oceanAddress == null) {
console.error('oceanAddress is not defined')
return null
}
await this.getDTAddress(account, poolAddress)
return super.getSpotPrice(account, poolAddress, this.dtAddress, this.oceanAddress)
}
/**
* Search all pools that have DT in their composition
* @param {String} account
* @param {String} dtAddress
* @return {String[]}
*/
public async searchPoolforDT(account: string, dtAddress: string): Promise<string[]> {
const result: string[] = []
const factory = new this.web3.eth.Contract(this.FactoryABI, this.factoryAddress, {
from: account
})
const events = await factory.getPastEvents('SPoolRegistered', {
filter: {},
fromBlock: 0,
toBlock: 'latest'
})
for (let i = 0; i < events.length; i++) {
const constituents = await super.getCurrentTokens(
account,
events[i].returnValues[0]
)
if (constituents.includes(dtAddress)) result.push(events[i].returnValues[0])
}
return result
}
public async getOceanNeeded(
account: string,
poolAddress: string,
dtRequired: string
): Promise<string> {
await this.getDTAddress(account, poolAddress)
const tokenBalanceIn = await this.getReserve(account, poolAddress, this.oceanAddress)
const tokenWeightIn = await this.getDenormalizedWeight(
account,
poolAddress,
this.oceanAddress
)
const tokenBalanceOut = await this.getReserve(account, poolAddress, this.dtAddress)
const tokenWeightOut = await this.getDenormalizedWeight(
account,
poolAddress,
this.dtAddress
)
const swapFee = await this.getSwapFee(account, poolAddress)
return super.calcInGivenOut(
tokenBalanceIn,
tokenWeightIn,
tokenBalanceOut,
tokenWeightOut,
dtRequired,
swapFee
)
}
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -2,73 +2,69 @@ import { Contract } from 'web3-eth-contract'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
export default class ContractHandler extends Instantiable {
protected static getContract(what: string, networkId: number) {
return ContractHandler.contracts.get(this.getHash(what, networkId))
protected static getContract(what: string, networkId: number): Contract {
return ContractHandler.contracts.get(this.getHash(what, networkId))
}
protected static setContract(
what: string,
networkId: number,
contractInstance: Contract
): void {
ContractHandler.contracts.set(this.getHash(what, networkId), contractInstance)
}
protected static hasContract(what: string, networkId: number): boolean {
return ContractHandler.contracts.has(this.getHash(what, networkId))
}
private static contracts: Map<string, Contract> = new Map<string, Contract>()
private static getHash(what: string, networkId: number): string {
return `${what}/#${networkId}`
}
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
}
public async get(what: string, optional: boolean = false): Promise<Contract> {
const where = (await this.ocean.network.getNetworkName()).toLowerCase()
const networkId = await this.ocean.network.getNetworkId()
try {
return (
ContractHandler.getContract(what, networkId) ||
(await this.load(what, where, networkId))
)
} catch (err) {
if (!optional) {
this.logger.error('Failed to load', what, 'from', where, err)
}
throw err
}
}
protected static setContract(
what: string,
networkId: number,
contractInstance: Contract
) {
ContractHandler.contracts.set(this.getHash(what, networkId), contractInstance)
private async load(what: string, where: string, networkId: number): Promise<Contract> {
this.logger.debug('Loading', what, 'from', where)
const artifact = require(`@oceanprotocol/contracts/artifacts/${where}/${what}.json`)
// Logger.log('Loaded artifact', artifact)
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 this.web3.eth.Contract(artifact.abi, artifact.address)
protected static hasContract(what: string, networkId: number): boolean {
return ContractHandler.contracts.has(this.getHash(what, networkId))
}
private static contracts: Map<string, Contract> = new Map<string, Contract>()
private static getHash(what: string, networkId: number): string {
return `${what}/#${networkId}`
}
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
}
public async get(what: string, optional: boolean = false): Promise<Contract> {
const where = (await this.ocean.network.getNetworkName()).toLowerCase()
const networkId = await this.ocean.network.getNetworkId()
try {
return (
ContractHandler.getContract(what, networkId) ||
(await this.load(what, where, networkId))
)
} catch (err) {
if (!optional) {
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/contracts/artifacts/${where}/${what}.json`)
// Logger.log('Loaded artifact', artifact)
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 this.web3.eth.Contract(artifact.abi, artifact.address)
this.logger.debug(
'Getting instance of',
what,
'from',
where,
'at address',
artifact.address
)
ContractHandler.setContract(what, networkId, contract)
return ContractHandler.getContract(what, networkId)
}
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

@ -5,12 +5,12 @@ const defaultDatatokensABI = require('@oceanprotocol/contracts/artifacts/develop
* Provides a interface to DataTokens
*/
export class DataTokens {
public factoryAddress: string
public factoryABI: any
public datatokensABI: any
public web3: any
public factoryAddress: string
public factoryABI: any
public datatokensABI: any
public web3: any
/**
/**
* Instantiate DataTokens (independently of Ocean).
* @param {String} factoryAddress
* @param {any} factoryABI
@ -18,303 +18,283 @@ export class DataTokens {
* @param {any} web3
*/
constructor(factoryAddress: string, factoryABI: any, datatokensABI: any, web3: any) {
this.factoryAddress = factoryAddress
this.factoryABI = factoryABI || defaultFactoryABI.abi
this.datatokensABI = datatokensABI || defaultDatatokensABI.abi
this.web3 = web3
constructor(factoryAddress: string, factoryABI: any, datatokensABI: any, web3: any) {
this.factoryAddress = factoryAddress
this.factoryABI = factoryABI || defaultFactoryABI.abi
this.datatokensABI = datatokensABI || defaultDatatokensABI.abi
this.web3 = web3
}
/**
* Create new datatoken
* @param {String} metaDataStoreURI
* @param {String} address
* @return {Promise<string>} datatoken address
*/
public async create(metaDataStoreURI: string, address: string): Promise<string> {
// Create factory contract object
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress, {
from: address
})
const estGas = await factory.methods
.createToken(metaDataStoreURI)
.estimateGas(function (err, estGas) {
if (err) console.log('Datatokens: ' + err)
return estGas
})
// Invoke createToken function of the contract
const trxReceipt = await factory.methods.createToken(metaDataStoreURI).send({
from: address,
gas: estGas + 1,
gasPrice: '3000000000'
})
let tokenAddress = null
try {
tokenAddress = trxReceipt.events.TokenCreated.returnValues[0]
} catch (e) {
console.error(e)
}
return tokenAddress
}
/**
* Create new datatoken
* @param {String} metaDataStoreURI
* @param {String} address
* @return {Promise<string>} datatoken address
*/
public async create(metaDataStoreURI: string, address: string): Promise<string> {
// Create factory contract object
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress, {
from: address
})
const estGas = await factory.methods
.createToken(metaDataStoreURI)
.estimateGas(function (err, estGas) {
if (err) console.log('Datatokens: ' + err)
return estGas
})
// Invoke createToken function of the contract
const trxReceipt = await factory.methods.createToken(metaDataStoreURI).send({
from: address,
gas: estGas + 1,
gasPrice: '3000000000'
})
/**
* Approve
* @param {String} dataTokenAddress
* @param {String} toAddress
* @param {string} amount Number of datatokens, as number. Will be converted to wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async approve(
dataTokenAddress: string,
spender: string,
amount: string,
address: string
): Promise<string> {
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, {
from: address
})
const trxReceipt = await datatoken.methods
.approve(spender, this.web3.utils.toWei(amount))
.send({ from: address })
return trxReceipt
}
let tokenAddress = null
try {
tokenAddress = trxReceipt.events.TokenCreated.returnValues[0]
} catch (e) {
console.error(e)
}
return tokenAddress
}
/**
* Mint
* @param {String} dataTokenAddress
* @param {String} address
* @param {String} amount Number of datatokens, as number. Will be converted to wei
* @param {String} toAddress - only if toAddress is different from the minter
* @return {Promise<string>} transactionId
*/
public async mint(
dataTokenAddress: string,
address: string,
amount: string,
toAddress?: string
): Promise<string> {
const destAddress = toAddress || address
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, {
from: address
})
const estGas = await datatoken.methods
.mint(destAddress, this.web3.utils.toWei(amount))
.estimateGas(function (err, estGas) {
if (err) console.log('Datatokens: ' + err)
return estGas
})
/**
* Approve
* @param {String} dataTokenAddress
* @param {String} toAddress
* @param {string} amount Number of datatokens, as number. Will be converted to wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async approve(
dataTokenAddress: string,
spender: string,
amount: string,
address: string
): Promise<string> {
const datatoken = new this.web3.eth.Contract(
this.datatokensABI,
dataTokenAddress,
{ from: address }
)
const trxReceipt = await datatoken.methods
.approve(spender, this.web3.utils.toWei(amount))
.send({ from: address })
return trxReceipt
}
const trxReceipt = await datatoken.methods
.mint(destAddress, this.web3.utils.toWei(amount))
.send({
from: address,
gas: estGas + 1,
gasPrice: '3000000000'
})
/**
* Mint
* @param {String} dataTokenAddress
* @param {String} address
* @param {String} amount Number of datatokens, as number. Will be converted to wei
* @param {String} toAddress - only if toAddress is different from the minter
* @return {Promise<string>} transactionId
*/
public async mint(
dataTokenAddress: string,
address: string,
amount: string,
toAddress?: string
): Promise<string> {
const destAddress = toAddress || address
const datatoken = new this.web3.eth.Contract(
this.datatokensABI,
dataTokenAddress,
{ from: address }
)
const estGas = await datatoken.methods
.mint(destAddress, this.web3.utils.toWei(amount))
.estimateGas(function (err, estGas) {
if (err) console.log('Datatokens: ' + err)
return estGas
})
return trxReceipt
}
const trxReceipt = await datatoken.methods
.mint(destAddress, this.web3.utils.toWei(amount))
.send({
from: address,
gas: estGas + 1,
gasPrice: '3000000000'
})
/**
* Transfer as number from address to toAddress
* @param {String} dataTokenAddress
* @param {String} toAddress
* @param {String} amount Number of datatokens, as number. Will be converted to wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async transfer(
dataTokenAddress: string,
toAddress: string,
amount: string,
address: string
): Promise<string> {
return this.transferToken(dataTokenAddress, toAddress, amount, address)
}
return trxReceipt
}
/**
* Transfer as number from address to toAddress
* @param {String} dataTokenAddress
* @param {String} toAddress
* @param {String} amount Number of datatokens, as number. Will be converted to wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async transferToken(
dataTokenAddress: string,
toAddress: string,
amount: string,
address: string
): Promise<string> {
const weiAmount = this.web3.utils.toWei(amount)
return this.transferWei(dataTokenAddress, toAddress, weiAmount, address)
}
/**
* Transfer as number from address to toAddress
* @param {String} dataTokenAddress
* @param {String} toAddress
* @param {String} amount Number of datatokens, as number. Will be converted to wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async transfer(
dataTokenAddress: string,
toAddress: string,
amount: string,
address: string
): Promise<string> {
return this.transferToken(dataTokenAddress, toAddress, amount, address)
}
/**
* Transfer in wei from address to toAddress
* @param {String} dataTokenAddress
* @param {String} toAddress
* @param {String} amount Number of datatokens, as number. Expressed as wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async transferWei(
dataTokenAddress: string,
toAddress: string,
amount: string,
address: string
): Promise<string> {
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, {
from: address
})
const trxReceipt = await datatoken.methods
.transfer(toAddress, amount)
.send({ from: address })
return trxReceipt
}
/**
* Transfer as number from address to toAddress
* @param {String} dataTokenAddress
* @param {String} toAddress
* @param {String} amount Number of datatokens, as number. Will be converted to wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async transferToken(
dataTokenAddress: string,
toAddress: string,
amount: string,
address: string
): Promise<string> {
const weiAmount = this.web3.utils.toWei(amount)
return this.transferWei(dataTokenAddress, toAddress, weiAmount, address)
}
/**
* Transfer from fromAddress to address (needs an Approve operation before)
* @param {String} dataTokenAddress
* @param {String} fromAddress
* @param {String} amount Number of datatokens, as number. Will be converted to wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async transferFrom(
dataTokenAddress: string,
fromAddress: string,
amount: string,
address: string
): Promise<string> {
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, {
from: address
})
const trxReceipt = await datatoken.methods
.transferFrom(fromAddress, address, this.web3.utils.toWei(amount))
.send({ from: address })
return trxReceipt
}
/**
* Transfer in wei from address to toAddress
* @param {String} dataTokenAddress
* @param {String} toAddress
* @param {String} amount Number of datatokens, as number. Expressed as wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async transferWei(
dataTokenAddress: string,
toAddress: string,
amount: string,
address: string
): Promise<string> {
const datatoken = new this.web3.eth.Contract(
this.datatokensABI,
dataTokenAddress,
{ from: address }
)
const trxReceipt = await datatoken.methods
.transfer(toAddress, amount)
.send({ from: address })
return trxReceipt
}
/**
* Get Address Balance for datatoken
* @param {String} dataTokenAddress
* @param {String} address
* @return {Promise<String>} balance Number of datatokens. Will be converted from wei
*/
public async balance(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, {
from: address
})
const balance = await datatoken.methods.balanceOf(address).call()
return this.web3.utils.fromWei(balance)
}
/**
* Transfer from fromAddress to address (needs an Approve operation before)
* @param {String} dataTokenAddress
* @param {String} fromAddress
* @param {String} amount Number of datatokens, as number. Will be converted to wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async transferFrom(
dataTokenAddress: string,
fromAddress: string,
amount: string,
address: string
): Promise<string> {
const datatoken = new this.web3.eth.Contract(
this.datatokensABI,
dataTokenAddress,
{ from: address }
)
const trxReceipt = await datatoken.methods
.transferFrom(fromAddress, address, this.web3.utils.toWei(amount))
.send({ from: address })
return trxReceipt
}
/**
* Get Alloance
* @param {String } dataTokenAddress
* @param {String} owner
* @param {String} spender
*/
public async allowance(
dataTokenAddress: string,
owner: string,
spender: string
): Promise<string> {
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, {
from: spender
})
const trxReceipt = await datatoken.methods.allowance(owner, spender).call()
return this.web3.utils.fromWei(trxReceipt)
}
/**
* Get Address Balance for datatoken
* @param {String} dataTokenAddress
* @param {String} address
* @return {Promise<String>} balance Number of datatokens. Will be converted from wei
*/
public async balance(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(
this.datatokensABI,
dataTokenAddress,
{ from: address }
)
const balance = await datatoken.methods.balanceOf(address).call()
return this.web3.utils.fromWei(balance)
}
/** Get Blob
* @param {String} dataTokenAddress
* @param {String} address
* @return {Promise<string>} string
*/
public async getBlob(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, {
from: address
})
const trxReceipt = await datatoken.methods.blob().call()
return trxReceipt
}
/**
* Get Alloance
* @param {String } dataTokenAddress
* @param {String} owner
* @param {String} spender
*/
public async allowance(
dataTokenAddress: string,
owner: string,
spender: string
): Promise<string> {
const datatoken = new this.web3.eth.Contract(
this.datatokensABI,
dataTokenAddress,
{ from: spender }
)
const trxReceipt = await datatoken.methods.allowance(owner, spender).call()
return this.web3.utils.fromWei(trxReceipt)
}
/** Get Name
* @param {String} dataTokenAddress
* @param {String} address
* @return {Promise<string>} string
*/
public async getName(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, {
from: address
})
const trxReceipt = await datatoken.methods.name().call()
return trxReceipt
}
/** Get Blob
* @param {String} dataTokenAddress
* @param {String} address
* @return {Promise<string>} string
*/
public async getBlob(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(
this.datatokensABI,
dataTokenAddress,
{ from: address }
)
const trxReceipt = await datatoken.methods.blob().call()
return trxReceipt
}
/** Get Symbol
* @param {String} dataTokenAddress
* @param {String} address
* @return {Promise<string>} string
*/
public async getSymbol(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, {
from: address
})
const trxReceipt = await datatoken.methods.symbol().call()
return trxReceipt
}
/** Get Name
* @param {String} dataTokenAddress
* @param {String} address
* @return {Promise<string>} string
*/
public async getName(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(
this.datatokensABI,
dataTokenAddress,
{ from: address }
)
const trxReceipt = await datatoken.methods.name().call()
return trxReceipt
}
/** Get Cap
* @param {String} dataTokenAddress
* @param {String} address
* @return {Promise<string>} string
*/
public async getCap(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, {
from: address
})
const trxReceipt = await datatoken.methods.cap().call()
return this.web3.utils.fromWei(trxReceipt)
}
/** Get Symbol
* @param {String} dataTokenAddress
* @param {String} address
* @return {Promise<string>} string
*/
public async getSymbol(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(
this.datatokensABI,
dataTokenAddress,
{ from: address }
)
const trxReceipt = await datatoken.methods.symbol().call()
return trxReceipt
}
/** Convert to wei
* @param {String} amount
* @return {Promise<string>} string
*/
public toWei(amount: string): string {
return this.web3.utils.toWei(amount)
}
/** Get Cap
* @param {String} dataTokenAddress
* @param {String} address
* @return {Promise<string>} string
*/
public async getCap(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract(
this.datatokensABI,
dataTokenAddress,
{ from: address }
)
const trxReceipt = await datatoken.methods.cap().call()
return this.web3.utils.fromWei(trxReceipt)
}
/** Convert to wei
* @param {String} amount
* @return {Promise<string>} string
*/
public toWei(amount: string) {
return this.web3.utils.toWei(amount)
}
/** Convert from wei
* @param {String} amount
* @return {Promise<string>} string
*/
public fromWei(amount: string) {
return this.web3.utils.fromWei(amount)
}
/** Convert from wei
* @param {String} amount
* @return {Promise<string>} string
*/
public fromWei(amount: string): string {
return this.web3.utils.fromWei(amount)
}
}

View File

@ -4,70 +4,67 @@ import ContractBase from './contracts/ContractBase'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
export class EventHandler extends Instantiable {
get count() {
return this.events.size
get count(): number {
return this.events.size
}
private events = new Set<(blockNumber) => void>()
private lastBlock: number
private interval = 200
private polling: boolean = false
private lastTimeout: NodeJS.Timeout
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
}
public subscribe(callback: (blockNumber: number) => void): { unsubscribe: () => void } {
this.events.add(callback)
this.checkBlock()
return {
unsubscribe: () => this.unsubscribe(callback)
}
}
public unsubscribe(callback: (blockNumber: number) => void): 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 }
): ContractEvent {
return new ContractEvent(this, contract, eventName, filter)
}
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
}
private events = new Set<(blockNumber) => void>()
private lastBlock: number
private interval = 200
private polling: boolean = false
private lastTimeout: NodeJS.Timeout
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
}
public subscribe(callback: (blockNumber: number) => void) {
this.events.add(callback)
this.checkBlock()
return {
unsubscribe: () => this.unsubscribe(callback)
}
}
public unsubscribe(callback: (blockNumber: 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)
}
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 = global.setTimeout(
() => this.checkBlock(true, n++),
this.interval
)
if (this.lastBlock !== blockNumber) {
this.events.forEach((fn) => fn(this.lastBlock + 1))
this.lastBlock = blockNumber
}
this.lastTimeout = global.setTimeout(() => this.checkBlock(true, n++), this.interval)
}
}

View File

@ -2,22 +2,22 @@ import { lookup } from '@ethereum-navigator/navigator'
import { Instantiable } from '../Instantiable.abstract'
export class Network extends Instantiable {
/**
* Returns network id.
* @return {Promise<number>} Network ID.
*/
public getNetworkId(): Promise<number> {
return this.web3.eth.net.getId()
}
/**
* 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 this.web3.eth.net.getId().then((networkId: number) => {
const network = lookup(networkId)
return network && network.name ? network.name : 'Development'
})
}
/**
* Returns the network by name.
* @return {Promise<string>} Network name.
*/
public async getNetworkName(): Promise<string> {
return this.web3.eth.net.getId().then((networkId: number) => {
const network = lookup(networkId)
return network && network.name ? network.name : 'Development'
})
}
}

View File

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

View File

@ -1,165 +1,164 @@
import { Contract } from 'web3-eth-contract'
import { Contract, EventData } from 'web3-eth-contract'
import { TransactionReceipt } from 'web3-core'
import ContractHandler from '../ContractHandler'
import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
export abstract class ContractBase extends Instantiable {
protected static instance = null
protected static instance = null
public contractName: string
public contractName: string
private contract: Contract = null
private contract: Contract = null
get address() {
return this.contract.options.address
get address(): string {
return this.contract.options.address
}
constructor(contractName: string, private optional: boolean = false) {
super()
this.contractName = contractName
}
public async getEventData(eventName: string, options: any): Promise<EventData[]> {
if (!this.contract.events[eventName]) {
throw new Error(`Event "${eventName}" not found on contract "${this.contractName}"`)
}
return this.contract.getPastEvents(eventName, options)
}
constructor(contractName: string, private optional: boolean = false) {
super()
this.contractName = contractName
public getPastEvents(
eventName: string,
filter: { [key: string]: any }
): Promise<EventData[]> {
return this.getEventData(eventName, {
filter,
fromBlock: 0,
toBlock: 'latest'
})
}
public getAddress(): string {
return this.contract.options.address
}
public getSignatureOfMethod(methodName: string): string {
const foundMethod = this.searchMethod(methodName)
return foundMethod.signature
}
public getInputsOfMethod(methodName: string): any[] {
const foundMethod = this.searchMethod(methodName)
return foundMethod.inputs
}
protected async init(config: InstantiableConfig): Promise<void> {
this.setInstanceConfig(config)
const contractHandler = new ContractHandler(config)
this.contract = await contractHandler.get(this.contractName, this.optional)
}
protected async getFromAddress(from?: string): Promise<string> {
if (!from) {
from = (await this.web3.eth.getAccounts())[0]
}
return from
}
public async getEventData(eventName: string, options: any) {
if (!this.contract.events[eventName]) {
throw new Error(
`Event "${eventName}" not found on contract "${this.contractName}"`
)
protected async sendFrom(
name: string,
args: any[],
from?: string
): Promise<TransactionReceipt> {
from = await this.getFromAddress(from)
return this.send(name, from, args)
}
protected async send(
name: string,
from: string,
args: any[]
): Promise<TransactionReceipt> {
if (!this.contract.methods[name]) {
throw new Error(`Method "${name}" is not part of contract "${this.contractName}"`)
}
// Logger.log(name, args)
const method = this.contract.methods[name]
try {
const methodInstance = method(...args)
const estimatedGas = await methodInstance.estimateGas(args, {
from
})
const tx = methodInstance.send({
from,
gas: estimatedGas
})
return tx
} catch (err) {
const mappedArgs = this.searchMethod(name, args).inputs.map((input, i) => {
return {
name: input.name,
value: args[i]
}
return this.contract.getPastEvents(eventName, options)
})
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
}
}
public getPastEvents(eventName: string, filter: { [key: string]: any }) {
return this.getEventData(eventName, {
filter,
fromBlock: 0,
toBlock: 'latest'
})
protected async call<T extends any>(
name: string,
args: any[],
from?: string
): Promise<T> {
if (!this.contract.methods[name]) {
throw new Error(`Method ${name} is not part of contract ${this.contractName}`)
}
public getAddress(): string {
return this.contract.options.address
// Logger.log(name)
try {
const method = this.contract.methods[name](...args)
return method.call(from ? { from } : null)
} catch (err) {
this.logger.error(
`Calling method "${name}" on contract "${this.contractName}" failed. Args: ${args}`,
err
)
throw err
}
}
public getSignatureOfMethod(methodName: string): string {
const foundMethod = this.searchMethod(methodName)
return foundMethod.signature
}
public getInputsOfMethod(methodName: string): any[] {
const foundMethod = this.searchMethod(methodName)
return foundMethod.inputs
}
protected async init(config: InstantiableConfig) {
this.setInstanceConfig(config)
const contractHandler = new ContractHandler(config)
this.contract = await contractHandler.get(this.contractName, this.optional)
}
protected async getFromAddress(from?: string): Promise<string> {
if (!from) {
from = (await this.web3.eth.getAccounts())[0]
}
return from
}
protected async sendFrom(
name: string,
args: any[],
from?: string
): Promise<TransactionReceipt> {
from = await this.getFromAddress(from)
return this.send(name, from, args)
}
protected async send(
name: string,
from: string,
args: any[]
): Promise<TransactionReceipt> {
if (!this.contract.methods[name]) {
throw new Error(
`Method "${name}" is not part of contract "${this.contractName}"`
)
}
// Logger.log(name, args)
const method = this.contract.methods[name]
try {
const methodInstance = method(...args)
const estimatedGas = await methodInstance.estimateGas(args, {
from
})
const tx = methodInstance.send({
from,
gas: estimatedGas
})
return tx
} catch (err) {
const mappedArgs = this.searchMethod(name, args).inputs.map((input, i) => {
return {
name: input.name,
value: args[i]
}
})
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
}
}
protected async call<T extends any>(
name: string,
args: any[],
from?: string
): Promise<T> {
if (!this.contract.methods[name]) {
throw new Error(`Method ${name} is not part of contract ${this.contractName}`)
}
// Logger.log(name)
try {
const method = this.contract.methods[name](...args)
return method.call(from ? { from } : null)
} catch (err) {
this.logger.error(
`Calling method "${name}" on contract "${this.contractName}" failed. Args: ${args}`,
err
)
throw err
}
}
// 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)
// }
private searchMethod(methodName: string, args: any[] = []) {
const methods = this.contract.options.jsonInterface
.map((method) => ({
...method,
signature: (method as any).signature
}))
.filter((method: any) => method.name === methodName)
const foundMethod =
methods.find(({ inputs }) => inputs.length === args.length) || methods[0]
if (!foundMethod) {
throw new Error(
`Method "${methodName}" is not part of contract "${this.contractName}"`
)
}
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)
// }
private searchMethod(methodName: string, args: any[] = []) {
const methods = this.contract.options.jsonInterface
.map((method) => ({
...method,
signature: (method as any).signature
}))
.filter((method: any) => method.name === methodName)
const foundMethod =
methods.find(({ inputs }) => inputs.length === args.length) || methods[0]
if (!foundMethod) {
throw new Error(
`Method "${methodName}" is not part of contract "${this.contractName}"`
)
}
return foundMethod
}
}
export default ContractBase

View File

@ -9,151 +9,146 @@ import Web3Provider from '../datatokens/Web3Provider'
* Contains all the data related to an asset.
*/
export class DDO {
/**
* Serializes the DDO object.
* @param {DDO} DDO to be serialized.
* @return {string} DDO serialized.
*/
public static serialize(ddo: DDO): string {
return JSON.stringify(ddo, null, 2)
/**
* Serializes the DDO object.
* @param {DDO} DDO to be serialized.
* @return {string} DDO serialized.
*/
public static serialize(ddo: DDO): string {
return JSON.stringify(ddo, null, 2)
}
/**
* Deserializes the DDO object.
* @param {DDO} DDO to be deserialized.
* @return {string} DDO deserialized.
*/
public static deserialize(ddoString: string): DDO {
const ddo = JSON.parse(ddoString)
return new DDO(ddo)
}
public '@context': string = 'https://w3id.org/did/v1'
/**
* DID, descentralized ID.
* @type {string}
*/
public id: string = null
public created: string
public updated: string
public dataToken: string
public publicKey: PublicKey[] = []
public authentication: Authentication[] = []
public service: Service[] = []
public proof: Proof
public constructor(ddo: Partial<DDO> = {}) {
Object.assign(this, ddo, {
created: (ddo && ddo.created) || new Date().toISOString().replace(/\.[0-9]{3}/, '')
})
}
public shortId(): string {
return this.id.replace('did:op:', '')
}
/**
* Finds a service of a DDO by index.
* @param {number} Service index.
* @return {Service} Service.
*/
public findServiceById<T extends ServiceType>(index: number): Service<T> {
if (isNaN(index)) {
throw new Error('index is not set')
}
/**
* Deserializes the DDO object.
* @param {DDO} DDO to be deserialized.
* @return {string} DDO deserialized.
*/
public static deserialize(ddoString: string): DDO {
const ddo = JSON.parse(ddoString)
const service = this.service.find((s) => s.index === index)
return new DDO(ddo)
return service as Service<T>
}
/**
* Finds a service of a DDO by type.
* @param {string} serviceType Service type.
* @return {Service} Service.
*/
public findServiceByType<T extends ServiceType>(serviceType: T): Service<T> {
if (!serviceType) {
throw new Error('serviceType not set')
}
public '@context': string = 'https://w3id.org/did/v1'
return this.service.find((s) => s.type === serviceType) as Service<T>
}
/**
* DID, descentralized ID.
* @type {string}
*/
public id: string = null
/**
* Generate the checksum using the current content.
* @return {string[]} DDO checksum.
*/
public getChecksum(): string {
const { attributes } = this.findServiceByType('metadata')
const { files, name, author, license } = attributes.main
public created: string
const values = [
...(files || []).map(({ checksum }) => checksum).filter((_) => !!_),
name,
author,
license,
this.id
]
public updated: string
return Web3Provider.getWeb3()
.utils.sha3(values.join(''))
.replace(/^0x([a-f0-9]{64})(:!.+)?$/i, '0x$1')
}
public dataToken: string
/**
* Generates proof using personal sing.
* @param {Ocean} ocean Ocean instance.
* @param {string} publicKey Public key to be used on personal sign.
* @param {string} password Password if it's required.
* @return {Promise<Proof>} Proof object.
*/
public async generateProof(
ocean: Ocean,
publicKey: string,
password?: string
): Promise<Proof> {
const checksum = this.getChecksum()
public publicKey: PublicKey[] = []
const signature = await ocean.utils.signature.signText(checksum, publicKey, password)
public authentication: Authentication[] = []
public service: Service[] = []
public proof: Proof
public constructor(ddo: Partial<DDO> = {}) {
Object.assign(this, ddo, {
created:
(ddo && ddo.created) || new Date().toISOString().replace(/\.[0-9]{3}/, '')
})
return {
created: new Date().toISOString().replace(/\.[0-9]{3}/, ''),
creator: publicKey,
type: 'DDOIntegritySignature',
signatureValue: signature
}
}
public shortId(): string {
return this.id.replace('did:op:', '')
}
/**
* Finds a service of a DDO by index.
* @param {number} Service index.
* @return {Service} Service.
*/
public findServiceById<T extends ServiceType>(index: number): Service<T> {
if (isNaN(index)) {
throw new Error('index is not set')
}
const service = this.service.find((s) => s.index === index)
return service as Service<T>
}
/**
* Finds a service of a DDO by type.
* @param {string} serviceType Service type.
* @return {Service} Service.
*/
public findServiceByType<T extends ServiceType>(serviceType: T): Service<T> {
if (!serviceType) {
throw new Error('serviceType not set')
}
return this.service.find((s) => s.type === serviceType) as Service<T>
}
/**
* Generate the checksum using the current content.
* @return {string[]} DDO checksum.
*/
public getChecksum(): string {
const { attributes } = this.findServiceByType('metadata')
const { files, name, author, license } = attributes.main
const values = [
...(files || []).map(({ checksum }) => checksum).filter((_) => !!_),
name,
author,
license,
this.id
]
return Web3Provider.getWeb3()
.utils.sha3(values.join(''))
.replace(/^0x([a-f0-9]{64})(:!.+)?$/i, '0x$1')
}
/**
* Generates proof using personal sing.
* @param {Ocean} ocean Ocean instance.
* @param {string} publicKey Public key to be used on personal sign.
* @param {string} password Password if it's required.
* @return {Promise<Proof>} Proof object.
*/
public async generateProof(
ocean: Ocean,
publicKey: string,
password?: string
): Promise<Proof> {
const checksum = this.getChecksum()
const signature = await ocean.utils.signature.signText(
checksum,
publicKey,
password
)
return {
created: new Date().toISOString().replace(/\.[0-9]{3}/, ''),
creator: publicKey,
type: 'DDOIntegritySignature',
signatureValue: signature
}
}
/**
* Generates and adds a proof using personal sing on the DDO.
* @param {Ocean} ocean Ocean instance.
* @param {string} publicKey Public key to be used on personal sign.
* @param {string} password Password if it's required.
* @return {Promise<Proof>} Proof object.
*/
public async addProof(
ocean: Ocean,
publicKey: string,
password?: string
): Promise<void> {
if (this.proof) {
throw new Error('Proof already exists')
}
this.proof = await this.generateProof(ocean, publicKey, password)
/**
* Generates and adds a proof using personal sing on the DDO.
* @param {Ocean} ocean Ocean instance.
* @param {string} publicKey Public key to be used on personal sign.
* @param {string} password Password if it's required.
* @return {Promise<Proof>} Proof object.
*/
public async addProof(
ocean: Ocean,
publicKey: string,
password?: string
): Promise<void> {
if (this.proof) {
throw new Error('Proof already exists')
}
this.proof = await this.generateProof(ocean, publicKey, password)
}
}

View File

@ -3,86 +3,86 @@
* @see https://github.com/oceanprotocol/OEPs/tree/master/8#additional-information
*/
export interface AdditionalInformation {
/**
* Details of what the resource is. For a dataset, this attribute
* explains what the data represents and what it can be used for.
* @type {string}
* @example "Weather information of UK including temperature and humidity"
*/
description?: string
/**
* Details of what the resource is. For a dataset, this attribute
* explains what the data represents and what it can be used for.
* @type {string}
* @example "Weather information of UK including temperature and humidity"
*/
description?: string
/**
* The party holding the legal copyright. Empty by default.
* @type {string}
* @example "Met Office"
*/
copyrightHolder?: string
/**
* The party holding the legal copyright. Empty by default.
* @type {string}
* @example "Met Office"
*/
copyrightHolder?: string
/**
* Example of the concept of this asset. This example is part
* of the metadata, not an external link.
* @type {string}
* @example "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68"
*/
workExample?: string
/**
* Example of the concept of this asset. This example is part
* of the metadata, not an external link.
* @type {string}
* @example "423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68"
*/
workExample?: string
/**
* Mapping of links for data samples, or links to find out more information.
* Links may be to either a URL or another Asset. We expect marketplaces to
* converge on agreements of typical formats for linked data: The Ocean Protocol
* itself does not mandate any specific formats as these requirements are likely
* to be domain-specific.
* @type {any[]}
* @example
* [
* {
* anotherSample: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/",
* },
* {
* fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/",
* },
* ]
*/
links?: { [name: string]: string }[]
/**
* Mapping of links for data samples, or links to find out more information.
* Links may be to either a URL or another Asset. We expect marketplaces to
* converge on agreements of typical formats for linked data: The Ocean Protocol
* itself does not mandate any specific formats as these requirements are likely
* to be domain-specific.
* @type {any[]}
* @example
* [
* {
* anotherSample: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/",
* },
* {
* fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/",
* },
* ]
*/
links?: { [name: string]: string }[]
/**
* The language of the content. Please use one of the language
* codes from the {@link https://tools.ietf.org/html/bcp47 IETF BCP 47 standard}.
* @type {String}
* @example "en"
*/
inLanguage?: string
/**
* The language of the content. Please use one of the language
* codes from the {@link https://tools.ietf.org/html/bcp47 IETF BCP 47 standard}.
* @type {String}
* @example "en"
*/
inLanguage?: string
/**
* Categories used to describe this content. Empty by default.
* @type {string[]}
* @example ["Economy", "Data Science"]
*/
categories?: string[]
/**
* Categories used to describe this content. Empty by default.
* @type {string[]}
* @example ["Economy", "Data Science"]
*/
categories?: string[]
/**
* Keywords or tags used to describe this content. Empty by default.
* @type {string[]}
* @example ["weather", "uk", "2011", "temperature", "humidity"]
*/
tags?: string[]
/**
* Keywords or tags used to describe this content. Empty by default.
* @type {string[]}
* @example ["weather", "uk", "2011", "temperature", "humidity"]
*/
tags?: string[]
/**
* An indication of update latency - i.e. How often are updates expected (seldom,
* annually, quarterly, etc.), or is the resource static that is never expected
* to get updated.
* @type {string}
* @example "yearly"
*/
updateFrequency?: string
/**
* An indication of update latency - i.e. How often are updates expected (seldom,
* annually, quarterly, etc.), or is the resource static that is never expected
* to get updated.
* @type {string}
* @example "yearly"
*/
updateFrequency?: string
/**
* A link to machine-readable structured markup (such as ttl/json-ld/rdf)
* describing the dataset.
* @type {StructuredMarkup[]}
*/
structuredMarkup?: {
uri: string
mediaType: string
}[]
/**
* A link to machine-readable structured markup (such as ttl/json-ld/rdf)
* describing the dataset.
* @type {StructuredMarkup[]}
*/
structuredMarkup?: {
uri: string
mediaType: string
}[]
}

View File

@ -1,4 +1,4 @@
export interface Authentication {
type: string
publicKey: string
type: string
publicKey: string
}

View File

@ -3,31 +3,31 @@
* @see https://github.com/oceanprotocol/OEPs/tree/master/8
*/
export interface Curation {
/**
* Decimal value between 0 and 1. 0 is the default value.
* @type {number}
* @example 0.93
*/
rating: number
/**
* Decimal value between 0 and 1. 0 is the default value.
* @type {number}
* @example 0.93
*/
rating: number
/**
* Number of votes. 0 is the default value.
* @type {number}
* @example 123
*/
numVotes: number
/**
* Number of votes. 0 is the default value.
* @type {number}
* @example 123
*/
numVotes: number
/**
* Schema applied to calculate the rating.
* @type {string}
* @example "Binary Voting"
*/
schema?: string
/**
* Schema applied to calculate the rating.
* @type {string}
* @example "Binary Voting"
*/
schema?: string
/**
* Flag unsuitable content.
* @type {boolean}
* @example true
*/
isListed?: boolean
/**
* Flag unsuitable content.
* @type {boolean}
* @example true
*/
isListed?: boolean
}

View File

@ -2,8 +2,8 @@ import { EditableMetadataLinks } from './EditableMetadataLinks'
import { ServicePrices } from './ServicePrices'
export interface EditableMetadata {
description?: string
title?: string
links?: EditableMetadataLinks[]
servicePrices?: ServicePrices[]
description?: string
title?: string
links?: EditableMetadataLinks[]
servicePrices?: ServicePrices[]
}

View File

@ -1,5 +1,5 @@
export interface EditableMetadataLinks {
name: string
url: string
type: string
name: string
url: string
type: string
}

View File

@ -1,64 +1,64 @@
export interface File {
/**
* File name.
* @type {string}
*/
name?: string
/**
* File name.
* @type {string}
*/
name?: string
/**
* File URL.
* @type {string}
*/
url: string
/**
* File URL.
* @type {string}
*/
url: string
/**
* File index.
* @type {number}
*/
index?: number
/**
* File index.
* @type {number}
*/
index?: number
/**
* File format, if applicable.
* @type {string}
* @example "text/csv"
*/
contentType: string
/**
* File format, if applicable.
* @type {string}
* @example "text/csv"
*/
contentType: string
/**
* File checksum.
* @type {[type]}
*/
checksum?: string
/**
* File checksum.
* @type {[type]}
*/
checksum?: string
/**
* Checksum hash algorithm.
* @type {[type]}
*/
checksumType?: string
/**
* Checksum hash algorithm.
* @type {[type]}
*/
checksumType?: string
/**
* File content length.
* @type {[type]}
*/
contentLength?: string
/**
* File content length.
* @type {[type]}
*/
contentLength?: string
/**
* Resource ID (depending on the source).
* @type {[type]}
*/
resourceId?: string
/**
* Resource ID (depending on the source).
* @type {[type]}
*/
resourceId?: string
/**
* File encoding.
* @type {string}
* @example "UTF-8"
*/
encoding?: string
/**
* File encoding.
* @type {string}
* @example "UTF-8"
*/
encoding?: string
/**
* File compression (e.g. no, gzip, bzip2, etc).
* @type {string}
* @example "zip"
*/
compression?: string
/**
* File compression (e.g. no, gzip, bzip2, etc).
* @type {string}
* @example "zip"
*/
compression?: string
}

View File

@ -3,8 +3,8 @@ import { AdditionalInformation } from './AdditionalInformation'
import { Curation } from './Curation'
export interface Metadata {
main: MetadataMain
encryptedFiles?: string
additionalInformation?: AdditionalInformation
curation?: Curation
main: MetadataMain
encryptedFiles?: string
additionalInformation?: AdditionalInformation
curation?: Curation
}

View File

@ -1,12 +1,12 @@
export interface MetadataAlgorithm {
url?: string
rawcode?: string
language?: string
format?: string
version?: string
container: {
entrypoint: string
image: string
tag: string
}
url?: string
rawcode?: string
language?: string
format?: string
version?: string
container: {
entrypoint: string
image: string
tag: string
}
}

View File

@ -6,61 +6,61 @@ import { File } from './File'
* @see https://github.com/oceanprotocol/OEPs/tree/master/8
*/
export interface MetadataMain {
/**
* Descriptive name of the Asset.
* @type {string}
* @example "UK Weather information 2011"
*/
name: string
/**
* Descriptive name of the Asset.
* @type {string}
* @example "UK Weather information 2011"
*/
name: string
/**
* Type of the Asset. Helps to filter by the type of asset ("dataset" or "algorithm").
* @type {string}
* @example "dataset"
*/
type: 'dataset' | 'algorithm'
/**
* Type of the Asset. Helps to filter by the type of asset ("dataset" or "algorithm").
* @type {string}
* @example "dataset"
*/
type: 'dataset' | 'algorithm'
/**
* The date on which the asset was created by the originator in
* ISO 8601 format, Coordinated Universal Time.
* @type {string}
* @example "2019-01-31T08:38:32Z"
*/
dateCreated: string
/**
* The date on which the asset was created by the originator in
* ISO 8601 format, Coordinated Universal Time.
* @type {string}
* @example "2019-01-31T08:38:32Z"
*/
dateCreated: string
/**
* The date on which the asset DDO was registered into the metadata store.
* This value is created automatically by Aquarius upon registering,
* so this value can't be set.
* @type {string}
* @example "2019-01-31T08:38:32Z"
*/
datePublished?: string
/**
* The date on which the asset DDO was registered into the metadata store.
* This value is created automatically by Aquarius upon registering,
* so this value can't be set.
* @type {string}
* @example "2019-01-31T08:38:32Z"
*/
datePublished?: string
/**
* Name of the entity generating this data (e.g. Tfl, Disney Corp, etc.).
* @type {string}
* @example "Met Office"
*/
author: string
/**
* Name of the entity generating this data (e.g. Tfl, Disney Corp, etc.).
* @type {string}
* @example "Met Office"
*/
author: string
/**
* Short name referencing the license of the asset (e.g. Public Domain, CC-0, CC-BY, No License Specified, etc. ).
* If it's not specified, the following value will be added: "No License Specified".
* @type {string}
* @example "CC-BY"
*/
license: string
/**
* Short name referencing the license of the asset (e.g. Public Domain, CC-0, CC-BY, No License Specified, etc. ).
* If it's not specified, the following value will be added: "No License Specified".
* @type {string}
* @example "CC-BY"
*/
license: string
/**
* Array of File objects including the encrypted file urls and some additional information.
* @type {File[]}
*/
files: File[]
/**
* Array of File objects including the encrypted file urls and some additional information.
* @type {File[]}
*/
files: File[]
/**
* Metadata used only for assets with type `algorithm`.
* @type {MetaDataAlgorithm}
*/
algorithm?: MetadataAlgorithm
/**
* Metadata used only for assets with type `algorithm`.
* @type {MetaDataAlgorithm}
*/
algorithm?: MetadataAlgorithm
}

View File

@ -1,6 +1,6 @@
export interface Proof {
type: string
created: string
creator: string
signatureValue: string
type: string
created: string
creator: string
signatureValue: string
}

View File

@ -2,31 +2,31 @@
* Public key data.
*/
export interface PublicKey {
/**
* ID of the key.
* @type {string}
* @example "did:op:123456789abcdefghi#keys-1"
*/
id: string
/**
* ID of the key.
* @type {string}
* @example "did:op:123456789abcdefghi#keys-1"
*/
id: string
/**
* Type of key.
* @type {string}
*/
type:
| 'Ed25519VerificationKey2018'
| 'RsaVerificationKey2018'
| 'EdDsaSAPublicKeySecp256k1'
| 'EthereumECDSAKey'
/**
* Type of key.
* @type {string}
*/
type:
| 'Ed25519VerificationKey2018'
| 'RsaVerificationKey2018'
| 'EdDsaSAPublicKeySecp256k1'
| 'EthereumECDSAKey'
/**
* Key owner.
* @type {string}
* @example "did:op:123456789abcdefghi"
*/
owner: string
/**
* Key owner.
* @type {string}
* @example "did:op:123456789abcdefghi"
*/
owner: string
publicKeyPem?: string
publicKeyBase58?: string
publicKeyHex?: string
publicKeyPem?: string
publicKeyBase58?: string
publicKeyHex?: string
}

View File

@ -3,91 +3,91 @@ import { Metadata } from './Metadata'
export type ServiceType = 'authorization' | 'metadata' | 'access' | 'compute'
export interface ServiceCommon {
type: ServiceType
index: number
serviceEndpoint?: string
attributes: ServiceCommonAttributes
type: ServiceType
index: number
serviceEndpoint?: string
attributes: ServiceCommonAttributes
}
export interface ServiceCommonAttributes {
main: { [key: string]: any }
additionalInformation?: { [key: string]: any }
main: { [key: string]: any }
additionalInformation?: { [key: string]: any }
}
export interface ServiceAccessAttributes extends ServiceCommonAttributes {
main: {
creator: string
name: string
datePublished: string
cost: string
timeout: number
}
main: {
creator: string
name: string
datePublished: string
cost: string
timeout: number
}
}
export interface ServiceComputePrivacy {
allowRawAlgorithm: boolean
allowNetworkAccess: boolean
trustedAlgorithms: string[]
allowRawAlgorithm: boolean
allowNetworkAccess: boolean
trustedAlgorithms: string[]
}
export interface ServiceComputeAttributes extends ServiceCommonAttributes {
main: {
creator: string
datePublished: string
cost: string
timeout: number
provider?: ServiceComputeProvider
name: string
privacy?: ServiceComputePrivacy
}
main: {
creator: string
datePublished: string
cost: string
timeout: number
provider?: ServiceComputeProvider
name: string
privacy?: ServiceComputePrivacy
}
}
export interface ServiceComputeProvider {
type: string
description: string
environment: {
cluster: {
type: string
url: string
}
supportedContainers: {
image: string
tag: string
checksum: string
}[]
supportedServers: {
serverId: string
serverType: string
cost: string
cpu: string
gpu: string
memory: string
disk: string
maxExecutionTime: number
}[]
type: string
description: string
environment: {
cluster: {
type: string
url: string
}
supportedContainers: {
image: string
tag: string
checksum: string
}[]
supportedServers: {
serverId: string
serverType: string
cost: string
cpu: string
gpu: string
memory: string
disk: string
maxExecutionTime: number
}[]
}
}
export interface ServiceMetadata extends ServiceCommon {
type: 'metadata'
attributes: Metadata
type: 'metadata'
attributes: Metadata
}
export interface ServiceAccess extends ServiceCommon {
type: 'access'
attributes: ServiceAccessAttributes
type: 'access'
attributes: ServiceAccessAttributes
}
export interface ServiceCompute extends ServiceCommon {
type: 'compute'
attributes: ServiceComputeAttributes
type: 'compute'
attributes: ServiceComputeAttributes
}
export type Service<T extends ServiceType | 'default' = 'default'> = T extends 'metadata'
? ServiceMetadata
: T extends 'access'
? ServiceAccess
: T extends 'compute'
? ServiceCompute
: T extends 'default'
? ServiceCommon
: ServiceCommon
? ServiceMetadata
: T extends 'access'
? ServiceAccess
: T extends 'compute'
? ServiceCompute
: T extends 'default'
? ServiceCommon
: ServiceCommon

View File

@ -1,4 +1,4 @@
export interface ServicePrices {
serviceIndex: number
price: string
serviceIndex: number
price: string
}

View File

@ -16,19 +16,19 @@ export * from './ddo/interfaces'
export { CreateProgressStep, OrderProgressStep } from './ocean/Assets'
export {
OceanPlatformTechStatus,
OceanPlatformTech,
OceanPlatformVersions
OceanPlatformTechStatus,
OceanPlatformTech,
OceanPlatformVersions
} from './ocean/Versions'
export {
Ocean,
Account,
Config,
DID,
Logger,
MetadataStore,
DataTokens,
utils,
ConfigHelper
Ocean,
Account,
Config,
DID,
Logger,
MetadataStore,
DataTokens,
utils,
ConfigHelper
}

View File

@ -8,18 +8,18 @@ import { WebServiceConnector } from '../ocean/utils/WebServiceConnector'
const apiPath = '/api/v1/aquarius/assets/ddo'
export interface QueryResult {
results: DDO[]
page: number
totalPages: number
totalResults: number
results: DDO[]
page: number
totalPages: number
totalResults: number
}
export interface SearchQuery {
text?: string
offset?: number
page?: number
query: { [property: string]: string | number | string[] | number[] }
sort?: { [jsonPath: string]: number }
text?: string
offset?: number
page?: number
query: { [property: string]: string | number | string[] | number[] }
sort?: { [jsonPath: string]: number }
}
/**
@ -27,413 +27,384 @@ export interface SearchQuery {
* Metadata Store provides an off-chain database store for metadata about data assets.
*/
export class MetadataStore {
public fetch: WebServiceConnector
private logger: Logger
private metadataStoreUri: string
public fetch: WebServiceConnector
private logger: Logger
private metadataStoreUri: string
private get url() {
return this.metadataStoreUri
}
private get url() {
return this.metadataStoreUri
}
/**
* Instantiate Metadata Store (independently of Ocean) for off-chain interaction.
* @param {String} metadataStoreUri
* @param {Logger} logger
*/
constructor(metadataStoreUri: string, logger: Logger) {
this.fetch = new WebServiceConnector(logger)
this.logger = logger
this.metadataStoreUri = metadataStoreUri
}
/**
* Instantiate Metadata Store (independently of Ocean) for off-chain interaction.
* @param {String} metadataStoreUri
* @param {Logger} logger
*/
constructor(metadataStoreUri: string, logger: Logger) {
this.fetch = new WebServiceConnector(logger)
this.logger = logger
this.metadataStoreUri = metadataStoreUri
}
public async getVersionInfo() {
return (await this.fetch.get(this.url)).json()
}
public async getVersionInfo(): Promise<any> {
return (await this.fetch.get(this.url)).json()
}
public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
const accessUrl: string = await this.fetch
.post(`${accessToken.service_endpoint}/${accessToken.resource_id}`, payload)
.then((response: any): string => {
if (response.ok) {
return response.text()
}
this.logger.error('Failed: ', response.status, response.statusText)
return null
})
.then((consumptionUrl: string): string => {
this.logger.error('Success accessing consume endpoint: ', consumptionUrl)
return consumptionUrl
})
.catch((error) => {
this.logger.error(
'Error fetching the data asset consumption url: ',
error
)
return null
})
public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
const accessUrl: string = await this.fetch
.post(`${accessToken.service_endpoint}/${accessToken.resource_id}`, payload)
.then((response: any): string => {
if (response.ok) {
return response.text()
}
this.logger.error('Failed: ', response.status, response.statusText)
return null
})
.then((consumptionUrl: string): string => {
this.logger.error('Success accessing consume endpoint: ', consumptionUrl)
return consumptionUrl
})
.catch((error) => {
this.logger.error('Error fetching the data asset consumption url: ', error)
return null
})
return accessUrl
}
return accessUrl
}
/**
* Search over the DDOs using a query.
* @param {SearchQuery} query Query to filter the DDOs.
* @return {Promise<QueryResult>}
*/
public async queryMetadata(query: SearchQuery): Promise<QueryResult> {
const result: QueryResult = await this.fetch
.post(`${this.url}${apiPath}/query`, JSON.stringify(query))
.then((response: any) => {
if (response.ok) {
return response.json() as DDO[]
}
this.logger.error(
'queryMetadata failed:',
response.status,
response.statusText
)
return this.transformResult()
})
.then((results) => {
return this.transformResult(results)
})
.catch((error) => {
this.logger.error('Error fetching querying metadata: ', error)
return this.transformResult()
})
/**
* Search over the DDOs using a query.
* @param {SearchQuery} query Query to filter the DDOs.
* @return {Promise<QueryResult>}
*/
public async queryMetadata(query: SearchQuery): Promise<QueryResult> {
const result: QueryResult = await this.fetch
.post(`${this.url}${apiPath}/query`, JSON.stringify(query))
.then((response: any) => {
if (response.ok) {
return response.json() as DDO[]
}
this.logger.error('queryMetadata failed:', response.status, response.statusText)
return this.transformResult()
})
.then((results) => {
return this.transformResult(results)
})
.catch((error) => {
this.logger.error('Error fetching querying metadata: ', error)
return this.transformResult()
})
return result
}
return result
}
/**
* Search over the DDOs using a query.
* @param {SearchQuery} query Query to filter the DDOs.
* @return {Promise<QueryResult>}
*/
public async queryMetadataByText(query: SearchQuery): Promise<QueryResult> {
const fullUrl = new URL(`${this.url}${apiPath}/query`)
fullUrl.searchParams.append('text', query.text)
fullUrl.searchParams.append(
'sort',
decodeURIComponent(JSON.stringify(query.sort))
/**
* Search over the DDOs using a query.
* @param {SearchQuery} query Query to filter the DDOs.
* @return {Promise<QueryResult>}
*/
public async queryMetadataByText(query: SearchQuery): Promise<QueryResult> {
const fullUrl = new URL(`${this.url}${apiPath}/query`)
fullUrl.searchParams.append('text', query.text)
fullUrl.searchParams.append('sort', decodeURIComponent(JSON.stringify(query.sort)))
fullUrl.searchParams.append('offset', query.offset.toString())
fullUrl.searchParams.append('page', query.page.toString())
const result: QueryResult = await this.fetch
.get(fullUrl)
.then((response: any) => {
if (response.ok) {
return response.json() as DDO[]
}
this.logger.log(
'queryMetadataByText failed:',
response.status,
response.statusText
)
fullUrl.searchParams.append('offset', query.offset.toString())
fullUrl.searchParams.append('page', query.page.toString())
return this.transformResult()
})
.then((results) => {
return this.transformResult(results)
})
.catch((error) => {
this.logger.error('Error fetching querying metadata by text: ', error)
return this.transformResult()
})
const result: QueryResult = await this.fetch
.get(fullUrl)
.then((response: any) => {
if (response.ok) {
return response.json() as DDO[]
}
this.logger.log(
'queryMetadataByText failed:',
response.status,
response.statusText
)
return this.transformResult()
})
.then((results) => {
return this.transformResult(results)
})
.catch((error) => {
this.logger.error('Error fetching querying metadata by text: ', error)
return this.transformResult()
})
return result
}
return result
}
/**
* Stores a DDO in Metadata Store.
* @param {DDO} ddo DDO to be stored.
* @return {Promise<DDO>} Final DDO.
*/
public async storeDDO(ddo: DDO): Promise<DDO> {
const fullUrl = `${this.url}${apiPath}`
const result: DDO = await this.fetch
.post(fullUrl, DDO.serialize(ddo))
.then((response: any) => {
if (response.ok) {
return response.json()
}
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) => {
this.logger.error('Error fetching querying metadata: ', error)
return null as DDO
})
return result
}
/**
* Retrieves a DDO by DID.
* @param {DID | string} did DID of the asset.
* @return {Promise<DDO>} DDO of the asset.
*/
public async retrieveDDO(
did: DID | string,
metadataServiceEndpoint?: string
): Promise<DDO> {
did = did && DID.parse(did)
const fullUrl = metadataServiceEndpoint || `${this.url}${apiPath}/${did.getDid()}`
const result = await this.fetch
.get(fullUrl)
.then((response: any) => {
if (response.ok) {
return response.json()
}
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) => {
this.logger.error('Error fetching querying metadata: ', error)
return null as DDO
})
return result
}
public async retrieveDDOByUrl(metadataServiceEndpoint?: string) {
return this.retrieveDDO(undefined, metadataServiceEndpoint)
}
/**
* Transfer ownership of a DDO
* @param {DID | string} did DID of the asset to update.
* @param {String} newOwner New owner of the DDO
* @param {String} updated Updated field of the DDO
* @param {String} signature Signature using updated field to verify that the consumer has rights
* @return {Promise<String>} Result.
*/
public async transferOwnership(
did: DID | string,
newOwner: string,
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/owner/update/${did.getDid()}`
const result = await this.fetch
.put(
fullUrl,
JSON.stringify({
signature: signature,
updated: updated,
newOwner: newOwner
})
)
.then((response: any) => {
if (response.ok) {
return response.text
}
this.logger.log(
'transferownership failed:',
response.status,
response.statusText
)
return null
})
.catch((error) => {
this.logger.error('Error transfering ownership metadata: ', error)
return null
})
return result
}
/**
* Update Compute Privacy
* @param {DID | string} did DID of the asset to update.
* @param {number } serviceIndex Service index
* @param {boolean} allowRawAlgorithm Allow Raw Algorithms
* @param {boolean} allowNetworkAccess Allow Raw Algorithms
* @param {String[]} trustedAlgorithms Allow Raw Algorithms
* @param {String} updated Updated field of the DDO
* @param {String} signature Signature using updated field to verify that the consumer has rights
* @return {Promise<String>} Result.
*/
public async updateComputePrivacy(
did: DID | string,
serviceIndex: number,
allowRawAlgorithm: boolean,
allowNetworkAccess: boolean,
trustedAlgorithms: string[],
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/computePrivacy/update/${did.getDid()}`
const result = await this.fetch
.put(
fullUrl,
JSON.stringify({
signature: signature,
updated: updated,
serviceIndex: serviceIndex,
allowRawAlgorithm: allowRawAlgorithm,
allowNetworkAccess: allowNetworkAccess,
trustedAlgorithms: trustedAlgorithms
})
)
.then((response: any) => {
if (response.ok) {
return response.text
}
this.logger.log(
'update compute privacy failed:',
response.status,
response.statusText
)
return null
})
.catch((error) => {
this.logger.error('Error updating compute privacy: ', error)
return null
})
return result
}
public async getOwnerAssets(owner: string): Promise<DDO[]> {
const q = {
offset: 100,
page: 1,
query: {
'publicKey.owner': [owner]
},
sort: {
value: 1
}
} as SearchQuery
return (await this.queryMetadata(q)).results
}
/**
* Edit Metadata for a DDO.
* @param {did} string DID.
* @param {newMetadata} EditableMetadata Metadata fields & new values.
* @param {String} updated Updated field of the DDO
* @param {String} signature Signature using updated field to verify that the consumer has rights
* @return {Promise<String>} Result.
*/
public async editMetadata(
did: DID | string,
newMetadata: EditableMetadata,
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/metadata/${did.getDid()}`
const data = Object()
if (newMetadata.description != null) data.description = newMetadata.description
if (newMetadata.title != null) data.title = newMetadata.title
if (newMetadata.servicePrices != null)
data.servicePrices = newMetadata.servicePrices
if (newMetadata.links != null) data.links = newMetadata.links
data.updated = updated
data.signature = signature
const result = await this.fetch
.put(fullUrl, JSON.stringify(data))
.then((response: any) => {
if (response.ok) {
return response.text
}
this.logger.log(
'editMetaData failed:',
response.status,
response.statusText
)
return null
})
.catch((error) => {
this.logger.error('Error transfering ownership metadata: ', error)
return null
})
return result
}
/**
* Retire a DDO (Delete)
* @param {DID | string} did DID of the asset to update.
* @param {String} updated Updated field of the DDO
* @param {String} signature Signature using updated field to verify that the consumer has rights
* @return {Promise<String>} Result.
*/
public async retire(
did: DID | string,
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/${did.getDid()}`
const result = await this.fetch
.delete(
fullUrl,
JSON.stringify({
signature: signature,
updated: updated
})
)
.then((response: any) => {
if (response.ok) {
return response.text
}
this.logger.log('retire failed:', response.status, response.statusText)
return null
})
.catch((error) => {
this.logger.error('Error transfering ownership metadata: ', error)
return null
})
return result
}
public getServiceEndpoint(did: DID) {
return `${this.url}/api/v1/aquarius/assets/ddo/did:op:${did.getId()}`
}
public getURI() {
return `${this.url}`
}
private transformResult(
{ results, page, total_pages: totalPages, total_results: totalResults }: any = {
result: [],
page: 0,
total_pages: 0, // eslint-disable-line @typescript-eslint/camelcase
total_results: 0 // eslint-disable-line @typescript-eslint/camelcase
/**
* Stores a DDO in Metadata Store.
* @param {DDO} ddo DDO to be stored.
* @return {Promise<DDO>} Final DDO.
*/
public async storeDDO(ddo: DDO): Promise<DDO> {
const fullUrl = `${this.url}${apiPath}`
const result: DDO = await this.fetch
.post(fullUrl, DDO.serialize(ddo))
.then((response: any) => {
if (response.ok) {
return response.json()
}
): QueryResult {
return {
results: (results || []).map((ddo) => new DDO(ddo as DDO)),
page,
totalPages,
totalResults
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) => {
this.logger.error('Error fetching querying metadata: ', error)
return null as DDO
})
return result
}
/**
* Retrieves a DDO by DID.
* @param {DID | string} did DID of the asset.
* @return {Promise<DDO>} DDO of the asset.
*/
public async retrieveDDO(
did: DID | string,
metadataServiceEndpoint?: string
): Promise<DDO> {
did = did && DID.parse(did)
const fullUrl = metadataServiceEndpoint || `${this.url}${apiPath}/${did.getDid()}`
const result = await this.fetch
.get(fullUrl)
.then((response: any) => {
if (response.ok) {
return response.json()
}
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) => {
this.logger.error('Error fetching querying metadata: ', error)
return null as DDO
})
return result
}
public async retrieveDDOByUrl(metadataServiceEndpoint?: string): Promise<DDO> {
return this.retrieveDDO(undefined, metadataServiceEndpoint)
}
/**
* Transfer ownership of a DDO
* @param {DID | string} did DID of the asset to update.
* @param {String} newOwner New owner of the DDO
* @param {String} updated Updated field of the DDO
* @param {String} signature Signature using updated field to verify that the consumer has rights
* @return {Promise<String>} Result.
*/
public async transferOwnership(
did: DID | string,
newOwner: string,
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/owner/update/${did.getDid()}`
const result = await this.fetch
.put(
fullUrl,
JSON.stringify({
signature: signature,
updated: updated,
newOwner: newOwner
})
)
.then((response: any) => {
if (response.ok) {
return response.text
}
this.logger.log('transferownership failed:', response.status, response.statusText)
return null
})
.catch((error) => {
this.logger.error('Error transfering ownership metadata: ', error)
return null
})
return result
}
/**
* Update Compute Privacy
* @param {DID | string} did DID of the asset to update.
* @param {number } serviceIndex Service index
* @param {boolean} allowRawAlgorithm Allow Raw Algorithms
* @param {boolean} allowNetworkAccess Allow Raw Algorithms
* @param {String[]} trustedAlgorithms Allow Raw Algorithms
* @param {String} updated Updated field of the DDO
* @param {String} signature Signature using updated field to verify that the consumer has rights
* @return {Promise<String>} Result.
*/
public async updateComputePrivacy(
did: DID | string,
serviceIndex: number,
allowRawAlgorithm: boolean,
allowNetworkAccess: boolean,
trustedAlgorithms: string[],
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/computePrivacy/update/${did.getDid()}`
const result = await this.fetch
.put(
fullUrl,
JSON.stringify({
signature: signature,
updated: updated,
serviceIndex: serviceIndex,
allowRawAlgorithm: allowRawAlgorithm,
allowNetworkAccess: allowNetworkAccess,
trustedAlgorithms: trustedAlgorithms
})
)
.then((response: any) => {
if (response.ok) {
return response.text
}
this.logger.log(
'update compute privacy failed:',
response.status,
response.statusText
)
return null
})
.catch((error) => {
this.logger.error('Error updating compute privacy: ', error)
return null
})
return result
}
public async getOwnerAssets(owner: string): Promise<DDO[]> {
const q = {
offset: 100,
page: 1,
query: {
'publicKey.owner': [owner]
},
sort: {
value: 1
}
} as SearchQuery
return (await this.queryMetadata(q)).results
}
/**
* Edit Metadata for a DDO.
* @param {did} string DID.
* @param {newMetadata} EditableMetadata Metadata fields & new values.
* @param {String} updated Updated field of the DDO
* @param {String} signature Signature using updated field to verify that the consumer has rights
* @return {Promise<String>} Result.
*/
public async editMetadata(
did: DID | string,
newMetadata: EditableMetadata,
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/metadata/${did.getDid()}`
const data = Object()
if (newMetadata.description != null) data.description = newMetadata.description
if (newMetadata.title != null) data.title = newMetadata.title
if (newMetadata.servicePrices != null) data.servicePrices = newMetadata.servicePrices
if (newMetadata.links != null) data.links = newMetadata.links
data.updated = updated
data.signature = signature
const result = await this.fetch
.put(fullUrl, JSON.stringify(data))
.then((response: any) => {
if (response.ok) {
return response.text
}
this.logger.log('editMetaData failed:', response.status, response.statusText)
return null
})
.catch((error) => {
this.logger.error('Error transfering ownership metadata: ', error)
return null
})
return result
}
/**
* Retire a DDO (Delete)
* @param {DID | string} did DID of the asset to update.
* @param {String} updated Updated field of the DDO
* @param {String} signature Signature using updated field to verify that the consumer has rights
* @return {Promise<String>} Result.
*/
public async retire(
did: DID | string,
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/${did.getDid()}`
const result = await this.fetch
.delete(
fullUrl,
JSON.stringify({
signature: signature,
updated: updated
})
)
.then((response: any) => {
if (response.ok) {
return response.text
}
this.logger.log('retire failed:', response.status, response.statusText)
return null
})
.catch((error) => {
this.logger.error('Error transfering ownership metadata: ', error)
return null
})
return result
}
public getServiceEndpoint(did: DID): string {
return `${this.url}/api/v1/aquarius/assets/ddo/did:op:${did.getId()}`
}
public getURI(): string {
return `${this.url}`
}
private transformResult(
{ results, page, total_pages: totalPages, total_results: totalResults }: any = {
result: [],
page: 0,
total_pages: 0,
total_results: 0
}
): QueryResult {
return {
results: (results || []).map((ddo) => new DDO(ddo as DDO)),
page,
totalPages,
totalResults
}
}
}

View File

@ -2,100 +2,100 @@ import { LogLevel } from '../utils/Logger'
export { LogLevel } from '../utils/Logger'
export class Config {
/**
* Ethereum node URL.
* @type {string}
*/
public nodeUri?: string
/**
* Ethereum node URL.
* @type {string}
*/
public nodeUri?: string
/**
* Address of Provider.
* @type {string}
*/
public providerAddress?: string
/**
* Address of Provider.
* @type {string}
*/
public providerAddress?: string
/**
* Metadata Store URL.
* @type {string}
*/
public metadataStoreUri?: string
/**
* Metadata Store URL.
* @type {string}
*/
public metadataStoreUri?: string
/**
* Provider URL.
* @type {string}
*/
public providerUri?: string
/**
* Provider URL.
* @type {string}
*/
public providerUri?: string
/**
* Web3 Provider.
* @type {any}
*/
public web3Provider?: any
/**
* Web3 Provider.
* @type {any}
*/
public web3Provider?: any
/**
* Ocean Token address
* @type {string}
*/
public oceanTokenAddress?: string
/**
* Ocean Token address
* @type {string}
*/
public oceanTokenAddress?: string
/**
* Factory address
* @type {string}
*/
public factoryAddress?: string
/**
* Factory address
* @type {string}
*/
public factoryAddress?: string
/**
* Factory ABI
* @type {string}
*/
public factoryABI?: object
/**
* Factory ABI
* @type {string}
*/
public factoryABI?: any
/**
* datatokens ABI
* @type {string}
*/
public datatokensABI?: object
/**
* datatokens ABI
* @type {string}
*/
public datatokensABI?: any
/**
* Pool Factory address
* @type {string}
*/
public poolFactoryAddress?: string
/**
* Pool Factory address
* @type {string}
*/
public poolFactoryAddress?: string
/**
* Pool Factory ABI
* @type {string}
*/
public poolFactoryABI?: object
/**
* Pool Factory ABI
* @type {string}
*/
public poolFactoryABI?: any
/**
* Pool ABI
* @type {string}
*/
public poolABI?: object
/**
* Pool ABI
* @type {string}
*/
public poolABI?: any
/**
* Log level.
* @type {boolean | LogLevel}
*/
public verbose?: boolean | LogLevel
/**
* Log level.
* @type {boolean | LogLevel}
*/
public verbose?: boolean | LogLevel
/**
* Message shown when the user creates its own token.
* @type {string}
*/
public authMessage?: string
/**
* Message shown when the user creates its own token.
* @type {string}
*/
public authMessage?: string
/**
* Token expiration time in ms.
* @type {number}
*/
public authTokenExpiration?: number
/**
* Token expiration time in ms.
* @type {number}
*/
public authTokenExpiration?: number
// Parity config
public parityUri?: string
// Parity config
public parityUri?: string
public threshold?: number
public threshold?: number
}
export default Config

View File

@ -5,44 +5,44 @@ import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
* Account information.
*/
export default class Account extends Instantiable {
private password?: string
private password?: string
private token?: string
private token?: string
constructor(private id: string = '0x0', config?: InstantiableConfig) {
super()
if (config) {
this.setInstanceConfig(config)
}
constructor(private id: string = '0x0', config?: InstantiableConfig) {
super()
if (config) {
this.setInstanceConfig(config)
}
}
public getId() {
return this.id
}
public getId() {
return this.id
}
public setId(id) {
this.id = id
}
public setId(id) {
this.id = id
}
/**
* Set account password.
* @param {string} password Password for account.
*/
public setPassword(password: string): void {
this.password = password
}
/**
* Set account password.
* @param {string} password Password for account.
*/
public setPassword(password: string): void {
this.password = password
}
/**
* Returns account password.
* @return {string} Account password.
*/
public getPassword(): string {
return this.password
}
/**
* Returns account password.
* @return {string} Account password.
*/
public getPassword(): string {
return this.password
}
// TODO - Check with Samer if authentificate is still needed or we can use sign
// TODO - Check with Samer if authentificate is still needed or we can use sign
/**
/**
* Set account token.
* @param {string} token Token for account.
@ -50,7 +50,7 @@ export default class Account extends Instantiable {
this.token = token
}
*/
/**
/**
* Returns account token.
* @return {Promise<string>} Account token.
@ -59,7 +59,7 @@ export default class Account extends Instantiable {
}
*/
/**
/**
* Returns if account token is stored.
* @return {Promise<boolean>} Is stored.
@ -67,7 +67,7 @@ export default class Account extends Instantiable {
return this.ocean.auth.isStored(this)
}
*/
/**
/**
* Authenticate the account.
public authenticate() {
@ -75,70 +75,68 @@ export default class Account extends Instantiable {
}
*/
/**
* Balance of Any Token (converted from wei).
* @return {Promise<string>}
*/
public async getTokenBalance(TokenAdress: string): Promise<string> {
if (TokenAdress === null) return null
const minABI = [
{
constant: true,
inputs: [
{
name: '_owner',
type: 'address'
}
],
name: 'balanceOf',
outputs: [
{
name: 'balance',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
]
let result = null
try {
const token = new this.web3.eth.Contract(minABI as any, TokenAdress, {
from: this.id
})
result = this.web3.utils.fromWei(
await token.methods.balanceOf(this.id).call()
)
} catch (e) {
console.error(e)
}
return result
/**
* Balance of Any Token (converted from wei).
* @return {Promise<string>}
*/
public async getTokenBalance(TokenAdress: string): Promise<string> {
if (TokenAdress === null) return null
const minABI = [
{
constant: true,
inputs: [
{
name: '_owner',
type: 'address'
}
],
name: 'balanceOf',
outputs: [
{
name: 'balance',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
]
let result = null
try {
const token = new this.web3.eth.Contract(minABI as any, TokenAdress, {
from: this.id
})
result = this.web3.utils.fromWei(await token.methods.balanceOf(this.id).call())
} catch (e) {
console.error(e)
}
return result
}
/**
* Balance of Ocean Token. (converted from wei).
* @return {Promise<string>}
*/
public async getOceanBalance(): Promise<string> {
return this.getTokenBalance(this.config.oceanTokenAddress)
}
/**
* Balance of Ocean Token. (converted from wei).
* @return {Promise<string>}
*/
public async getOceanBalance(): Promise<string> {
return this.getTokenBalance(this.config.oceanTokenAddress)
}
/**
* Symbol of a Token
* @return {Promise<string>}
*/
public async getTokenSymbol(TokenAdress: string): Promise<string> {
// TO DO
return ''
}
/**
* Symbol of a Token
* @return {Promise<string>}
*/
public async getTokenSymbol(TokenAdress: string): Promise<string> {
// TO DO
return ''
}
/**
* Balance of Ether.(converted from wei).
* @return {Promise<string>}
*/
public async getEtherBalance(): Promise<string> {
const result = await this.web3.eth.getBalance(this.id, 'latest')
return this.web3.utils.fromWei(result)
}
/**
* Balance of Ether.(converted from wei).
* @return {Promise<string>}
*/
public async getEtherBalance(): Promise<string> {
const result = await this.web3.eth.getBalance(this.id, 'latest')
return this.web3.utils.fromWei(result)
}
}

View File

@ -5,56 +5,56 @@ import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
* Account submodule of Ocean Protocol.
*/
export class Accounts extends Instantiable {
/**
* Returns the instance of OceanAccounts.
* @return {Promise<OceanAccounts>}
*/
public static async getInstance(config: InstantiableConfig): Promise<Accounts> {
const instance = new Accounts()
instance.setInstanceConfig(config)
/**
* Returns the instance of OceanAccounts.
* @return {Promise<OceanAccounts>}
*/
public static async getInstance(config: InstantiableConfig): Promise<Accounts> {
const instance = new Accounts()
instance.setInstanceConfig(config)
return instance
}
return instance
}
/**
* Returns the list of accounts.
* @return {Promise<Account[]>}
*/
public async list(): Promise<Account[]> {
// retrieve eth accounts
const ethAccounts: string[] = await this.web3.eth.getAccounts()
/**
* Returns the list of accounts.
* @return {Promise<Account[]>}
*/
public async list(): Promise<Account[]> {
// retrieve eth accounts
const ethAccounts: string[] = await this.web3.eth.getAccounts()
const accountPromises = ethAccounts.map(
(address) => new Account(address, this.instanceConfig)
)
return Promise.all(accountPromises)
}
const accountPromises = ethAccounts.map(
(address) => new Account(address, this.instanceConfig)
)
return Promise.all(accountPromises)
}
/**
* Return account balance for a given ERC20 token
* @param {String} TokenAddress .
* @param {Account} account Account instance.
* @return {Promise<String>} Token balance.
*/
public getTokenBalance(TokenAddress: string, account: Account): Promise<string> {
return account.getTokenBalance(TokenAddress)
}
/**
* Return account balance for a given ERC20 token
* @param {String} TokenAddress .
* @param {Account} account Account instance.
* @return {Promise<String>} Token balance.
*/
public getTokenBalance(TokenAddress: string, account: Account): Promise<string> {
return account.getTokenBalance(TokenAddress)
}
/**
* Return account balance for a Ocean Tokens
* @param {Account} account Account instance.
* @return {Promise<String>} Ocean Token balance.
*/
public getOceanBalance(account: Account): Promise<string> {
return account.getOceanBalance()
}
/**
* Return account balance for a Ocean Tokens
* @param {Account} account Account instance.
* @return {Promise<String>} Ocean Token balance.
*/
public getOceanBalance(account: Account): Promise<string> {
return account.getOceanBalance()
}
/**
* Return account balance in ETH
* @param {Account} account Account instance.
* @return {Promise<String>} Ether balance.
*/
public getEtherBalance(account: Account): Promise<string> {
return account.getEtherBalance()
}
/**
* Return account balance in ETH
* @param {Account} account Account instance.
* @return {Promise<String>} Ether balance.
*/
public getEtherBalance(account: Account): Promise<string> {
return account.getEtherBalance()
}
}

View File

@ -1,13 +1,11 @@
import { SearchQuery } from '../metadatastore/MetadataStore'
import { SearchQuery, QueryResult } from '../metadatastore/MetadataStore'
import { DDO } from '../ddo/DDO'
import { Metadata } from '../ddo/interfaces/Metadata'
import { MetadataAlgorithm } from '../ddo/interfaces/MetadataAlgorithm'
import {
Service,
ServiceAccess,
ServiceComputePrivacy,
ServiceCommon,
ServiceCompute
Service,
ServiceAccess,
ServiceComputePrivacy,
ServiceCommon
} from '../ddo/interfaces/Service'
import { EditableMetadata } from '../ddo/interfaces/EditableMetadata'
@ -16,465 +14,456 @@ import DID from './DID'
import { SubscribablePromise } from '../utils'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import { WebServiceConnector } from './utils/WebServiceConnector'
import { Output } from './interfaces/ComputeOutput'
import { ComputeJob } from './interfaces/ComputeJob'
export enum CreateProgressStep {
CreatingDataToken,
DataTokenCreated,
EncryptingFiles,
FilesEncrypted,
GeneratingProof,
ProofGenerated,
StoringDdo,
DdoStored
CreatingDataToken,
DataTokenCreated,
EncryptingFiles,
FilesEncrypted,
GeneratingProof,
ProofGenerated,
StoringDdo,
DdoStored
}
export enum OrderProgressStep {
TransferDataToken
TransferDataToken
}
/**
* Assets submodule of Ocean Protocol.
*/
export class Assets extends Instantiable {
/**
* Returns the instance of Assets.
* @return {Promise<Assets>}
*/
public static async getInstance(config: InstantiableConfig): Promise<Assets> {
const instance = new Assets()
instance.setInstanceConfig(config)
/**
* Returns the instance of Assets.
* @return {Promise<Assets>}
*/
public static async getInstance(config: InstantiableConfig): Promise<Assets> {
const instance = new Assets()
instance.setInstanceConfig(config)
return instance
}
return instance
}
/**
* Creates a new DDO and publishes it
* @param {Metadata} metadata DDO metadata.
* @param {Account} publisher Publisher account.
* @param {list} services list of Service description documents
* @return {Promise<DDO>}
*/
public create(
metadata: Metadata,
publisher: Account,
services: Service[] = [],
dtAddress?: string
): SubscribablePromise<CreateProgressStep, DDO> {
this.logger.log('Creating asset')
return new SubscribablePromise(async (observer) => {
if (services.length === 0) {
this.logger.log('You have no services. Are you sure about this?')
}
if (!dtAddress) {
this.logger.log('Creating datatoken')
observer.next(CreateProgressStep.CreatingDataToken)
const metadataStoreURI = this.ocean.metadatastore.getURI()
const jsonBlob = { t: 1, url: metadataStoreURI }
const { datatokens } = this.ocean
dtAddress = await datatokens.create(
JSON.stringify(jsonBlob),
publisher.getId()
)
this.logger.log('DataToken creted')
observer.next(CreateProgressStep.DataTokenCreated)
}
/**
* Creates a new DDO and publishes it
* @param {Metadata} metadata DDO metadata.
* @param {Account} publisher Publisher account.
* @param {list} services list of Service description documents
* @return {Promise<DDO>}
*/
public create(
metadata: Metadata,
publisher: Account,
services: Service[] = [],
dtAddress?: string
): SubscribablePromise<CreateProgressStep, DDO> {
this.logger.log('Creating asset')
return new SubscribablePromise(async (observer) => {
if (services.length === 0) {
this.logger.log('You have no services. Are you sure about this?')
}
if (!dtAddress) {
this.logger.log('Creating datatoken')
observer.next(CreateProgressStep.CreatingDataToken)
const metadataStoreURI = this.ocean.metadatastore.getURI()
const jsonBlob = { t: 1, url: metadataStoreURI }
const { datatokens } = this.ocean
dtAddress = await datatokens.create(JSON.stringify(jsonBlob), publisher.getId())
this.logger.log('DataToken creted')
observer.next(CreateProgressStep.DataTokenCreated)
}
const did: DID = DID.generate()
const did: DID = DID.generate()
this.logger.log('Encrypting files')
observer.next(CreateProgressStep.EncryptingFiles)
const encryptedFiles = await this.ocean.provider.encrypt(
did.getId(),
metadata.main.files,
publisher
)
this.logger.log('Files encrypted')
observer.next(CreateProgressStep.FilesEncrypted)
this.logger.log('Encrypting files')
observer.next(CreateProgressStep.EncryptingFiles)
const encryptedFiles = await this.ocean.provider.encrypt(
did.getId(),
metadata.main.files,
publisher
)
this.logger.log('Files encrypted')
observer.next(CreateProgressStep.FilesEncrypted)
let indexCount = 0
// create ddo itself
const ddo: DDO = new DDO({
id: did.getDid(),
dataToken: dtAddress,
authentication: [
{
type: 'RsaSignatureAuthentication2018',
publicKey: did.getDid()
}
],
publicKey: [
{
id: did.getDid(),
type: 'EthereumECDSAKey',
owner: publisher.getId()
}
],
service: [
{
type: 'metadata',
attributes: {
// Default values
curation: {
rating: 0,
numVotes: 0
},
// Overwrites defaults
...metadata,
encryptedFiles,
// Cleaning not needed information
main: {
...metadata.main,
files: metadata.main.files.map((file, index) => ({
...file,
index,
url: undefined
}))
} as any
}
},
...services
]
// Remove duplications
.reverse()
.filter(
({ type }, i, list) =>
list.findIndex(({ type: t }) => t === type) === i
)
.reverse()
// Adding index
.map((_) => ({
..._,
index: indexCount++
})) as Service[]
})
this.logger.log('Generating proof')
observer.next(CreateProgressStep.GeneratingProof)
await ddo.addProof(this.ocean, publisher.getId(), publisher.getPassword())
this.logger.log('Proof generated')
observer.next(CreateProgressStep.ProofGenerated)
this.logger.log('Storing DDO')
observer.next(CreateProgressStep.StoringDdo)
const storedDdo = await this.ocean.metadatastore.storeDDO(ddo)
this.logger.log('DDO stored')
observer.next(CreateProgressStep.DdoStored)
return storedDdo
})
}
/**
* Returns the assets of a owner.
* @param {string} owner Owner address.
* @return {Promise<string[]>} List of DIDs.
*/
public async ownerAssets(owner: string): Promise<DDO[]> {
return this.ocean.metadatastore.getOwnerAssets(owner)
}
/**
* Returns a DDO by DID.
* @param {string} did Decentralized ID.
* @return {Promise<DDO>}
*/
public async resolve(did: string): Promise<DDO> {
return this.ocean.metadatastore.retrieveDDO(did)
}
public async resolveByDTAddress(
dtAddress: string,
offset?: number,
page?: number,
sort?: number
): Promise<DDO[]> {
const searchQuery = {
offset: offset || 100,
page: page || 1,
query: {
dtAddress: [dtAddress]
},
sort: {
value: sort || 1
},
text: dtAddress
} as SearchQuery
return (await this.ocean.metadatastore.queryMetadata(searchQuery)).results
}
/**
* Edit Metadata for a DDO.
* @param {did} string DID.
* @param {newMetadata} EditableMetadata Metadata fields & new values.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async editMetadata(
did: string,
newMetadata: EditableMetadata,
account: Account
): Promise<string> {
const oldDdo = await this.ocean.metadatastore.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.metadatastore.editMetadata(
did,
newMetadata,
oldDdo.updated,
signature
)
return result
}
/**
* Update Compute Privacy
* @param {did} string DID.
* @param {number} serviceIndex Index of the compute service in the DDO
* @param {ServiceComputePrivacy} computePrivacy ComputePrivacy fields & new values.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async updateComputePrivacy(
did: string,
serviceIndex: number,
computePrivacy: ServiceComputePrivacy,
account: Account
): Promise<string> {
const oldDdo = await this.ocean.metadatastore.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.metadatastore.updateComputePrivacy(
did,
serviceIndex,
computePrivacy.allowRawAlgorithm,
computePrivacy.allowNetworkAccess,
computePrivacy.trustedAlgorithms,
oldDdo.updated,
signature
)
return result
}
/**
* Retire a DDO (Delete)
* @param {did} string DID.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async retire(did: string, account: Account): Promise<string> {
const oldDdo = await this.ocean.metadatastore.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.metadatastore.retire(did, oldDdo.updated, signature)
return result
}
/**
* Returns the creator of a asset.
* @param {string} did Decentralized ID.
* @return {Promise<string>} Returns eth address
*/
public async creator(did: string): Promise<string> {
const ddo = await this.resolve(did)
const checksum = ddo.getChecksum()
const { creator, signatureValue } = ddo.proof
const signer = await this.ocean.utils.signature.verifyText(
checksum,
signatureValue
)
if (signer.toLowerCase() !== creator.toLowerCase()) {
this.logger.warn(
`Owner of ${ddo.id} doesn't match. Expected ${creator} instead of ${signer}.`
)
}
return creator
}
/**
* Search over the assets using a query.
* @param {SearchQuery} query Query to filter the assets.
* @return {Promise<DDO[]>}
*/
public async query(query: SearchQuery) {
return this.ocean.metadatastore.queryMetadata(query)
}
/**
* Search over the assets using a keyword.
* @param {SearchQuery} text Text to filter the assets.
* @return {Promise<DDO[]>}
*/
public async search(text: string) {
return this.ocean.metadatastore.queryMetadataByText({
text,
page: 1,
offset: 100,
query: {
value: 1
},
sort: {
value: 1
}
} as SearchQuery)
}
public async getServiceByType(
did: string,
serviceType: string
): Promise<ServiceCommon> {
const services: ServiceCommon[] = (await this.resolve(did)).service
let service
services.forEach((serv) => {
if (serv.type.toString() === serviceType) {
service = serv
}
})
return service
}
public async getServiceByIndex(
did: string,
serviceIndex: number
): Promise<ServiceCommon> {
const services: ServiceCommon[] = (await this.resolve(did)).service
let service
services.forEach((serv) => {
if (serv.index === serviceIndex) {
service = serv
}
})
return service
}
/**
* Creates an access service
* @param {Account} creator
* @param {String} cost number of datatokens needed for this service, expressed in wei
* @param {String} datePublished
* @param {Number} timeout
* @return {Promise<string>} service
*/
public async createAccessServiceAttributes(
creator: Account,
cost: string,
datePublished: string,
timeout: number = 0
): Promise<ServiceAccess> {
return {
type: 'access',
index: 2,
serviceEndpoint: this.ocean.provider.getConsumeEndpoint(),
let indexCount = 0
// create ddo itself
const ddo: DDO = new DDO({
id: did.getDid(),
dataToken: dtAddress,
authentication: [
{
type: 'RsaSignatureAuthentication2018',
publicKey: did.getDid()
}
],
publicKey: [
{
id: did.getDid(),
type: 'EthereumECDSAKey',
owner: publisher.getId()
}
],
service: [
{
type: 'metadata',
attributes: {
main: {
creator: creator.getId(),
datePublished,
cost,
timeout: timeout,
name: 'dataAssetAccess'
}
// Default values
curation: {
rating: 0,
numVotes: 0
},
// Overwrites defaults
...metadata,
encryptedFiles,
// Cleaning not needed information
main: {
...metadata.main,
files: metadata.main.files.map((file, index) => ({
...file,
index,
url: undefined
}))
} as any
}
}
},
...services
]
// Remove duplications
.reverse()
.filter(
({ type }, i, list) => list.findIndex(({ type: t }) => t === type) === i
)
.reverse()
// Adding index
.map((_) => ({
..._,
index: indexCount++
})) as Service[]
})
this.logger.log('Generating proof')
observer.next(CreateProgressStep.GeneratingProof)
await ddo.addProof(this.ocean, publisher.getId(), publisher.getPassword())
this.logger.log('Proof generated')
observer.next(CreateProgressStep.ProofGenerated)
this.logger.log('Storing DDO')
observer.next(CreateProgressStep.StoringDdo)
const storedDdo = await this.ocean.metadatastore.storeDDO(ddo)
this.logger.log('DDO stored')
observer.next(CreateProgressStep.DdoStored)
return storedDdo
})
}
/**
* Returns the assets of a owner.
* @param {string} owner Owner address.
* @return {Promise<string[]>} List of DIDs.
*/
public async ownerAssets(owner: string): Promise<DDO[]> {
return this.ocean.metadatastore.getOwnerAssets(owner)
}
/**
* Returns a DDO by DID.
* @param {string} did Decentralized ID.
* @return {Promise<DDO>}
*/
public async resolve(did: string): Promise<DDO> {
return this.ocean.metadatastore.retrieveDDO(did)
}
public async resolveByDTAddress(
dtAddress: string,
offset?: number,
page?: number,
sort?: number
): Promise<DDO[]> {
const searchQuery = {
offset: offset || 100,
page: page || 1,
query: {
dtAddress: [dtAddress]
},
sort: {
value: sort || 1
},
text: dtAddress
} as SearchQuery
return (await this.ocean.metadatastore.queryMetadata(searchQuery)).results
}
/**
* Edit Metadata for a DDO.
* @param {did} string DID.
* @param {newMetadata} EditableMetadata Metadata fields & new values.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async editMetadata(
did: string,
newMetadata: EditableMetadata,
account: Account
): Promise<string> {
const oldDdo = await this.ocean.metadatastore.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.metadatastore.editMetadata(
did,
newMetadata,
oldDdo.updated,
signature
)
return result
}
/**
* Update Compute Privacy
* @param {did} string DID.
* @param {number} serviceIndex Index of the compute service in the DDO
* @param {ServiceComputePrivacy} computePrivacy ComputePrivacy fields & new values.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async updateComputePrivacy(
did: string,
serviceIndex: number,
computePrivacy: ServiceComputePrivacy,
account: Account
): Promise<string> {
const oldDdo = await this.ocean.metadatastore.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.metadatastore.updateComputePrivacy(
did,
serviceIndex,
computePrivacy.allowRawAlgorithm,
computePrivacy.allowNetworkAccess,
computePrivacy.trustedAlgorithms,
oldDdo.updated,
signature
)
return result
}
/**
* Retire a DDO (Delete)
* @param {did} string DID.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async retire(did: string, account: Account): Promise<string> {
const oldDdo = await this.ocean.metadatastore.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.metadatastore.retire(did, oldDdo.updated, signature)
return result
}
/**
* Returns the creator of a asset.
* @param {string} did Decentralized ID.
* @return {Promise<string>} Returns eth address
*/
public async creator(did: string): Promise<string> {
const ddo = await this.resolve(did)
const checksum = ddo.getChecksum()
const { creator, signatureValue } = ddo.proof
const signer = await this.ocean.utils.signature.verifyText(checksum, signatureValue)
if (signer.toLowerCase() !== creator.toLowerCase()) {
this.logger.warn(
`Owner of ${ddo.id} doesn't match. Expected ${creator} instead of ${signer}.`
)
}
public async order(
did: string,
serviceType: string,
consumerAddress: string,
serviceIndex: number = -1
): Promise<string> {
if (serviceIndex === -1) {
const service = await this.getServiceByType(did, serviceType)
serviceIndex = service.index
} else {
const service = await this.getServiceByIndex(did, serviceIndex)
serviceType = service.type
return creator
}
/**
* Search over the assets using a query.
* @param {SearchQuery} query Query to filter the assets.
* @return {Promise<QueryResult>}
*/
public async query(query: SearchQuery): Promise<QueryResult> {
return this.ocean.metadatastore.queryMetadata(query)
}
/**
* Search over the assets using a keyword.
* @param {SearchQuery} text Text to filter the assets.
* @return {Promise<QueryResult>}
*/
public async search(text: string): Promise<QueryResult> {
return this.ocean.metadatastore.queryMetadataByText({
text,
page: 1,
offset: 100,
query: {
value: 1
},
sort: {
value: 1
}
} as SearchQuery)
}
public async getServiceByType(
did: string,
serviceType: string
): Promise<ServiceCommon> {
const services: ServiceCommon[] = (await this.resolve(did)).service
let service
services.forEach((serv) => {
if (serv.type.toString() === serviceType) {
service = serv
}
})
return service
}
public async getServiceByIndex(
did: string,
serviceIndex: number
): Promise<ServiceCommon> {
const services: ServiceCommon[] = (await this.resolve(did)).service
let service
services.forEach((serv) => {
if (serv.index === serviceIndex) {
service = serv
}
})
return service
}
/**
* Creates an access service
* @param {Account} creator
* @param {String} cost number of datatokens needed for this service, expressed in wei
* @param {String} datePublished
* @param {Number} timeout
* @return {Promise<string>} service
*/
public async createAccessServiceAttributes(
creator: Account,
cost: string,
datePublished: string,
timeout: number = 0
): Promise<ServiceAccess> {
return {
type: 'access',
index: 2,
serviceEndpoint: this.ocean.provider.getConsumeEndpoint(),
attributes: {
main: {
creator: creator.getId(),
datePublished,
cost,
timeout: timeout,
name: 'dataAssetAccess'
}
return await this.ocean.provider.initialize(
did,
serviceIndex,
serviceType,
consumerAddress
)
}
}
}
public async order(
did: string,
serviceType: string,
consumerAddress: string,
serviceIndex: number = -1
): Promise<string> {
if (serviceIndex === -1) {
const service = await this.getServiceByType(did, serviceType)
serviceIndex = service.index
} else {
const service = await this.getServiceByIndex(did, serviceIndex)
serviceType = service.type
}
return await this.ocean.provider.initialize(
did,
serviceIndex,
serviceType,
consumerAddress
)
}
// marketplace flow
public async download(
did: string,
txId: string,
tokenAddress: string,
consumerAccount: Account,
destination: string
): Promise<string | true> {
const ddo = await this.resolve(did)
const { attributes } = ddo.findServiceByType('metadata')
const service = ddo.findServiceByType('access')
const { files } = attributes.main
const { serviceEndpoint } = service
if (!serviceEndpoint) {
throw new Error(
'Consume asset failed, service definition is missing the `serviceEndpoint`.'
)
}
// marketplace flow
public async download(
did: string,
txId: string,
tokenAddress: string,
consumerAccount: Account,
destination: string
): Promise<string | true> {
const ddo = await this.resolve(did)
const { attributes } = ddo.findServiceByType('metadata')
const service = ddo.findServiceByType('access')
const { files } = attributes.main
const { serviceEndpoint } = service
this.logger.log('Consuming files')
if (!serviceEndpoint) {
throw new Error(
'Consume asset failed, service definition is missing the `serviceEndpoint`.'
)
}
destination = destination
? `${destination}/datafile.${ddo.shortId()}.${service.index}/`
: undefined
this.logger.log('Consuming files')
await this.ocean.provider.download(
did,
txId,
tokenAddress,
service.type,
service.index.toString(),
destination,
consumerAccount,
files
)
return true
}
destination = destination
? `${destination}/datafile.${ddo.shortId()}.${service.index}/`
: undefined
await this.ocean.provider.download(
did,
txId,
tokenAddress,
service.type,
service.index.toString(),
destination,
consumerAccount,
files
)
return true
// simple flow
public async simpleDownload(
dtAddress: string,
serviceEndpoint: string,
txId: string,
account: string
): Promise<string> {
let consumeUrl = serviceEndpoint
consumeUrl += `?consumerAddress=${account}`
consumeUrl += `&tokenAddress=${dtAddress}`
consumeUrl += `&transferTxId=${txId}`
const serviceConnector = new WebServiceConnector(this.logger)
console.log(consumeUrl)
try {
await serviceConnector.downloadFile(consumeUrl)
} catch (e) {
this.logger.error('Error consuming assets')
this.logger.error(e)
throw e
}
// simple flow
public async simpleDownload(
dtAddress: string,
serviceEndpoint: string,
txId: string,
account: string
): Promise<string> {
let consumeUrl = serviceEndpoint
consumeUrl += `?consumerAddress=${account}`
consumeUrl += `&tokenAddress=${dtAddress}`
consumeUrl += `&transferTxId=${txId}`
const serviceConnector = new WebServiceConnector(this.logger)
console.log(consumeUrl)
try {
await serviceConnector.downloadFile(consumeUrl)
} catch (e) {
this.logger.error('Error consuming assets')
this.logger.error(e)
throw e
}
return serviceEndpoint
}
return serviceEndpoint
}
}

View File

@ -8,354 +8,381 @@ import { Output } from './interfaces/ComputeOutput'
import { ComputeJob } from './interfaces/ComputeJob'
export enum OrderProgressStep {
TransferDataToken
TransferDataToken
}
export interface Cluster {
type: string
url: string
}
export interface Container {
image: string
tag: string
checksum: string
}
export interface Server {
serverId: string
serverType: string
cost: string
cpu: string
gpu: string
memory: string
disk: string
maxExecutionTime: number
}
export const ComputeJobStatus = Object.freeze({
Started: 10,
ConfiguringVolumes: 20,
ProvisioningSuccess: 30,
DataProvisioningFailed: 31,
AlgorithmProvisioningFailed: 32,
RunningAlgorithm: 40,
FilteringResults: 50,
PublishingResult: 60,
Completed: 70,
Stopped: 80,
Deleted: 90
Started: 10,
ConfiguringVolumes: 20,
ProvisioningSuccess: 30,
DataProvisioningFailed: 31,
AlgorithmProvisioningFailed: 32,
RunningAlgorithm: 40,
FilteringResults: 50,
PublishingResult: 60,
Completed: 70,
Stopped: 80,
Deleted: 90
})
/**
* Compute submodule of Ocean Protocol.
*/
export class Compute extends Instantiable {
/**
* Returns the instance of Compute.
* @return {Promise<Assets>}
*/
public static async getInstance(config: InstantiableConfig): Promise<Compute> {
const instance = new Compute()
instance.setInstanceConfig(config)
/**
* Returns the instance of Compute.
* @return {Promise<Assets>}
*/
public static async getInstance(config: InstantiableConfig): Promise<Compute> {
const instance = new Compute()
instance.setInstanceConfig(config)
return instance
return instance
}
/**
* Start the execution of a compute job.
* @param {string} did Decentralized identifer for the asset
* @param {string} txId
* @param {string} tokenAddress
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset.
* @param {MetaData} algorithmMeta Metadata about the algorithm being run if `algorithm` is being used. This is ignored when `algorithmDid` is specified.
* @param {Output} output Define algorithm output publishing. Publishing the result of a compute job is turned off by default.
* @return {Promise<ComputeJob>} Returns compute job ID under status.jobId
*/
public async start(
did: string,
txId: string,
tokenAddress: string,
consumerAccount: Account,
algorithmDid?: string,
algorithmMeta?: MetadataAlgorithm,
output?: Output,
serviceIndex?: string,
serviceType?: string,
algorithmTransferTxId?: string,
algorithmDataToken?: string
): Promise<ComputeJob> {
output = this.checkOutput(consumerAccount, output)
if (did) {
const computeJobsList = await this.ocean.provider.compute(
'post',
did,
consumerAccount,
algorithmDid,
algorithmMeta,
undefined,
output,
txId,
serviceIndex,
serviceType,
tokenAddress,
algorithmTransferTxId,
algorithmDataToken
)
return computeJobsList[0] as ComputeJob
} else return null
}
/**
* Ends a running compute job.
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} did Decentralized identifier.
* @param {string} jobId The ID of the compute job to be stopped
* @return {Promise<ComputeJob>} Returns the new status of a job
*/
public async stop(
consumerAccount: Account,
did: string,
jobId: string
): Promise<ComputeJob> {
const computeJobsList = await this.ocean.provider.compute(
'put',
did,
consumerAccount,
undefined,
undefined,
jobId
)
return computeJobsList[0] as ComputeJob
}
/**
* Deletes a compute job and all resources associated with the job. If job is running it will be stopped first.
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} did Decentralized identifier.
* @param {string} jobId The ID of the compute job to be stopped
* @return {Promise<ComputeJob>} Returns the new status of a job
*/
public async delete(
consumerAccount: Account,
did: string,
jobId: string
): Promise<ComputeJob> {
const computeJobsList = await this.ocean.provider.compute(
'delete',
did,
consumerAccount,
undefined,
undefined,
jobId
)
return computeJobsList[0] as ComputeJob
}
/**
* Returns information about the status of all compute jobs, or a single compute job.
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} did Decentralized identifier.
* @param {string} jobId The ID of the compute job to be stopped
* @return {Promise<ComputeJob[]>} Returns the status
*/
public async status(
consumerAccount: Account,
did?: string,
jobId?: string
): Promise<ComputeJob[]> {
const computeJobsList = await this.ocean.provider.compute(
'get',
did,
consumerAccount,
undefined,
undefined,
jobId
)
return computeJobsList as ComputeJob[]
}
/**
* Returns the final result of a specific compute job published as an asset.
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} did Decentralized identifier.
* @param {string} jobId The ID of the compute job to be stopped.
* @return {Promise<ComputeJob>} Returns the DDO of the result asset.
*/
public async result(
consumerAccount: Account,
did: string,
jobId: string
): Promise<ComputeJob> {
const computeJobsList = await this.ocean.provider.compute(
'get',
did,
consumerAccount,
undefined,
undefined,
jobId
)
return computeJobsList[0] as ComputeJob
}
public createServerAttributes(
serverId: string,
serverType: string,
cost: string,
cpu: string,
gpu: string,
memory: string,
disk: string,
maxExecutionTime: number
): Server {
return {
serverId,
serverType,
cost,
cpu,
gpu,
memory,
disk,
maxExecutionTime
}
}
/**
* Start the execution of a compute job.
* @param {string} did Decentralized identifer for the asset
* @param {string} txId
* @param {string} tokenAddress
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset.
* @param {MetaData} algorithmMeta Metadata about the algorithm being run if `algorithm` is being used. This is ignored when `algorithmDid` is specified.
* @param {Output} output Define algorithm output publishing. Publishing the result of a compute job is turned off by default.
* @return {Promise<ComputeJob>} Returns compute job ID under status.jobId
*/
public async start(
did: string,
txId: string,
tokenAddress: string,
consumerAccount: Account,
algorithmDid?: string,
algorithmMeta?: MetadataAlgorithm,
output?: Output,
serviceIndex?: string,
serviceType?: string,
algorithmTransferTxId?: string,
algorithmDataToken?: string
): Promise<ComputeJob> {
output = this.checkOutput(consumerAccount, output)
if (did) {
const computeJobsList = await this.ocean.provider.compute(
'post',
did,
consumerAccount,
algorithmDid,
algorithmMeta,
undefined,
output,
txId,
serviceIndex,
serviceType,
tokenAddress,
algorithmTransferTxId,
algorithmDataToken
)
return computeJobsList[0] as ComputeJob
} else return null
public createContainerAttributes(
image: string,
tag: string,
checksum: string
): Container {
return { image, tag, checksum }
}
public createClusterAttributes(type: string, url: string): Cluster {
return { type, url }
}
public createProviderAttributes(
type: string,
description: string,
cluster: Cluster,
containers: Container[],
servers: Server[]
): {
type: string
description: string
environment: {
cluster: Cluster
supportedServers: Server[]
supportedContainers: Container[]
}
/**
* Ends a running compute job.
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} did Decentralized identifier.
* @param {string} jobId The ID of the compute job to be stopped
* @return {Promise<ComputeJob>} Returns the new status of a job
*/
public async stop(
consumerAccount: Account,
did: string,
jobId: string
): Promise<ComputeJob> {
const computeJobsList = await this.ocean.provider.compute(
'put',
did,
consumerAccount,
undefined,
undefined,
jobId
)
return computeJobsList[0] as ComputeJob
} {
return {
type,
description,
environment: {
cluster: cluster,
supportedServers: servers,
supportedContainers: containers
}
}
}
/**
* Deletes a compute job and all resources associated with the job. If job is running it will be stopped first.
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} did Decentralized identifier.
* @param {string} jobId The ID of the compute job to be stopped
* @return {Promise<ComputeJob>} Returns the new status of a job
*/
public async delete(
consumerAccount: Account,
did: string,
jobId: string
): Promise<ComputeJob> {
const computeJobsList = await this.ocean.provider.compute(
'delete',
did,
consumerAccount,
undefined,
undefined,
jobId
)
return computeJobsList[0] as ComputeJob
}
/**
* Returns information about the status of all compute jobs, or a single compute job.
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} did Decentralized identifier.
* @param {string} jobId The ID of the compute job to be stopped
* @return {Promise<ComputeJob[]>} Returns the status
*/
public async status(
consumerAccount: Account,
did?: string,
jobId?: string
): Promise<ComputeJob[]> {
const computeJobsList = await this.ocean.provider.compute(
'get',
did,
consumerAccount,
undefined,
undefined,
jobId
)
return computeJobsList as ComputeJob[]
}
/**
* Returns the final result of a specific compute job published as an asset.
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} did Decentralized identifier.
* @param {string} jobId The ID of the compute job to be stopped.
* @return {Promise<ComputeJob>} Returns the DDO of the result asset.
*/
public async result(
consumerAccount: Account,
did: string,
jobId: string
): Promise<ComputeJob> {
const computeJobsList = await this.ocean.provider.compute(
'get',
did,
consumerAccount,
undefined,
undefined,
jobId
)
return computeJobsList[0] as ComputeJob
}
public createServerAttributes(
serverId: string,
serverType: string,
cost: string,
cpu: string,
gpu: string,
memory: string,
disk: string,
maxExecutionTime: number
): object {
return {
serverId,
serverType,
cost,
cpu,
gpu,
memory,
disk,
maxExecutionTime
/**
* Creates a compute service
* @param {Account} consumerAccount
* @param {String} cost number of datatokens needed for this service, expressed in wei
* @param {String} datePublished
* @param {Object} providerAttributes
* @param {Object} computePrivacy
* @param {Number} timeout
* @return {Promise<string>} service
*/
public createComputeService(
consumerAccount: Account,
cost: string,
datePublished: string,
providerAttributes: any,
computePrivacy?: ServiceComputePrivacy,
timeout?: number
): ServiceCompute {
const name = 'dataAssetComputingService'
if (!timeout) timeout = 3600
const service = {
type: 'compute',
index: 3,
serviceEndpoint: this.ocean.provider.getComputeEndpoint(),
attributes: {
main: {
name,
creator: consumerAccount.getId(),
datePublished,
cost,
timeout: timeout,
provider: providerAttributes,
privacy: {}
}
}
}
public createContainerAttributes(
image: string,
tag: string,
checksum: string
): object {
return { image, tag, checksum }
if (computePrivacy) service.attributes.main.privacy = computePrivacy
return service as ServiceCompute
}
/**
* Check the output object and add default properties if needed
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {Output} output Output section used for publishing the result.
* @return {Promise<Output>} Returns output object
*/
private checkOutput(consumerAccount: Account, output?: Output): Output {
const isDefault = !output || (!output.publishAlgorithmLog && !output.publishOutput)
if (isDefault) {
return {
publishAlgorithmLog: false,
publishOutput: false
}
}
public createClusterAttributes(type: string, url: string): object {
return { type, url }
return {
publishAlgorithmLog: output.publishAlgorithmLog,
publishOutput: output.publishOutput,
providerAddress: output.providerAddress || this.config.providerAddress,
providerUri: output.providerUri || this.config.providerUri,
metadataUri: output.metadataUri || this.config.metadataStoreUri,
nodeUri: output.nodeUri || this.config.nodeUri,
owner: output.owner || consumerAccount.getId()
}
}
public createProviderAttributes(
type: string,
description: string,
cluster: object,
containers: object[],
servers: object[]
): object {
return {
type,
description,
environment: {
cluster: cluster,
supportedServers: containers,
supportedContainers: servers
}
}
}
/**
* Creates a compute service
* @param {Account} consumerAccount
* @param {String} cost number of datatokens needed for this service, expressed in wei
* @param {String} datePublished
* @param {Object} providerAttributes
* @param {Object} computePrivacy
* @param {Number} timeout
* @return {Promise<string>} service
*/
public createComputeService(
consumerAccount: Account,
cost: string,
datePublished: string,
providerAttributes: object,
computePrivacy?: ServiceComputePrivacy,
timeout?: number
): ServiceCompute {
const name = 'dataAssetComputingService'
if (!timeout) timeout = 3600
const service = {
type: 'compute',
index: 3,
serviceEndpoint: this.ocean.provider.getComputeEndpoint(),
attributes: {
main: {
name,
creator: consumerAccount.getId(),
datePublished,
cost,
timeout: timeout,
provider: providerAttributes,
privacy: {}
}
}
}
if (computePrivacy) service.attributes.main.privacy = computePrivacy
return service as ServiceCompute
}
/**
* Check the output object and add default properties if needed
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {Output} output Output section used for publishing the result.
* @return {Promise<Output>} Returns output object
*/
private checkOutput(consumerAccount: Account, output?: Output): Output {
const isDefault =
!output || (!output.publishAlgorithmLog && !output.publishOutput)
if (isDefault) {
return {
publishAlgorithmLog: false,
publishOutput: false
}
}
return {
publishAlgorithmLog: output.publishAlgorithmLog,
publishOutput: output.publishOutput,
providerAddress: output.providerAddress || this.config.providerAddress,
providerUri: output.providerUri || this.config.providerUri,
metadataUri: output.metadataUri || this.config.metadataStoreUri,
nodeUri: output.nodeUri || this.config.nodeUri,
owner: output.owner || consumerAccount.getId()
}
}
/**
* Starts an order of a compute service that is defined in an asset's services.
* @param {String} consumerAccount The account of the consumer ordering the service.
* @param {string} datasetDid The DID of the dataset asset (of type `dataset`) to run the algorithm on.
* @param {string} serviceIndex The Service index
* @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset.
* @param {MetaData} algorithmMeta Metadata about the algorithm being run if `algorithm` is being used. This is ignored when `algorithmDid` is specified.
* @return {Promise<string>} Returns the transaction details
*
* Note: algorithmDid and algorithmMeta are optional, but if they are not passed,
* you can end up in the situation that you are ordering and paying for your compute job,
* but provider will not allow the compute, due to privacy settings of the ddo
*/
public order(
consumerAccount: string,
datasetDid: string,
serviceIndex: number,
algorithmDid?: string,
algorithmMeta?: MetadataAlgorithm
): SubscribablePromise<OrderProgressStep, string> {
return new SubscribablePromise(async (observer) => {
const ddo: DDO = await this.ocean.assets.resolve(datasetDid)
// const service: Service = ddo.findServiceByType('compute')
const service: Service = ddo.findServiceById(serviceIndex)
if (!service) return null
if (service.type !== 'compute') return null
if (algorithmMeta) {
// check if raw algo is allowed
if (service.attributes.main.privacy)
if (!service.attributes.main.privacy.allowRawAlgorithm) {
console.error('This service does not allow Raw Algo')
return null
}
}
if (algorithmDid) {
// check if did is in trusted list
if (service.attributes.main.privacy)
if (service.attributes.main.privacy.trustedAlgorithms)
if (service.attributes.main.privacy.trustedAlgorithms.length > 0)
if (
!service.attributes.main.privacy.trustedAlgorithms.includes(
algorithmDid
)
) {
console.error('This service does not allow this Algo')
return null
}
}
const order = await this.ocean.assets.order(
datasetDid,
service.type,
consumerAccount
)
return order
})
}
/**
* Starts an order of a compute service that is defined in an asset's services.
* @param {String} consumerAccount The account of the consumer ordering the service.
* @param {string} datasetDid The DID of the dataset asset (of type `dataset`) to run the algorithm on.
* @param {string} serviceIndex The Service index
* @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset.
* @param {MetaData} algorithmMeta Metadata about the algorithm being run if `algorithm` is being used. This is ignored when `algorithmDid` is specified.
* @return {Promise<string>} Returns the transaction details
*
* Note: algorithmDid and algorithmMeta are optional, but if they are not passed,
* you can end up in the situation that you are ordering and paying for your compute job,
* but provider will not allow the compute, due to privacy settings of the ddo
*/
public order(
consumerAccount: string,
datasetDid: string,
serviceIndex: number,
algorithmDid?: string,
algorithmMeta?: MetadataAlgorithm
): SubscribablePromise<OrderProgressStep, string> {
return new SubscribablePromise(async (observer) => {
const ddo: DDO = await this.ocean.assets.resolve(datasetDid)
// const service: Service = ddo.findServiceByType('compute')
const service: Service = ddo.findServiceById(serviceIndex)
if (!service) return null
if (service.type !== 'compute') return null
if (algorithmMeta) {
// check if raw algo is allowed
if (service.attributes.main.privacy)
if (!service.attributes.main.privacy.allowRawAlgorithm) {
console.error('This service does not allow Raw Algo')
return null
}
}
if (algorithmDid) {
// check if did is in trusted list
if (service.attributes.main.privacy)
if (service.attributes.main.privacy.trustedAlgorithms)
if (service.attributes.main.privacy.trustedAlgorithms.length > 0)
if (
!service.attributes.main.privacy.trustedAlgorithms.includes(algorithmDid)
) {
console.error('This service does not allow this Algo')
return null
}
}
const order = await this.ocean.assets.order(
datasetDid,
service.type,
consumerAccount
)
return order
})
}
}

View File

@ -6,60 +6,60 @@ const prefix = 'did:op:'
* Decentralized ID.
*/
export default class DID {
/**
* Parses a DID from a string.
* @param {string} didString DID in string.
* @return {DID}
*/
public static parse(didString: string | DID): DID {
if (didString instanceof DID) {
didString = didString.getDid()
}
let did: DID
const didMatch = didString.match(/^did:op:([a-f0-9]{64})$/i)
/**
* Parses a DID from a string.
* @param {string} didString DID in string.
* @return {DID}
*/
public static parse(didString: string | DID): DID {
if (didString instanceof DID) {
didString = didString.getDid()
}
let did: DID
const didMatch = didString.match(/^did:op:([a-f0-9]{64})$/i)
if (didMatch) {
did = new DID(didMatch[1])
}
if (!did) {
throw new Error(`Parsing DID failed, ${didString}`)
}
return did
if (didMatch) {
did = new DID(didMatch[1])
}
/**
* Returns a new DID.
* @return {DID}
*/
public static generate(): DID {
return new DID(generateId())
if (!did) {
throw new Error(`Parsing DID failed, ${didString}`)
}
/**
* ID.
* @type {string}
*/
private id: string
return did
}
private constructor(id: string) {
this.id = id
}
/**
* Returns a new DID.
* @return {DID}
*/
public static generate(): DID {
return new DID(generateId())
}
/**
* Returns the DID.
* @return {string}
*/
public getDid(): string {
return `${prefix}${this.id}`
}
/**
* ID.
* @type {string}
*/
private id: string
/**
* Returns the ID.
* @return {string}
*/
public getId(): string {
return this.id
}
private constructor(id: string) {
this.id = id
}
/**
* Returns the DID.
* @return {string}
*/
public getDid(): string {
return `${prefix}${this.id}`
}
/**
* Returns the ID.
* @return {string}
*/
public getId(): string {
return this.id
}
}

View File

@ -14,8 +14,8 @@ import { Network } from '../datatokens/Network'
import { Config } from '../models/Config'
import {
Instantiable,
generateIntantiableConfigFromConfig
Instantiable,
generateIntantiableConfigFromConfig
} from '../Instantiable.abstract'
import { Compute } from './Compute'
import { OceanPool } from '../balancer/OceanPool'
@ -24,131 +24,131 @@ import { OceanPool } from '../balancer/OceanPool'
* Main interface for Ocean Protocol.
*/
export class Ocean extends Instantiable {
/**
* Returns the instance of Ocean.
* @param {Config} config Ocean instance configuration.
* @return {Promise<Ocean>}
*/
public static async getInstance(config: Config): Promise<Ocean> {
const instance = new Ocean()
/**
* Returns the instance of Ocean.
* @param {Config} config Ocean instance configuration.
* @return {Promise<Ocean>}
*/
public static async getInstance(config: Config): Promise<Ocean> {
const instance = new Ocean()
const instanceConfig = {
...generateIntantiableConfigFromConfig(config),
ocean: instance
}
instance.setInstanceConfig(instanceConfig)
instance.utils = await OceanUtils.getInstance(instanceConfig)
instance.provider = new Provider(instanceConfig)
instance.metadatastore = new MetadataStore(
instanceConfig.config.metadataStoreUri,
instanceConfig.logger
)
instance.accounts = await Accounts.getInstance(instanceConfig)
// instance.auth = await Auth.getInstance(instanceConfig)
instance.assets = await Assets.getInstance(instanceConfig)
instance.compute = await Compute.getInstance(instanceConfig)
instance.datatokens = new DataTokens(
instanceConfig.config.factoryAddress,
instanceConfig.config.factoryABI,
instanceConfig.config.datatokensABI,
instanceConfig.config.web3Provider
)
instance.pool = new OceanPool(
instanceConfig.config.web3Provider,
instanceConfig.config.poolFactoryABI,
instanceConfig.config.poolABI,
instanceConfig.config.poolFactoryAddress,
instanceConfig.config.oceanTokenAddress
)
instance.versions = await Versions.getInstance(instanceConfig)
instance.network = new Network()
return instance
const instanceConfig = {
...generateIntantiableConfigFromConfig(config),
ocean: instance
}
instance.setInstanceConfig(instanceConfig)
/**
* Network instance
* @type {Network}
*/
public network: Network
instance.utils = await OceanUtils.getInstance(instanceConfig)
/**
* Provider instance.
* @type {Provider}
*/
public provider: Provider
instance.provider = new Provider(instanceConfig)
instance.metadatastore = new MetadataStore(
instanceConfig.config.metadataStoreUri,
instanceConfig.logger
)
/**
* Web3 provider.
* @type {any}
*/
public web3Provider: any
instance.accounts = await Accounts.getInstance(instanceConfig)
// instance.auth = await Auth.getInstance(instanceConfig)
instance.assets = await Assets.getInstance(instanceConfig)
instance.compute = await Compute.getInstance(instanceConfig)
instance.datatokens = new DataTokens(
instanceConfig.config.factoryAddress,
instanceConfig.config.factoryABI,
instanceConfig.config.datatokensABI,
instanceConfig.config.web3Provider
)
instance.pool = new OceanPool(
instanceConfig.config.web3Provider,
instanceConfig.config.poolFactoryABI,
instanceConfig.config.poolABI,
instanceConfig.config.poolFactoryAddress,
instanceConfig.config.oceanTokenAddress
)
instance.versions = await Versions.getInstance(instanceConfig)
instance.network = new Network()
return instance
}
/**
* MetadataStore instance.
* @type {MetadataStore}
*/
public metadatastore: MetadataStore
/**
* Network instance
* @type {Network}
*/
public network: Network
/**
* Ocean account submodule
* @type {Accounts}
*/
public accounts: Accounts
/**
* Provider instance.
* @type {Provider}
*/
public provider: Provider
/**
/**
* Web3 provider.
* @type {any}
*/
public web3Provider: any
/**
* MetadataStore instance.
* @type {MetadataStore}
*/
public metadatastore: MetadataStore
/**
* Ocean account submodule
* @type {Accounts}
*/
public accounts: Accounts
/**
* Ocean auth submodule
* @type {OceanAuth}
public auth: OceanAuth
*/
/**
* Ocean assets submodule
* @type {Assets}
*/
public assets: Assets
/**
* Ocean assets submodule
* @type {Assets}
*/
public assets: Assets
/**
* Ocean compute submodule
* @type {Compute}
*/
public compute: Compute
/**
* Ocean compute submodule
* @type {Compute}
*/
public compute: Compute
/**
* Ocean DataTokens submodule
* @type {DataTokens}
*/
public datatokens: DataTokens
/**
* Ocean DataTokens submodule
* @type {DataTokens}
*/
public datatokens: DataTokens
/**
* Ocean Pools submodule
* @type {OceanPool}
*/
public pool: OceanPool
/**
* Ocean Pools submodule
* @type {OceanPool}
*/
public pool: OceanPool
/**
/**
* Ocean tokens submodule
* @type {OceanTokens}
public tokens: OceanTokens
*/
/**
* Ocean versions submodule
* @type {Versions}
*/
public versions: Versions
/**
* Ocean versions submodule
* @type {Versions}
*/
public versions: Versions
/**
* Ocean utils submodule
* @type {OceanUtils}
*/
public utils: OceanUtils
/**
* Ocean utils submodule
* @type {OceanUtils}
*/
public utils: OceanUtils
private constructor() {
super()
}
private constructor() {
super()
}
}

View File

@ -9,136 +9,136 @@ const localStorageKey = 'SquidTokens'
* Tokens submodule of Ocean Protocol.
*/
export class OceanAuth extends Instantiable {
/**
* Returns the instance of OceanAuth.
* @return {Promise<OceanAuth>}
*/
public static async getInstance(config: InstantiableConfig): Promise<OceanAuth> {
const instance = new OceanAuth()
instance.setInstanceConfig(config)
/**
* Returns the instance of OceanAuth.
* @return {Promise<OceanAuth>}
*/
public static async getInstance(config: InstantiableConfig): Promise<OceanAuth> {
const instance = new OceanAuth()
instance.setInstanceConfig(config)
return instance
return instance
}
/**
* Returns a token for a account.
* @param {Account} account Signer account.
* @return {Promise<string>} Token
*/
public async get(account: Account): Promise<string> {
const time = Math.floor(Date.now() / 1000)
const message = `${this.getMessage()}\n${time}`
try {
const signature = await this.ocean.utils.signature.signText(
message,
account.getId(),
account.getPassword()
)
return `${signature}-${time}`
} catch {
throw new Error('User denied the signature.')
}
}
/**
* Returns the address of signed token.
* @param {string} token Token.
* @return {Promise<string>} Signer address.
*/
public async check(token: string): Promise<string> {
const expiration = this.getExpiration()
const [signature, timestamp] = token.split('-')
const message = `${this.getMessage()}\n${timestamp}`
if (+timestamp * 1000 + expiration < Date.now()) {
return `0x${'0'.repeat(40)}`
}
/**
* Returns a token for a account.
* @param {Account} account Signer account.
* @return {Promise<string>} Token
*/
public async get(account: Account): Promise<string> {
const time = Math.floor(Date.now() / 1000)
const message = `${this.getMessage()}\n${time}`
return this.web3.utils.toChecksumAddress(
await this.ocean.utils.signature.verifyText(message, signature)
)
}
try {
const signature = await this.ocean.utils.signature.signText(
message,
account.getId(),
account.getPassword()
)
/**
* Generates and stores the token for a account.
* @param {Account} account Signer account.
*/
public async store(account: Account) {
const token = await this.get(account)
this.writeToken(account.getId(), token)
}
return `${signature}-${time}`
} catch {
throw new Error('User denied the signature.')
}
/**
* Returns a stored token.
* @param {Account} account Signer account.
*/
public async restore(account: Account): Promise<string> {
let token
try {
token = this.readToken(account.getId())
} catch {
return
}
/**
* Returns the address of signed token.
* @param {string} token Token.
* @return {Promise<string>} Signer address.
*/
public async check(token: string): Promise<string> {
const expiration = this.getExpiration()
const [signature, timestamp] = token.split('-')
const message = `${this.getMessage()}\n${timestamp}`
if (+timestamp * 1000 + expiration < Date.now()) {
return `0x${'0'.repeat(40)}`
}
return this.web3.utils.toChecksumAddress(
await this.ocean.utils.signature.verifyText(message, signature)
)
if (!token) {
return
}
/**
* Generates and stores the token for a account.
* @param {Account} account Signer account.
*/
public async store(account: Account) {
const token = await this.get(account)
this.writeToken(account.getId(), token)
const signer = await this.check(token)
if (signer.toLowerCase() !== account.getId().toLowerCase()) {
return
}
return token
}
/**
* Returns a stored token.
* @param {Account} account Signer account.
*/
public async restore(account: Account): Promise<string> {
let token
try {
token = this.readToken(account.getId())
} catch {
return
}
if (!token) {
return
}
const signer = await this.check(token)
if (signer.toLowerCase() !== account.getId().toLowerCase()) {
return
}
return token
/**
* Returns if the token is stored and is valid.
* @param {Account} account Signer account.
* @return {Promise<boolean>} Is stored and valid.
*/
public async isStored(account: Account): Promise<boolean> {
return !!(await this.restore(account))
}
private writeToken(address: string, token: string) {
const localStorage = this.getLocalStorage()
const storedTokens = localStorage.getItem(localStorageKey)
const tokens = storedTokens ? JSON.parse(storedTokens) : {}
localStorage.setItem(
localStorageKey,
JSON.stringify({
...tokens,
[address]: token
})
)
}
private readToken(address: string) {
const localStorage = this.getLocalStorage()
const storedTokens = localStorage.getItem(localStorageKey)
const tokens = storedTokens ? JSON.parse(storedTokens) : {}
return tokens[address]
}
private getLocalStorage() {
try {
localStorage.getItem('')
} catch {
throw new Error(
'LocalStorage is not supported. This feature is only available on browsers.'
)
}
return localStorage
}
/**
* Returns if the token is stored and is valid.
* @param {Account} account Signer account.
* @return {Promise<boolean>} Is stored and valid.
*/
public async isStored(account: Account): Promise<boolean> {
return !!(await this.restore(account))
}
private getMessage() {
return this.config.authMessage || defaultAuthMessage
}
private writeToken(address: string, token: string) {
const localStorage = this.getLocalStorage()
const storedTokens = localStorage.getItem(localStorageKey)
const tokens = storedTokens ? JSON.parse(storedTokens) : {}
localStorage.setItem(
localStorageKey,
JSON.stringify({
...tokens,
[address]: token
})
)
}
private readToken(address: string) {
const localStorage = this.getLocalStorage()
const storedTokens = localStorage.getItem(localStorageKey)
const tokens = storedTokens ? JSON.parse(storedTokens) : {}
return tokens[address]
}
private getLocalStorage() {
try {
localStorage.getItem('')
} catch {
throw new Error(
'LocalStorage is not supported. This feature is only available on browsers.'
)
}
return localStorage
}
private getMessage() {
return this.config.authMessage || defaultAuthMessage
}
private getExpiration() {
return this.config.authTokenExpiration || defaultExpirationTime
}
private getExpiration() {
return this.config.authTokenExpiration || defaultExpirationTime
}
}

View File

@ -3,77 +3,74 @@ import * as metadata from '../metadata.json'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
export enum OceanPlatformTechStatus {
Loading = 'Loading',
Unknown = 'Unknown',
Stopped = 'Stopped',
Working = 'Working'
Loading = 'Loading',
Unknown = 'Unknown',
Stopped = 'Stopped',
Working = 'Working'
}
export interface OceanPlatformTech {
name: string
version?: string
commit?: string
status: OceanPlatformTechStatus
name: string
version?: string
commit?: string
status: OceanPlatformTechStatus
}
export interface OceanPlatformVersions {
lib: OceanPlatformTech
metadataStore: OceanPlatformTech
provider: OceanPlatformTech
status: {
ok: boolean
}
lib: OceanPlatformTech
metadataStore: OceanPlatformTech
provider: OceanPlatformTech
status: {
ok: boolean
}
}
/**
* Versions submodule of Ocean Protocol.
*/
export class Versions extends Instantiable {
/**
* Returns the instance of Ocean Stack Versions.
* @return {Promise<Versions>}
*/
public static async getInstance(config: InstantiableConfig): Promise<Versions> {
const instance = new Versions()
instance.setInstanceConfig(config)
return instance
/**
* Returns the instance of Ocean Stack Versions.
* @return {Promise<Versions>}
*/
public static async getInstance(config: InstantiableConfig): Promise<Versions> {
const instance = new Versions()
instance.setInstanceConfig(config)
return instance
}
public async get(): Promise<OceanPlatformVersions> {
const versions = {} as OceanPlatformVersions
versions.lib = {
name: 'Lib',
version: metadata.version,
commit: metadata.commit,
status: OceanPlatformTechStatus.Working
}
public async get(): Promise<OceanPlatformVersions> {
const versions = {} as OceanPlatformVersions
versions.lib = {
name: 'Lib',
version: metadata.version,
commit: metadata.commit,
status: OceanPlatformTechStatus.Working
}
// MetadataStore
try {
const {
software: name,
version
} = await this.ocean.metadatastore.getVersionInfo()
versions.metadataStore = {
name,
status: OceanPlatformTechStatus.Working,
version
}
} catch {
versions.metadataStore = {
name: 'MetadataStore',
status: OceanPlatformTechStatus.Stopped
}
}
// Status
const techs: OceanPlatformTech[] = Object.values(versions as any)
versions.status = {
ok: !techs.find(({ status }) => status !== OceanPlatformTechStatus.Working)
}
return versions
// MetadataStore
try {
const { software: name, version } = await this.ocean.metadatastore.getVersionInfo()
versions.metadataStore = {
name,
status: OceanPlatformTechStatus.Working,
version
}
} catch {
versions.metadataStore = {
name: 'MetadataStore',
status: OceanPlatformTechStatus.Stopped
}
}
// Status
const techs: OceanPlatformTech[] = Object.values(versions as any)
versions.status = {
ok: !techs.find(({ status }) => status !== OceanPlatformTechStatus.Working)
}
return versions
}
}

View File

@ -1,14 +1,14 @@
import DID from '../DID'
export interface ComputeJob {
owner: string
did: string
jobId: string
dateCreated: string
dateFinished: string
status: number
statusText: string
algorithmLogUrl: string
resultsUrls: string[]
resultsDid?: DID
owner: string
did: string
jobId: string
dateCreated: string
dateFinished: string
status: number
statusText: string
algorithmLogUrl: string
resultsUrls: string[]
resultsDid?: DID
}

View File

@ -1,14 +1,14 @@
import { Metadata } from '../../ddo/interfaces/Metadata'
export interface Output {
publishAlgorithmLog?: boolean
publishOutput?: boolean
providerAddress?: string
providerUri?: string
metadata?: Metadata
metadataUri?: string
nodeUri?: string
owner?: string
secretStoreUri?: string
whitelist?: string[]
publishAlgorithmLog?: boolean
publishOutput?: boolean
providerAddress?: string
providerUri?: string
metadata?: Metadata
metadataUri?: string
nodeUri?: string
owner?: string
secretStoreUri?: string
whitelist?: string[]
}

View File

@ -3,101 +3,97 @@ import { Logger } from '../../utils'
import { Account } from '../../lib'
export class SignatureUtils {
private web3: Web3
private logger: Logger
private web3: Web3
private logger: Logger
constructor(web3: Web3, logger: Logger) {
this.web3 = web3
this.logger = logger
}
constructor(web3: Web3, logger: Logger) {
this.web3 = web3
this.logger = logger
}
public async signText(
text: string,
publicKey: string,
password?: string
): Promise<string> {
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return await this.web3.eth.personal.sign(text, publicKey, password)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
try {
return await this.web3.eth.sign(text, publicKey)
} catch (e2) {
this.logger.error('Error on sign.')
this.logger.error(e2)
throw new Error('Error executing personal sign')
}
}
public async signText(
text: string,
publicKey: string,
password?: string
): Promise<string> {
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return await this.web3.eth.personal.sign(text, publicKey, password)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
try {
return await this.web3.eth.sign(text, publicKey)
} catch (e2) {
this.logger.error('Error on sign.')
this.logger.error(e2)
throw new Error('Error executing personal sign')
}
}
}
public async signWithHash(
text: string,
publicKey: string,
password?: string
): Promise<string> {
const hash = this.web3.utils.utf8ToHex(text)
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return await this.web3.eth.personal.sign(hash, publicKey, password)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
try {
return await this.web3.eth.sign(hash, publicKey)
} catch (e2) {
this.logger.error('Error on sign.')
this.logger.error(e2)
throw new Error('Error executing personal sign')
}
}
public async signWithHash(
text: string,
publicKey: string,
password?: string
): Promise<string> {
const hash = this.web3.utils.utf8ToHex(text)
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return await this.web3.eth.personal.sign(hash, publicKey, password)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
try {
return await this.web3.eth.sign(hash, publicKey)
} catch (e2) {
this.logger.error('Error on sign.')
this.logger.error(e2)
throw new Error('Error executing personal sign')
}
}
}
public async verifyText(text: string, signature: string): Promise<string> {
return this.web3.eth.personal.ecRecover(text, signature)
}
public async verifyText(text: string, signature: string): Promise<string> {
return this.web3.eth.personal.ecRecover(text, signature)
}
public async getHash(message: string): Promise<string> {
let hex = ''
for (let i = 0; i < message.length; i++) {
hex += '' + message.charCodeAt(i).toString(16)
}
const hexMessage = '0x' + hex
return hexMessage as string
public async getHash(message: string): Promise<string> {
let hex = ''
for (let i = 0; i < message.length; i++) {
hex += '' + message.charCodeAt(i).toString(16)
}
const hexMessage = '0x' + hex
return hexMessage as string
}
public async signForAquarius(message: string, account: Account): Promise<string> {
const hash = await this.getHash(message)
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return this.web3.eth.personal.sign(
hash,
account.getId(),
account.getPassword()
)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
return null
}
public async signForAquarius(message: string, account: Account): Promise<string> {
const hash = await this.getHash(message)
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return this.web3.eth.personal.sign(hash, account.getId(), account.getPassword())
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
return null
}
}
}

View File

@ -6,29 +6,29 @@ import { WebServiceConnector } from './WebServiceConnector'
* Utils internal submodule of Ocean Protocol.
*/
export class OceanUtils extends Instantiable {
/**
* Returns the instance of OceanUtils.
* @return {Promise<OceanUtils>}
*/
public static async getInstance(config: InstantiableConfig): Promise<OceanUtils> {
const instance = new OceanUtils()
instance.setInstanceConfig(config)
/**
* Returns the instance of OceanUtils.
* @return {Promise<OceanUtils>}
*/
public static async getInstance(config: InstantiableConfig): Promise<OceanUtils> {
const instance = new OceanUtils()
instance.setInstanceConfig(config)
instance.signature = new SignatureUtils(config.web3, config.logger)
instance.fetch = new WebServiceConnector(config.logger)
instance.signature = new SignatureUtils(config.web3, config.logger)
instance.fetch = new WebServiceConnector(config.logger)
return instance
}
return instance
}
/**
* Signature utils.
* @type {SignatureUtils}
*/
public signature: SignatureUtils
/**
* Signature utils.
* @type {SignatureUtils}
*/
public signature: SignatureUtils
/**
* Fetch utils.
* @type {WebServiceConnector}
*/
public fetch: WebServiceConnector
/**
* Fetch utils.
* @type {WebServiceConnector}
*/
public fetch: WebServiceConnector
}

View File

@ -9,104 +9,104 @@ const fetch = require('node-fetch')
* Provides a common interface to web services.
*/
export class WebServiceConnector {
public logger: Logger
constructor(logger: Logger) {
this.logger = logger
}
public logger: Logger
constructor(logger: Logger) {
this.logger = logger
}
public post(url: string, payload: BodyInit): Promise<Response> {
return this.fetch(url, {
method: 'POST',
body: payload,
headers: {
'Content-type': 'application/json'
}
})
}
public post(url: string, payload: BodyInit): Promise<Response> {
return this.fetch(url, {
method: 'POST',
body: payload,
headers: {
'Content-type': 'application/json'
}
})
}
public get(url: string): Promise<Response> {
return this.fetch(url, {
method: 'GET',
headers: {
'Content-type': 'application/json'
}
})
}
public get(url: string): Promise<Response> {
return this.fetch(url, {
method: 'GET',
headers: {
'Content-type': 'application/json'
}
})
}
public put(url: string, payload: BodyInit): Promise<Response> {
return this.fetch(url, {
method: 'PUT',
body: payload,
headers: {
'Content-type': 'application/json'
}
})
}
public put(url: string, payload: BodyInit): Promise<Response> {
return this.fetch(url, {
method: 'PUT',
body: payload,
headers: {
'Content-type': 'application/json'
}
})
}
public delete(url: string, payload?: BodyInit): Promise<Response> {
if (payload != null) {
return this.fetch(url, {
method: 'DELETE',
body: payload,
headers: {
'Content-type': 'application/json'
}
})
} else {
return this.fetch(url, {
method: 'DELETE',
headers: {
'Content-type': 'application/json'
}
})
public delete(url: string, payload?: BodyInit): Promise<Response> {
if (payload != null) {
return this.fetch(url, {
method: 'DELETE',
body: payload,
headers: {
'Content-type': 'application/json'
}
})
} else {
return this.fetch(url, {
method: 'DELETE',
headers: {
'Content-type': 'application/json'
}
})
}
}
public async downloadFile(
url: string,
destination?: string,
index?: number
): Promise<string> {
const response = await this.get(url)
if (!response.ok) {
throw new Error('Response error.')
}
let filename: string
try {
filename = response.headers
.get('content-disposition')
.match(/attachment;filename=(.+)/)[1]
} catch {
try {
filename = url.split('/').pop()
} catch {
filename = `file${index}`
}
}
public async downloadFile(
url: string,
destination?: string,
index?: number
): Promise<string> {
const response = await this.get(url)
if (!response.ok) {
throw new Error('Response error.')
}
let filename: string
try {
filename = response.headers
.get('content-disposition')
.match(/attachment;filename=(.+)/)[1]
} catch {
try {
filename = url.split('/').pop()
} catch {
filename = `file${index}`
}
}
if (destination) {
// eslint-disable-next-line no-async-promise-executor
await new Promise(async (resolve, reject) => {
fs.mkdirSync(destination, { recursive: true })
const fileStream = fs.createWriteStream(`${destination}${filename}`)
response.body.pipe(fileStream)
response.body.on('error', reject)
fileStream.on('finish', resolve)
})
if (destination) {
// eslint-disable-next-line no-async-promise-executor
await new Promise(async (resolve, reject) => {
fs.mkdirSync(destination, { recursive: true })
const fileStream = fs.createWriteStream(`${destination}${filename}`)
response.body.pipe(fileStream)
response.body.on('error', reject)
fileStream.on('finish', resolve)
})
return destination
} else {
save(await response.arrayBuffer(), filename)
}
return destination
} else {
save(await response.arrayBuffer(), filename)
}
}
private async fetch(url: string, opts: RequestInit): Promise<Response> {
const result = await fetch(url, opts)
if (!result.ok) {
this.logger.error(`Error requesting [${opts.method}] ${url}`)
this.logger.error(`Response message: \n${await result.text()}`)
throw result
}
return result
private async fetch(url: string, opts: RequestInit): Promise<Response> {
const result = await fetch(url, opts)
if (!result.ok) {
this.logger.error(`Error requesting [${opts.method}] ${url}`)
this.logger.error(`Response message: \n${await result.text()}`)
throw result
}
return result
}
}

View File

@ -5,6 +5,7 @@ import { File } from '../ddo/interfaces/File'
import { ComputeJob } from '../ocean/interfaces/ComputeJob'
import { Output } from '../ocean/interfaces/ComputeOutput'
import { MetadataAlgorithm } from '../ddo/interfaces/MetadataAlgorithm'
import { Versions } from '../ocean/Versions'
const apiPath = '/api/v1/services'
@ -15,279 +16,270 @@ const apiPath = '/api/v1/services'
* data services.
*/
export class Provider extends Instantiable {
public nonce: string
private get url() {
return this.config.providerUri
public nonce: string
private get url() {
return this.config.providerUri
}
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
this.nonce = '0'
}
public async createSignature(account: Account, agreementId: string): Promise<string> {
const signature = await this.ocean.utils.signature.signText(
noZeroX(agreementId),
account.getId()
)
return signature
}
public async createHashSignature(account: Account, message: string): Promise<string> {
const signature = await this.ocean.utils.signature.signWithHash(
message,
account.getId()
)
return signature
}
public async encrypt(did: string, document: any, account: Account): Promise<string> {
await this.getNonce(account.getId())
const signature = await this.ocean.utils.signature.signWithHash(
did + this.nonce,
account.getId(),
account.getPassword()
)
const args = {
documentId: did,
signature: signature,
document: JSON.stringify(document),
publisherAddress: account.getId()
}
try {
const response = await this.ocean.utils.fetch.post(
this.getEncryptEndpoint(),
decodeURI(JSON.stringify(args))
)
return (await response.json()).encryptedDocument
} catch (e) {
this.logger.error(e)
throw new Error('HTTP request failed')
}
}
/** Get nonce from provider
* @param {String} consumerAddress
* @return {Promise<string>} string
*/
public async getNonce(consumerAddress: string): Promise<string> {
let initializeUrl = this.getNonceEndpoint()
initializeUrl += `?userAddress=${consumerAddress}`
try {
const response = await this.ocean.utils.fetch.get(initializeUrl)
this.nonce = String((await response.json()).nonce)
return this.nonce
} catch (e) {
this.logger.error(e)
throw new Error('HTTP request failed')
}
}
public async initialize(
did: string,
serviceIndex: number,
serviceType: string,
consumerAddress: string
): Promise<string> {
let DDO
try {
DDO = await this.ocean.assets.resolve(did)
} catch (e) {
this.logger.error(e)
throw new Error('Failed to resolve DID')
}
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
this.nonce = '0'
let initializeUrl = this.getInitializeEndpoint()
initializeUrl += `?documentId=${did}`
initializeUrl += `&serviceId=${serviceIndex}`
initializeUrl += `&serviceType=${serviceType}`
initializeUrl += `&dataToken=${DDO.dataToken}`
initializeUrl += `&consumerAddress=${consumerAddress}`
try {
const response = await this.ocean.utils.fetch.get(initializeUrl)
return await response.text()
} catch (e) {
this.logger.error(e)
throw new Error('HTTP request failed')
}
}
public async createSignature(account: Account, agreementId: string): Promise<string> {
const signature = await this.ocean.utils.signature.signText(
noZeroX(agreementId),
account.getId()
)
public async download(
did: string,
txId: string,
tokenAddress: string,
serviceType: string,
serviceIndex: string,
destination: string,
account: Account,
files: File[],
index: number = -1
): Promise<any> {
await this.getNonce(account.getId())
const signature = await this.createSignature(account, did + this.nonce)
const filesPromises = files
.filter((_, i) => index === -1 || i === index)
.map(async ({ index: i }) => {
let consumeUrl = this.getDownloadEndpoint()
consumeUrl += `?fileIndex=${i}`
consumeUrl += `&documentId=${did}`
consumeUrl += `&serviceId=${serviceIndex}`
consumeUrl += `&serviceType=${serviceType}`
consumeUrl += `&dataToken=${tokenAddress}`
consumeUrl += `&transferTxId=${txId}`
consumeUrl += `&consumerAddress=${account.getId()}`
consumeUrl += `&signature=${signature}`
return signature
}
public async createHashSignature(account: Account, message: string): Promise<string> {
const signature = await this.ocean.utils.signature.signWithHash(
message,
account.getId()
)
return signature
}
public async encrypt(did: string, document: any, account: Account): Promise<string> {
await this.getNonce(account.getId())
const signature = await this.ocean.utils.signature.signWithHash(
did + this.nonce,
account.getId(),
account.getPassword()
)
const args = {
documentId: did,
signature: signature,
document: JSON.stringify(document),
publisherAddress: account.getId()
}
try {
const response = await this.ocean.utils.fetch.post(
this.getEncryptEndpoint(),
decodeURI(JSON.stringify(args))
)
return (await response.json()).encryptedDocument
await this.ocean.utils.fetch.downloadFile(consumeUrl, destination, i)
} catch (e) {
this.logger.error(e)
throw new Error('HTTP request failed')
this.logger.error('Error consuming assets')
this.logger.error(e)
throw e
}
})
await Promise.all(filesPromises)
return destination
}
public async compute(
method: string,
did: string,
consumerAccount: Account,
algorithmDid?: string,
algorithmMeta?: MetadataAlgorithm,
jobId?: string,
output?: Output,
txId?: string,
serviceIndex?: string,
serviceType?: string,
tokenAddress?: string,
algorithmTransferTxId?: string,
algorithmDataToken?: string
): Promise<ComputeJob | ComputeJob[]> {
const address = consumerAccount.getId()
await this.getNonce(consumerAccount.getId())
let signatureMessage = address
signatureMessage += jobId || ''
signatureMessage += (did && `${noZeroX(did)}`) || ''
signatureMessage += this.nonce
const signature = await this.createHashSignature(consumerAccount, signatureMessage)
// construct Brizo URL
let url = this.getComputeEndpoint()
url += `?signature=${signature}`
url += `&documentId=${noZeroX(did)}`
url += (output && `&output=${JSON.stringify(output)}`) || ''
url += (algorithmDid && `&algorithmDid=${algorithmDid}`) || ''
url +=
(algorithmMeta &&
`&algorithmMeta=${encodeURIComponent(JSON.stringify(algorithmMeta))}`) ||
''
url += (jobId && `&jobId=${jobId}`) || ''
url += `&consumerAddress=${address}`
url += `&transferTxId=${txId}` || ''
url +=
(algorithmTransferTxId && `&algorithmTransferTxId=${algorithmTransferTxId}`) || ''
url += (algorithmDataToken && `&algorithmDataToken=${algorithmDataToken}`) || ''
url += `&serviceId=${serviceIndex}` || ''
url += `&serviceType=${serviceType}` || ''
url += `&dataToken=${tokenAddress}` || ''
url += `&consumerAddress=${consumerAccount.getId()}` || ''
// 'signature': signature,
// 'documentId': did,
// 'serviceId': sa.index,
// 'serviceType': sa.type,
// 'consumerAddress': cons_acc.address,
// 'transferTxId': Web3.toHex(tx_id),
// 'dataToken': data_token,
// 'output': build_stage_output_dict(dict(), dataset_ddo_w_compute_service, cons_acc.address, pub_acc),
// 'algorithmDid': alg_ddo.did,
// 'algorithmMeta': {},
// 'algorithmDataToken': alg_data_token
// switch fetch method
let fetch
switch (method) {
case 'post':
fetch = this.ocean.utils.fetch.post(url, '')
break
case 'put':
fetch = this.ocean.utils.fetch.put(url, '')
break
case 'delete':
fetch = this.ocean.utils.fetch.delete(url)
break
default:
fetch = this.ocean.utils.fetch.get(url)
break
}
/** Get nonce from provider
* @param {String} consumerAddress
* @return {Promise<string>} string
*/
public async getNonce(consumerAddress: string): Promise<string> {
let initializeUrl = this.getNonceEndpoint()
initializeUrl += `?userAddress=${consumerAddress}`
try {
const response = await this.ocean.utils.fetch.get(initializeUrl)
this.nonce = String((await response.json()).nonce)
return this.nonce
} catch (e) {
this.logger.error(e)
throw new Error('HTTP request failed')
}
}
public async initialize(
did: string,
serviceIndex: number,
serviceType: string,
consumerAddress: string
): Promise<string> {
let DDO
try {
DDO = await this.ocean.assets.resolve(did)
} catch (e) {
this.logger.error(e)
throw new Error('Failed to resolve DID')
const result = await fetch
.then((response: any) => {
if (response.ok) {
return response.json()
}
let initializeUrl = this.getInitializeEndpoint()
initializeUrl += `?documentId=${did}`
initializeUrl += `&serviceId=${serviceIndex}`
initializeUrl += `&serviceType=${serviceType}`
initializeUrl += `&dataToken=${DDO.dataToken}`
initializeUrl += `&consumerAddress=${consumerAddress}`
try {
const response = await this.ocean.utils.fetch.get(initializeUrl)
return await response.text()
} catch (e) {
this.logger.error(e)
throw new Error('HTTP request failed')
}
}
this.logger.error('Compute job failed:', response.status, response.statusText)
public async download(
did: string,
txId: string,
tokenAddress: string,
serviceType: string,
serviceIndex: string,
destination: string,
account: Account,
files: File[],
index: number = -1
): Promise<any> {
await this.getNonce(account.getId())
const signature = await this.createSignature(account, did + this.nonce)
const filesPromises = files
.filter((_, i) => index === -1 || i === index)
.map(async ({ index: i }) => {
let consumeUrl = this.getDownloadEndpoint()
consumeUrl += `?fileIndex=${i}`
consumeUrl += `&documentId=${did}`
consumeUrl += `&serviceId=${serviceIndex}`
consumeUrl += `&serviceType=${serviceType}`
consumeUrl += `&dataToken=${tokenAddress}`
consumeUrl += `&transferTxId=${txId}`
consumeUrl += `&consumerAddress=${account.getId()}`
consumeUrl += `&signature=${signature}`
return null
})
.catch((error: Error) => {
this.logger.error('Error with compute job')
this.logger.error(error.message)
throw error
})
try {
await this.ocean.utils.fetch.downloadFile(consumeUrl, destination, i)
} catch (e) {
this.logger.error('Error consuming assets')
this.logger.error(e)
throw e
}
})
await Promise.all(filesPromises)
return destination
}
return result
}
public async compute(
method: string,
did: string,
consumerAccount: Account,
algorithmDid?: string,
algorithmMeta?: MetadataAlgorithm,
jobId?: string,
output?: Output,
txId?: string,
serviceIndex?: string,
serviceType?: string,
tokenAddress?: string,
algorithmTransferTxId?: string,
algorithmDataToken?: string
): Promise<ComputeJob | ComputeJob[]> {
const address = consumerAccount.getId()
await this.getNonce(consumerAccount.getId())
let signatureMessage = address
signatureMessage += jobId || ''
signatureMessage += (did && `${noZeroX(did)}`) || ''
signatureMessage += this.nonce
const signature = await this.createHashSignature(
consumerAccount,
signatureMessage
)
public async getVersionInfo(): Promise<Versions> {
return (await this.ocean.utils.fetch.get(this.url)).json()
}
// construct Brizo URL
let url = this.getComputeEndpoint()
url += `?signature=${signature}`
url += `&documentId=${noZeroX(did)}`
url += (output && `&output=${JSON.stringify(output)}`) || ''
url += (algorithmDid && `&algorithmDid=${algorithmDid}`) || ''
url +=
(algorithmMeta &&
`&algorithmMeta=${encodeURIComponent(JSON.stringify(algorithmMeta))}`) ||
''
url += (jobId && `&jobId=${jobId}`) || ''
url += `&consumerAddress=${address}`
url += `&transferTxId=${txId}` || ''
url +=
(algorithmTransferTxId &&
`&algorithmTransferTxId=${algorithmTransferTxId}`) ||
''
url += (algorithmDataToken && `&algorithmDataToken=${algorithmDataToken}`) || ''
url += `&serviceId=${serviceIndex}` || ''
url += `&serviceType=${serviceType}` || ''
url += `&dataToken=${tokenAddress}` || ''
url += `&consumerAddress=${consumerAccount.getId()}` || ''
// 'signature': signature,
// 'documentId': did,
// 'serviceId': sa.index,
// 'serviceType': sa.type,
// 'consumerAddress': cons_acc.address,
// 'transferTxId': Web3.toHex(tx_id),
// 'dataToken': data_token,
// 'output': build_stage_output_dict(dict(), dataset_ddo_w_compute_service, cons_acc.address, pub_acc),
// 'algorithmDid': alg_ddo.did,
// 'algorithmMeta': {},
// 'algorithmDataToken': alg_data_token
public getURI(): string {
return `${this.url}`
}
// switch fetch method
let fetch
public getInitializeEndpoint(): string {
return `${this.url}${apiPath}/initialize`
}
switch (method) {
case 'post':
fetch = this.ocean.utils.fetch.post(url, '')
break
case 'put':
fetch = this.ocean.utils.fetch.put(url, '')
break
case 'delete':
fetch = this.ocean.utils.fetch.delete(url)
break
default:
fetch = this.ocean.utils.fetch.get(url)
break
}
public getNonceEndpoint(): string {
return `${this.url}${apiPath}/nonce`
}
const result = await fetch
.then((response: any) => {
if (response.ok) {
return response.json()
}
public getConsumeEndpoint(): string {
return `${this.url}${apiPath}/consume`
}
this.logger.error(
'Compute job failed:',
response.status,
response.statusText
)
public getEncryptEndpoint(): string {
return `${this.url}${apiPath}/encrypt`
}
return null
})
.catch((error: Error) => {
this.logger.error('Error with compute job')
this.logger.error(error.message)
throw error
})
public getPublishEndpoint(): string {
return `${this.url}${apiPath}/publish`
}
return result
}
public getComputeEndpoint(): string {
return `${this.url}${apiPath}/compute`
}
public async getVersionInfo() {
return (await this.ocean.utils.fetch.get(this.url)).json()
}
public getURI() {
return `${this.url}`
}
public getInitializeEndpoint() {
return `${this.url}${apiPath}/initialize`
}
public getNonceEndpoint() {
return `${this.url}${apiPath}/nonce`
}
public getConsumeEndpoint() {
return `${this.url}${apiPath}/consume`
}
public getEncryptEndpoint() {
return `${this.url}${apiPath}/encrypt`
}
public getPublishEndpoint() {
return `${this.url}${apiPath}/publish`
}
public getComputeEndpoint() {
return `${this.url}${apiPath}/compute`
}
public getDownloadEndpoint() {
return `${this.url}${apiPath}/download`
}
public getDownloadEndpoint(): string {
return `${this.url}${apiPath}/download`
}
}

View File

@ -1,102 +1,102 @@
import { config } from 'process'
export interface ConfigHelper {
chainId?: number
network: string
url: string
factoryAddress: string
poolFactoryAddress: string
oceanTokenAddress: string
metadataStoreUri: string
providerUri: string
chainId?: number
network: string
url: string
factoryAddress: string
poolFactoryAddress: string
oceanTokenAddress: string
metadataStoreUri: string
providerUri: string
}
const configs = [
{
chaindId: null,
network: 'development',
url: 'http://localhost:8545',
factoryAddress: null,
metadataStoreUri: 'http://127.0.0.1:5000',
providerUri: 'http://127.0.0.1:8030',
poolFactoryAddress: null
},
{
chainId: 4,
network: 'rinkeby',
url: 'https://rinkeby.infura.io/v3',
factoryAddress: '0xcDfEe5D80041224cDCe9AE2334E85B3236385EA3',
oceanTokenAddress: '0x8967BCF84170c91B0d24D4302C2376283b0B3a07',
metadataStoreUri: 'https://aquarius.rinkeby.v3.dev-ocean.com',
providerUri: 'https://provider.rinkeby.v3.dev-ocean.com',
poolFactoryAddress: '0xA4531C624A3D88323a1e178DABe1233AF178701B'
},
{
chainId: 1,
network: 'mainnet',
url: 'https://mainnet.infura.io/v3',
factoryAddress: '0x1234',
oceanTokenAddress: '0x985dd3d42de1e256d09e1c10f112bccb8015ad41',
metadataStoreUri: null,
providerUri: null,
poolFactoryAddress: null
}
{
chaindId: null,
network: 'development',
url: 'http://localhost:8545',
factoryAddress: null,
metadataStoreUri: 'http://127.0.0.1:5000',
providerUri: 'http://127.0.0.1:8030',
poolFactoryAddress: null
},
{
chainId: 4,
network: 'rinkeby',
url: 'https://rinkeby.infura.io/v3',
factoryAddress: '0xcDfEe5D80041224cDCe9AE2334E85B3236385EA3',
oceanTokenAddress: '0x8967BCF84170c91B0d24D4302C2376283b0B3a07',
metadataStoreUri: 'https://aquarius.rinkeby.v3.dev-ocean.com',
providerUri: 'https://provider.rinkeby.v3.dev-ocean.com',
poolFactoryAddress: '0xA4531C624A3D88323a1e178DABe1233AF178701B'
},
{
chainId: 1,
network: 'mainnet',
url: 'https://mainnet.infura.io/v3',
factoryAddress: '0x1234',
oceanTokenAddress: '0x985dd3d42de1e256d09e1c10f112bccb8015ad41',
metadataStoreUri: null,
providerUri: null,
poolFactoryAddress: null
}
]
export class ConfigHelper {
public getConfig(network: string, infuraProjectId?: string): ConfigHelper {
const confighelp = new ConfigHelper()
// fill unknown values
confighelp.chainId = null
confighelp.factoryAddress = null
confighelp.url = null
confighelp.network = network
confighelp.oceanTokenAddress = null
confighelp.metadataStoreUri = null
confighelp.providerUri = null
confighelp.poolFactoryAddress = null
public getConfig(network: string, infuraProjectId?: string): ConfigHelper {
const confighelp = new ConfigHelper()
// fill unknown values
confighelp.chainId = null
confighelp.factoryAddress = null
confighelp.url = null
confighelp.network = network
confighelp.oceanTokenAddress = null
confighelp.metadataStoreUri = null
confighelp.providerUri = null
confighelp.poolFactoryAddress = null
const knownconfig = configs.find((c) => c.network === network)
const knownconfig = configs.find((c) => c.network === network)
if (knownconfig) {
confighelp.chainId = knownconfig.chainId
confighelp.factoryAddress = knownconfig.factoryAddress
confighelp.oceanTokenAddress = knownconfig.oceanTokenAddress
confighelp.url = `${knownconfig.url}/${infuraProjectId}`
confighelp.network = knownconfig.network
confighelp.metadataStoreUri = knownconfig.metadataStoreUri
confighelp.providerUri = knownconfig.providerUri
confighelp.poolFactoryAddress = knownconfig.poolFactoryAddress
}
return confighelp
if (knownconfig) {
confighelp.chainId = knownconfig.chainId
confighelp.factoryAddress = knownconfig.factoryAddress
confighelp.oceanTokenAddress = knownconfig.oceanTokenAddress
confighelp.url = `${knownconfig.url}/${infuraProjectId}`
confighelp.network = knownconfig.network
confighelp.metadataStoreUri = knownconfig.metadataStoreUri
confighelp.providerUri = knownconfig.providerUri
confighelp.poolFactoryAddress = knownconfig.poolFactoryAddress
}
public getConfigById(chainId: number, infuraProjectId?: string): ConfigHelper {
const confighelp = new ConfigHelper()
// fill unknown values
confighelp.chainId = chainId
confighelp.factoryAddress = null
confighelp.url = null
confighelp.network = null
confighelp.oceanTokenAddress = null
confighelp.metadataStoreUri = null
confighelp.providerUri = null
confighelp.poolFactoryAddress = null
return confighelp
}
const knownconfig = configs.find((c) => c.chainId === chainId)
public getConfigById(chainId: number, infuraProjectId?: string): ConfigHelper {
const confighelp = new ConfigHelper()
// fill unknown values
confighelp.chainId = chainId
confighelp.factoryAddress = null
confighelp.url = null
confighelp.network = null
confighelp.oceanTokenAddress = null
confighelp.metadataStoreUri = null
confighelp.providerUri = null
confighelp.poolFactoryAddress = null
if (knownconfig) {
confighelp.chainId = knownconfig.chainId
confighelp.factoryAddress = knownconfig.factoryAddress
confighelp.oceanTokenAddress = knownconfig.oceanTokenAddress
confighelp.url = `${knownconfig.url}/${infuraProjectId}`
confighelp.network = knownconfig.network
confighelp.metadataStoreUri = knownconfig.metadataStoreUri
confighelp.providerUri = knownconfig.providerUri
confighelp.poolFactoryAddress = knownconfig.poolFactoryAddress
}
const knownconfig = configs.find((c) => c.chainId === chainId)
return confighelp
if (knownconfig) {
confighelp.chainId = knownconfig.chainId
confighelp.factoryAddress = knownconfig.factoryAddress
confighelp.oceanTokenAddress = knownconfig.oceanTokenAddress
confighelp.url = `${knownconfig.url}/${infuraProjectId}`
confighelp.network = knownconfig.network
confighelp.metadataStoreUri = knownconfig.metadataStoreUri
confighelp.providerUri = knownconfig.providerUri
confighelp.poolFactoryAddress = knownconfig.poolFactoryAddress
}
return confighelp
}
}

View File

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

View File

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

View File

@ -1,43 +1,43 @@
export enum LogLevel {
None = -1,
Error = 0,
Warn = 1,
Log = 2,
Verbose = 3
None = -1,
Error = 0,
Warn = 1,
Log = 2,
Verbose = 3
}
export class Logger {
constructor(private logLevel: LogLevel = LogLevel.Verbose) {}
constructor(private logLevel: LogLevel = LogLevel.Verbose) {}
public setLevel(logLevel: LogLevel) {
this.logLevel = logLevel
}
public setLevel(logLevel: LogLevel): void {
this.logLevel = logLevel
}
public bypass(...args: any[]) {
this.dispatch('log', -Infinity as any, ...args)
}
public bypass(...args: any[]): void {
this.dispatch('log', -Infinity as any, ...args)
}
public debug(...args: any[]) {
this.dispatch('debug', LogLevel.Verbose, ...args)
}
public debug(...args: any[]): void {
this.dispatch('debug', LogLevel.Verbose, ...args)
}
public log(...args: any[]) {
this.dispatch('log', LogLevel.Log, ...args)
}
public log(...args: any[]): void {
this.dispatch('log', LogLevel.Log, ...args)
}
public warn(...args: any[]) {
this.dispatch('warn', LogLevel.Warn, ...args)
}
public warn(...args: any[]): void {
this.dispatch('warn', LogLevel.Warn, ...args)
}
public error(...args: any[]) {
this.dispatch('error', LogLevel.Error, ...args)
}
public error(...args: any[]): void {
this.dispatch('error', LogLevel.Error, ...args)
}
private dispatch(verb: string, level: LogLevel, ...args: any[]) {
if (this.logLevel >= level) {
console[verb](...args) // eslint-disable-line
}
private dispatch(verb: string, level: LogLevel, ...args: any[]) {
if (this.logLevel >= level) {
console[verb](...args)
}
}
}
export const LoggerInstance = new Logger()

View File

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

View File

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

View File

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

View File

@ -1,106 +1,106 @@
import { Contract } from 'web3-eth-contract'
export class BalancerContractHandler {
public factory: Contract
public pool: Contract
public accounts: string[]
public poolBytecode: string
public factoryBytecode: string
public factoryAddress: string
public poolAddress: string
public web3: any
public factory: Contract
public pool: Contract
public accounts: string[]
public poolBytecode: string
public factoryBytecode: string
public factoryAddress: string
public poolAddress: string
public web3: any
constructor(
factoryABI: Contract,
factoryBytecode: string,
poolABI: Contract,
poolBytecode: string,
web3: any
) {
this.web3 = web3
this.factory = new this.web3.eth.Contract(factoryABI)
this.factoryBytecode = factoryBytecode
this.pool = new this.web3.eth.Contract(poolABI)
this.poolBytecode = poolBytecode
}
constructor(
factoryABI: Contract,
factoryBytecode: string,
poolABI: Contract,
poolBytecode: string,
web3: any
) {
this.web3 = web3
this.factory = new this.web3.eth.Contract(factoryABI)
this.factoryBytecode = factoryBytecode
this.pool = new this.web3.eth.Contract(poolABI)
this.poolBytecode = poolBytecode
}
public async getAccounts() {
this.accounts = await this.web3.eth.getAccounts()
}
public async getAccounts() {
this.accounts = await this.web3.eth.getAccounts()
}
public async deployContracts(minter: string) {
const estGas = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: []
})
.estimateGas(function (err, estGas) {
if (err) console.log('DeployContracts: ' + err)
return estGas
})
// deploy the contract and get it's address
this.factoryAddress = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: []
})
.send({
from: minter,
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
}
public async deployContracts(minter: string) {
const estGas = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: []
})
.estimateGas(function (err, estGas) {
if (err) console.log('DeployContracts: ' + err)
return estGas
})
// deploy the contract and get it's address
this.factoryAddress = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: []
})
.send({
from: minter,
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
}
public async SdeployContracts(minter: string) {
let estGas
estGas = await this.pool
.deploy({
data: this.poolBytecode,
arguments: []
})
.estimateGas(function (err, estGas) {
if (err) console.log('Pool deploy estimate gas: ' + err)
return estGas
})
// deploy the contract and get it's address
this.poolAddress = await this.pool
.deploy({
data: this.poolBytecode,
arguments: []
})
.send({
from: minter,
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
estGas = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: [this.poolAddress]
})
.estimateGas(function (err, estGas) {
if (err) console.log('DeployContracts: ' + err)
return estGas
})
// deploy the contract and get it's address
this.factoryAddress = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: [this.poolAddress]
})
.send({
from: minter,
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
}
public async SdeployContracts(minter: string) {
let estGas
estGas = await this.pool
.deploy({
data: this.poolBytecode,
arguments: []
})
.estimateGas(function (err, estGas) {
if (err) console.log('Pool deploy estimate gas: ' + err)
return estGas
})
// deploy the contract and get it's address
this.poolAddress = await this.pool
.deploy({
data: this.poolBytecode,
arguments: []
})
.send({
from: minter,
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
estGas = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: [this.poolAddress]
})
.estimateGas(function (err, estGas) {
if (err) console.log('DeployContracts: ' + err)
return estGas
})
// deploy the contract and get it's address
this.factoryAddress = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: [this.poolAddress]
})
.send({
from: minter,
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
}
}

View File

@ -1,86 +1,86 @@
import { Contract } from 'web3-eth-contract'
export class TestContractHandler {
public factory: Contract
public template: Contract
public accounts: string[]
public templateBytecode: string
public factoryBytecode: string
public factoryAddress: string
public templateAddress: string
public web3: any
public factory: Contract
public template: Contract
public accounts: string[]
public templateBytecode: string
public factoryBytecode: string
public factoryAddress: string
public templateAddress: string
public web3: any
constructor(
factoryABI: Contract,
datatokensABI: Contract,
templateBytecode: string,
factoryBytecode: string,
web3: any
) {
this.web3 = web3
this.factory = new this.web3.eth.Contract(factoryABI)
this.template = new this.web3.eth.Contract(datatokensABI)
this.templateBytecode = templateBytecode
this.factoryBytecode = factoryBytecode
}
constructor(
factoryABI: Contract,
datatokensABI: Contract,
templateBytecode: string,
factoryBytecode: string,
web3: any
) {
this.web3 = web3
this.factory = new this.web3.eth.Contract(factoryABI)
this.template = new this.web3.eth.Contract(datatokensABI)
this.templateBytecode = templateBytecode
this.factoryBytecode = factoryBytecode
}
public async getAccounts() {
this.accounts = await this.web3.eth.getAccounts()
}
public async getAccounts() {
this.accounts = await this.web3.eth.getAccounts()
}
public async deployContracts(minter: string) {
let estGas
public async deployContracts(minter: string) {
let estGas
const blob = 'https://example.com/dataset-1'
const cap = 1400000000
const blob = 'https://example.com/dataset-1'
const cap = 1400000000
// get est gascost
estGas = await this.template
.deploy({
data: this.templateBytecode,
arguments: ['Template Contract', 'TEMPLATE', minter, cap, blob]
})
.estimateGas(function (err, estGas) {
if (err) console.log('DeployContracts: ' + err)
return estGas
})
// deploy the contract and get it's address
this.templateAddress = await this.template
.deploy({
data: this.templateBytecode,
arguments: ['Template Contract', 'TEMPLATE', minter, cap, blob]
})
.send({
from: minter,
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
// get est gascost
estGas = await this.template
.deploy({
data: this.templateBytecode,
arguments: ['Template Contract', 'TEMPLATE', minter, cap, blob]
})
.estimateGas(function (err, estGas) {
if (err) console.log('DeployContracts: ' + err)
return estGas
})
// deploy the contract and get it's address
this.templateAddress = await this.template
.deploy({
data: this.templateBytecode,
arguments: ['Template Contract', 'TEMPLATE', minter, cap, blob]
})
.send({
from: minter,
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
estGas = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: [this.templateAddress]
})
.estimateGas(function (err, estGas) {
if (err) console.log('DeployContracts: ' + err)
return estGas
})
// deploy the contract and get it's address
this.factoryAddress = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: [this.templateAddress]
})
.send({
from: minter,
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
}
estGas = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: [this.templateAddress]
})
.estimateGas(function (err, estGas) {
if (err) console.log('DeployContracts: ' + err)
return estGas
})
// deploy the contract and get it's address
this.factoryAddress = await this.factory
.deploy({
data: this.factoryBytecode,
arguments: [this.templateAddress]
})
.send({
from: minter,
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
}
}

View File

@ -10,376 +10,376 @@ const factory = require('@oceanprotocol/contracts/artifacts/development/DTFactor
const datatokensTemplate = require('@oceanprotocol/contracts/artifacts/development/DataTokenTemplate.json')
describe('Compute flow', () => {
let owner
let bob
let ddo
let alice
let asset
let datasetNoRawAlgo
let datasetWithTrustedAlgo
let algorithmAsset
let contracts
let datatoken
let tokenAddress
let price
let ocean
let computeService
let data
let blob
let jobId
let owner
let bob
let ddo
let alice
let asset
let datasetNoRawAlgo
let datasetWithTrustedAlgo
let algorithmAsset
let contracts
let datatoken
let tokenAddress
let price
let ocean
let computeService
let data
let blob
let jobId
let cluster
let servers
let containers
let provider
let cluster
let servers
let containers
let provider
const dateCreated = new Date(Date.now()).toISOString().split('.')[0] + 'Z' // remove milliseconds
const dateCreated = new Date(Date.now()).toISOString().split('.')[0] + 'Z' // remove milliseconds
const marketplaceAllowance = '20'
const tokenAmount = '100'
const marketplaceAllowance = '20'
const tokenAmount = '100'
const timeout = 86400
const algorithmMeta = {
language: 'js',
format: 'docker-image',
version: '0.1',
url:
'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js',
container: {
entrypoint: 'node $ALGO',
image: 'node',
tag: '10'
}
const timeout = 86400
const algorithmMeta = {
language: 'js',
format: 'docker-image',
version: '0.1',
url:
'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js',
container: {
entrypoint: 'node $ALGO',
image: 'node',
tag: '10'
}
}
describe('#MarketplaceComputeFlow-Test', () => {
it('Initialize Ocean contracts v3', async () => {
contracts = new TestContractHandler(
factory.abi,
datatokensTemplate.abi,
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
describe('#MarketplaceComputeFlow-Test', () => {
it('Initialize Ocean contracts v3', async () => {
contracts = new TestContractHandler(
factory.abi,
datatokensTemplate.abi,
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
ocean = await Ocean.getInstance(config)
owner = (await ocean.accounts.list())[0]
alice = (await ocean.accounts.list())[1]
bob = (await ocean.accounts.list())[2]
data = { t: 1, url: ocean.config.metadataStoreUri }
blob = JSON.stringify(data)
await contracts.deployContracts(owner.getId())
})
it('Alice deploys datatoken contract', async () => {
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
tokenAddress = await datatoken.create(blob, alice.getId())
assert(tokenAddress != null)
})
it('Generates metadata', async () => {
asset = {
main: {
type: 'dataset',
name: 'UK Weather information 2011',
dateCreated: dateCreated,
author: 'Met Office',
license: 'CC-BY',
files: [
{
url:
'https://raw.githubusercontent.com/tbertinmahieux/MSongsDB/master/Tasks_Demos/CoverSongs/shs_dataset_test.txt',
checksum: 'efb2c764274b745f5fc37f97c6b0e764',
contentLength: '4535431',
contentType: 'text/csv',
encoding: 'UTF-8',
compression: 'zip'
}
]
}
}
})
it('Alice publishes dataset with a compute service that allows Raw Algo', async () => {
price = datatoken.toWei('2') // in datatoken
cluster = ocean.compute.createClusterAttributes(
'Kubernetes',
'http://10.0.0.17/xxx'
)
servers = [
ocean.compute.createServerAttributes(
'1',
'xlsize',
'50',
'16',
'0',
'128gb',
'160gb',
timeout
)
]
containers = [
ocean.compute.createContainerAttributes(
'tensorflow/tensorflow',
'latest',
'sha256:cb57ecfa6ebbefd8ffc7f75c0f00e57a7fa739578a429b6f72a0df19315deadc'
)
]
provider = ocean.compute.createProviderAttributes(
'Azure',
'Compute service with 16gb ram for each node.',
cluster,
containers,
servers
)
const origComputePrivacy = {
allowRawAlgorithm: true,
allowNetworkAccess: false,
trustedAlgorithms: []
}
const computeService = ocean.compute.createComputeService(
alice,
price,
dateCreated,
provider,
origComputePrivacy as ServiceComputePrivacy
)
ddo = await ocean.assets.create(asset, alice, [computeService], tokenAddress)
assert(ddo.dataToken === tokenAddress)
})
// alex
it('should publish a dataset with a compute service object that does not allow rawAlgo', async () => {
const origComputePrivacy = {
allowRawAlgorithm: false,
allowNetworkAccess: false,
trustedAlgorithms: []
}
const computeService = ocean.compute.createComputeService(
alice,
'1000',
dateCreated,
provider,
origComputePrivacy as ServiceComputePrivacy
)
datasetNoRawAlgo = await ocean.assets.create(
asset,
alice,
[computeService],
tokenAddress
)
assert(datasetNoRawAlgo.dataToken === tokenAddress)
})
it('should publish a dataset with a compute service object that allows only algo with did:op:1234', async () => {
const origComputePrivacy = {
allowRawAlgorithm: false,
allowNetworkAccess: false,
trustedAlgorithms: ['did:op:1234']
}
const computeService = ocean.compute.createComputeService(
alice,
'1000',
dateCreated,
provider,
origComputePrivacy as ServiceComputePrivacy
)
datasetWithTrustedAlgo = await ocean.assets.create(
asset,
alice,
[computeService],
tokenAddress
)
assert(datasetWithTrustedAlgo.dataToken === tokenAddress)
})
it('should publish an algorithm', async () => {
const algoAsset = {
main: {
type: 'algorithm',
name: 'Test Algo',
dateCreated: dateCreated,
author: 'DevOps',
license: 'CC-BY',
files: [
{
url:
'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js',
contentType: 'text/js',
encoding: 'UTF-8'
}
],
algorithm: {
language: 'js',
format: 'docker-image',
version: '0.1',
container: {
entrypoint: 'node $ALGO',
image: 'node',
tag: '10'
}
}
}
}
const service1 = await ocean.assets.createAccessServiceAttributes(
alice,
price,
dateCreated,
0
)
algorithmAsset = await ocean.assets.create(
algoAsset,
alice,
[service1],
tokenAddress
)
assert(algorithmAsset.dataToken === tokenAddress)
})
it('Alice mints 100 DTs and tranfers them to the compute marketplace', async () => {
await datatoken.mint(tokenAddress, alice.getId(), tokenAmount)
})
it('Marketplace posts compute service for sale', async () => {
computeService = await ocean.assets.getServiceByType(ddo.id, 'compute')
assert(computeService.attributes.main.cost === price)
})
it('Bob gets datatokens from Alice to be able to try the compute service', async () => {
const dTamount = '20'
await datatoken
.transfer(tokenAddress, bob.getId(), dTamount, alice.getId())
.then(async () => {
const balance = await datatoken.balance(tokenAddress, bob.getId())
assert(balance.toString() === dTamount.toString())
})
})
it('Bob starts compute job with a raw Algo', async () => {
const output = {}
const order = await ocean.compute.order(
bob.getId(),
ddo.id,
computeService.index,
undefined,
algorithmMeta
)
assert(order != null)
const computeOrder = JSON.parse(order)
const tx = await datatoken.transferWei(
computeOrder['dataToken'],
computeOrder['to'],
String(computeOrder['numTokens']),
computeOrder['from']
)
const response = await ocean.compute.start(
ddo.id,
tx.transactionHash,
tokenAddress,
bob,
undefined,
algorithmMeta,
output,
computeService.index,
computeService.type
)
jobId = response.jobId
assert(response.status >= 10)
})
it('Bob should get status of a compute job', async () => {
const response = await ocean.compute.status(bob, ddo.id, jobId)
assert(response[0].jobId === jobId)
})
it('should get status of all compute jobs for an address', async () => {
const response = await ocean.compute.status(bob, undefined, undefined)
assert(response.length > 0)
})
it('Bob should stop compute job', async () => {
await ocean.compute.stop(bob, ddo.id, jobId)
const response = await ocean.compute.status(bob, ddo.id, jobId)
assert(response[0].stopreq === 1)
})
it('should not allow order the compute service with raw algo for dataset that does not allow raw algo', async () => {
const service1 = datasetNoRawAlgo.findServiceByType('compute')
assert(service1 !== null)
const order = await ocean.compute.order(
bob.getId(),
datasetNoRawAlgo.id,
service1.index,
undefined,
algorithmMeta
)
assert(order === null)
})
it('should not allow order the compute service with algoDid != "did:op:1234" for dataset that allows only "did:op:1234" as algo', async () => {
const service1 = datasetWithTrustedAlgo.findServiceByType('compute')
assert(service1 !== null)
const order = await ocean.compute.order(
bob.getId(),
datasetWithTrustedAlgo.id,
service1.index,
'did:op:77777',
undefined
)
assert(order === null)
})
it('should start a compute job with a published algo', async () => {
const output = {}
const serviceAlgo = algorithmAsset.findServiceByType('access')
const orderalgo = await ocean.assets.order(
algorithmAsset.id,
serviceAlgo.type,
bob.getId()
)
const algoOrder = JSON.parse(orderalgo)
const algoTx = await datatoken.transferWei(
algoOrder['dataToken'],
algoOrder['to'],
String(algoOrder['numTokens']),
algoOrder['from']
)
const order = await ocean.compute.order(
bob.getId(),
ddo.id,
computeService.index,
algorithmAsset.id,
undefined
)
assert(order != null)
const computeOrder = JSON.parse(order)
const tx = await datatoken.transferWei(
computeOrder['dataToken'],
computeOrder['to'],
String(computeOrder['numTokens']),
computeOrder['from']
)
const response = await ocean.compute.start(
ddo.id,
tx.transactionHash,
tokenAddress,
bob,
algorithmAsset.id,
undefined,
output,
computeService.index,
computeService.type,
algoTx.transactionHash,
algorithmAsset.dataToken
)
jobId = response.jobId
assert(response.status >= 10)
})
// it('Bob restarts compute job', async () => {})
// it('Bob gets outputs', async () => {})
ocean = await Ocean.getInstance(config)
owner = (await ocean.accounts.list())[0]
alice = (await ocean.accounts.list())[1]
bob = (await ocean.accounts.list())[2]
data = { t: 1, url: ocean.config.metadataStoreUri }
blob = JSON.stringify(data)
await contracts.deployContracts(owner.getId())
})
it('Alice deploys datatoken contract', async () => {
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
tokenAddress = await datatoken.create(blob, alice.getId())
assert(tokenAddress != null)
})
it('Generates metadata', async () => {
asset = {
main: {
type: 'dataset',
name: 'UK Weather information 2011',
dateCreated: dateCreated,
author: 'Met Office',
license: 'CC-BY',
files: [
{
url:
'https://raw.githubusercontent.com/tbertinmahieux/MSongsDB/master/Tasks_Demos/CoverSongs/shs_dataset_test.txt',
checksum: 'efb2c764274b745f5fc37f97c6b0e764',
contentLength: '4535431',
contentType: 'text/csv',
encoding: 'UTF-8',
compression: 'zip'
}
]
}
}
})
it('Alice publishes dataset with a compute service that allows Raw Algo', async () => {
price = datatoken.toWei('2') // in datatoken
cluster = ocean.compute.createClusterAttributes(
'Kubernetes',
'http://10.0.0.17/xxx'
)
servers = [
ocean.compute.createServerAttributes(
'1',
'xlsize',
'50',
'16',
'0',
'128gb',
'160gb',
timeout
)
]
containers = [
ocean.compute.createContainerAttributes(
'tensorflow/tensorflow',
'latest',
'sha256:cb57ecfa6ebbefd8ffc7f75c0f00e57a7fa739578a429b6f72a0df19315deadc'
)
]
provider = ocean.compute.createProviderAttributes(
'Azure',
'Compute service with 16gb ram for each node.',
cluster,
containers,
servers
)
const origComputePrivacy = {
allowRawAlgorithm: true,
allowNetworkAccess: false,
trustedAlgorithms: []
}
const computeService = ocean.compute.createComputeService(
alice,
price,
dateCreated,
provider,
origComputePrivacy as ServiceComputePrivacy
)
ddo = await ocean.assets.create(asset, alice, [computeService], tokenAddress)
assert(ddo.dataToken === tokenAddress)
})
// alex
it('should publish a dataset with a compute service object that does not allow rawAlgo', async () => {
const origComputePrivacy = {
allowRawAlgorithm: false,
allowNetworkAccess: false,
trustedAlgorithms: []
}
const computeService = ocean.compute.createComputeService(
alice,
'1000',
dateCreated,
provider,
origComputePrivacy as ServiceComputePrivacy
)
datasetNoRawAlgo = await ocean.assets.create(
asset,
alice,
[computeService],
tokenAddress
)
assert(datasetNoRawAlgo.dataToken === tokenAddress)
})
it('should publish a dataset with a compute service object that allows only algo with did:op:1234', async () => {
const origComputePrivacy = {
allowRawAlgorithm: false,
allowNetworkAccess: false,
trustedAlgorithms: ['did:op:1234']
}
const computeService = ocean.compute.createComputeService(
alice,
'1000',
dateCreated,
provider,
origComputePrivacy as ServiceComputePrivacy
)
datasetWithTrustedAlgo = await ocean.assets.create(
asset,
alice,
[computeService],
tokenAddress
)
assert(datasetWithTrustedAlgo.dataToken === tokenAddress)
})
it('should publish an algorithm', async () => {
const algoAsset = {
main: {
type: 'algorithm',
name: 'Test Algo',
dateCreated: dateCreated,
author: 'DevOps',
license: 'CC-BY',
files: [
{
url:
'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js',
contentType: 'text/js',
encoding: 'UTF-8'
}
],
algorithm: {
language: 'js',
format: 'docker-image',
version: '0.1',
container: {
entrypoint: 'node $ALGO',
image: 'node',
tag: '10'
}
}
}
}
const service1 = await ocean.assets.createAccessServiceAttributes(
alice,
price,
dateCreated,
0
)
algorithmAsset = await ocean.assets.create(
algoAsset,
alice,
[service1],
tokenAddress
)
assert(algorithmAsset.dataToken === tokenAddress)
})
it('Alice mints 100 DTs and tranfers them to the compute marketplace', async () => {
await datatoken.mint(tokenAddress, alice.getId(), tokenAmount)
})
it('Marketplace posts compute service for sale', async () => {
computeService = await ocean.assets.getServiceByType(ddo.id, 'compute')
assert(computeService.attributes.main.cost === price)
})
it('Bob gets datatokens from Alice to be able to try the compute service', async () => {
const dTamount = '20'
await datatoken
.transfer(tokenAddress, bob.getId(), dTamount, alice.getId())
.then(async () => {
const balance = await datatoken.balance(tokenAddress, bob.getId())
assert(balance.toString() === dTamount.toString())
})
})
it('Bob starts compute job with a raw Algo', async () => {
const output = {}
const order = await ocean.compute.order(
bob.getId(),
ddo.id,
computeService.index,
undefined,
algorithmMeta
)
assert(order != null)
const computeOrder = JSON.parse(order)
const tx = await datatoken.transferWei(
computeOrder['dataToken'],
computeOrder['to'],
String(computeOrder['numTokens']),
computeOrder['from']
)
const response = await ocean.compute.start(
ddo.id,
tx.transactionHash,
tokenAddress,
bob,
undefined,
algorithmMeta,
output,
computeService.index,
computeService.type
)
jobId = response.jobId
assert(response.status >= 10)
})
it('Bob should get status of a compute job', async () => {
const response = await ocean.compute.status(bob, ddo.id, jobId)
assert(response[0].jobId === jobId)
})
it('should get status of all compute jobs for an address', async () => {
const response = await ocean.compute.status(bob, undefined, undefined)
assert(response.length > 0)
})
it('Bob should stop compute job', async () => {
await ocean.compute.stop(bob, ddo.id, jobId)
const response = await ocean.compute.status(bob, ddo.id, jobId)
assert(response[0].stopreq === 1)
})
it('should not allow order the compute service with raw algo for dataset that does not allow raw algo', async () => {
const service1 = datasetNoRawAlgo.findServiceByType('compute')
assert(service1 !== null)
const order = await ocean.compute.order(
bob.getId(),
datasetNoRawAlgo.id,
service1.index,
undefined,
algorithmMeta
)
assert(order === null)
})
it('should not allow order the compute service with algoDid != "did:op:1234" for dataset that allows only "did:op:1234" as algo', async () => {
const service1 = datasetWithTrustedAlgo.findServiceByType('compute')
assert(service1 !== null)
const order = await ocean.compute.order(
bob.getId(),
datasetWithTrustedAlgo.id,
service1.index,
'did:op:77777',
undefined
)
assert(order === null)
})
it('should start a compute job with a published algo', async () => {
const output = {}
const serviceAlgo = algorithmAsset.findServiceByType('access')
const orderalgo = await ocean.assets.order(
algorithmAsset.id,
serviceAlgo.type,
bob.getId()
)
const algoOrder = JSON.parse(orderalgo)
const algoTx = await datatoken.transferWei(
algoOrder['dataToken'],
algoOrder['to'],
String(algoOrder['numTokens']),
algoOrder['from']
)
const order = await ocean.compute.order(
bob.getId(),
ddo.id,
computeService.index,
algorithmAsset.id,
undefined
)
assert(order != null)
const computeOrder = JSON.parse(order)
const tx = await datatoken.transferWei(
computeOrder['dataToken'],
computeOrder['to'],
String(computeOrder['numTokens']),
computeOrder['from']
)
const response = await ocean.compute.start(
ddo.id,
tx.transactionHash,
tokenAddress,
bob,
algorithmAsset.id,
undefined,
output,
computeService.index,
computeService.type,
algoTx.transactionHash,
algorithmAsset.dataToken
)
jobId = response.jobId
assert(response.status >= 10)
})
// it('Bob restarts compute job', async () => {})
// it('Bob gets outputs', async () => {})
})
})

View File

@ -10,180 +10,173 @@ const factory = require('@oceanprotocol/contracts/artifacts/development/DTFactor
const datatokensTemplate = require('@oceanprotocol/contracts/artifacts/development/DataTokenTemplate.json')
describe('Marketplace flow', () => {
let owner
let bob
let ddo
let alice
let asset
let marketplace
let contracts
let datatoken
let tokenAddress
let service1
let price
let ocean
let accessService
let data
let blob
let owner
let bob
let ddo
let alice
let asset
let marketplace
let contracts
let datatoken
let tokenAddress
let service1
let price
let ocean
let accessService
let data
let blob
const marketplaceAllowance = '20'
const tokenAmount = '100'
const marketplaceAllowance = '20'
const tokenAmount = '100'
describe('#MarketplaceDownloadFlow-Test', () => {
it('Initialize Ocean contracts v3', async () => {
contracts = new TestContractHandler(
factory.abi,
datatokensTemplate.abi,
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
describe('#MarketplaceDownloadFlow-Test', () => {
it('Initialize Ocean contracts v3', async () => {
contracts = new TestContractHandler(
factory.abi,
datatokensTemplate.abi,
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
ocean = await Ocean.getInstance(config)
owner = (await ocean.accounts.list())[0]
alice = (await ocean.accounts.list())[1]
bob = (await ocean.accounts.list())[2]
marketplace = (await ocean.accounts.list())[3]
data = { t: 1, url: ocean.config.metadataStoreUri }
blob = JSON.stringify(data)
await contracts.deployContracts(owner.getId())
})
ocean = await Ocean.getInstance(config)
owner = (await ocean.accounts.list())[0]
alice = (await ocean.accounts.list())[1]
bob = (await ocean.accounts.list())[2]
marketplace = (await ocean.accounts.list())[3]
data = { t: 1, url: ocean.config.metadataStoreUri }
blob = JSON.stringify(data)
await contracts.deployContracts(owner.getId())
})
it('Alice publishes a datatoken contract', async () => {
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
tokenAddress = await datatoken.create(blob, alice.getId())
assert(tokenAddress != null)
})
it('Alice publishes a datatoken contract', async () => {
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
tokenAddress = await datatoken.create(blob, alice.getId())
assert(tokenAddress != null)
})
it('Generates metadata', async () => {
asset = {
main: {
type: 'dataset',
name: 'test-dataset',
dateCreated: new Date(Date.now()).toISOString().split('.')[0] + 'Z', // remove milliseconds
author: 'oceanprotocol-team',
license: 'MIT',
files: [
{
url:
'https://raw.githubusercontent.com/tbertinmahieux/MSongsDB/master/Tasks_Demos/CoverSongs/shs_dataset_test.txt',
checksum: 'efb2c764274b745f5fc37f97c6b0e761',
contentLength: '4535431',
contentType: 'text/csv',
encoding: 'UTF-8',
compression: 'zip'
}
]
}
it('Generates metadata', async () => {
asset = {
main: {
type: 'dataset',
name: 'test-dataset',
dateCreated: new Date(Date.now()).toISOString().split('.')[0] + 'Z', // remove milliseconds
author: 'oceanprotocol-team',
license: 'MIT',
files: [
{
url:
'https://raw.githubusercontent.com/tbertinmahieux/MSongsDB/master/Tasks_Demos/CoverSongs/shs_dataset_test.txt',
checksum: 'efb2c764274b745f5fc37f97c6b0e761',
contentLength: '4535431',
contentType: 'text/csv',
encoding: 'UTF-8',
compression: 'zip'
}
})
]
}
}
})
it('Alice publishes a dataset', async () => {
price = datatoken.toWei('10') // in datatoken
const publishedDate = new Date(Date.now()).toISOString().split('.')[0] + 'Z'
const timeout = 0
service1 = await ocean.assets.createAccessServiceAttributes(
alice,
price,
publishedDate,
timeout
)
ddo = await ocean.assets.create(asset, alice, [service1], tokenAddress)
assert(ddo.dataToken === tokenAddress)
})
it('Alice publishes a dataset', async () => {
price = datatoken.toWei('10') // in datatoken
const publishedDate = new Date(Date.now()).toISOString().split('.')[0] + 'Z'
const timeout = 0
service1 = await ocean.assets.createAccessServiceAttributes(
alice,
price,
publishedDate,
timeout
)
ddo = await ocean.assets.create(asset, alice, [service1], tokenAddress)
assert(ddo.dataToken === tokenAddress)
})
it('Alice mints 100 tokens', async () => {
await datatoken.mint(tokenAddress, alice.getId(), tokenAmount)
})
it('Alice mints 100 tokens', async () => {
await datatoken.mint(tokenAddress, alice.getId(), tokenAmount)
})
it('Alice allows marketplace to sell her datatokens', async () => {
await datatoken
.approve(
tokenAddress,
marketplace.getId(),
marketplaceAllowance,
alice.getId()
)
.then(async () => {
const allowance = await datatoken.allowance(
tokenAddress,
alice.getId(),
marketplace.getId()
)
assert(allowance.toString() === marketplaceAllowance.toString())
})
})
it('Marketplace withdraw Alice tokens from allowance', async () => {
const allowance = await datatoken.allowance(
tokenAddress,
alice.getId(),
marketplace.getId()
)
await datatoken
.transferFrom(tokenAddress, alice.getId(), allowance, marketplace.getId())
.then(async () => {
const marketplaceBalance = await datatoken.balance(
tokenAddress,
marketplace.getId()
)
assert(
marketplaceBalance.toString() === marketplaceAllowance.toString()
)
})
})
it('Marketplace should resolve asset using DID', async () => {
await ocean.assets.resolve(ddo.id).then((newDDO) => {
assert(newDDO.id === ddo.id)
})
})
it('Marketplace posts asset for sale', async () => {
accessService = await ocean.assets.getServiceByType(ddo.id, 'access')
price = 20
assert(accessService.attributes.main.cost * price === datatoken.toWei('200'))
})
it('Bob gets datatokens', async () => {
const dTamount = '20'
await datatoken
.transfer(tokenAddress, bob.getId(), dTamount, alice.getId())
.then(async () => {
const balance = await datatoken.balance(tokenAddress, bob.getId())
assert(balance.toString() === dTamount.toString())
})
})
it('Bob consumes asset 1', async () => {
await ocean.assets
.order(ddo.id, accessService.type, bob.getId())
.then(async (res: string) => {
res = JSON.parse(res)
return await datatoken.transferWei(
res['dataToken'],
res['to'],
String(res['numTokens']),
res['from']
)
})
.then(async (tx) => {
await ocean.assets.download(
ddo.id,
tx.transactionHash,
tokenAddress,
bob,
'./node_modules/my-datasets'
)
})
})
it('owner can list there assets', async () => {
const assets = await ocean.assets.ownerAssets(alice.getId())
assert(assets.length > 0)
it('Alice allows marketplace to sell her datatokens', async () => {
await datatoken
.approve(tokenAddress, marketplace.getId(), marketplaceAllowance, alice.getId())
.then(async () => {
const allowance = await datatoken.allowance(
tokenAddress,
alice.getId(),
marketplace.getId()
)
assert(allowance.toString() === marketplaceAllowance.toString())
})
})
it('Marketplace withdraw Alice tokens from allowance', async () => {
const allowance = await datatoken.allowance(
tokenAddress,
alice.getId(),
marketplace.getId()
)
await datatoken
.transferFrom(tokenAddress, alice.getId(), allowance, marketplace.getId())
.then(async () => {
const marketplaceBalance = await datatoken.balance(
tokenAddress,
marketplace.getId()
)
assert(marketplaceBalance.toString() === marketplaceAllowance.toString())
})
})
it('Marketplace should resolve asset using DID', async () => {
await ocean.assets.resolve(ddo.id).then((newDDO) => {
assert(newDDO.id === ddo.id)
})
})
it('Marketplace posts asset for sale', async () => {
accessService = await ocean.assets.getServiceByType(ddo.id, 'access')
price = 20
assert(accessService.attributes.main.cost * price === datatoken.toWei('200'))
})
it('Bob gets datatokens', async () => {
const dTamount = '20'
await datatoken
.transfer(tokenAddress, bob.getId(), dTamount, alice.getId())
.then(async () => {
const balance = await datatoken.balance(tokenAddress, bob.getId())
assert(balance.toString() === dTamount.toString())
})
})
it('Bob consumes asset 1', async () => {
await ocean.assets
.order(ddo.id, accessService.type, bob.getId())
.then(async (res: string) => {
res = JSON.parse(res)
return await datatoken.transferWei(
res['dataToken'],
res['to'],
String(res['numTokens']),
res['from']
)
})
.then(async (tx) => {
await ocean.assets.download(
ddo.id,
tx.transactionHash,
tokenAddress,
bob,
'./node_modules/my-datasets'
)
})
})
it('owner can list there assets', async () => {
const assets = await ocean.assets.ownerAssets(alice.getId())
assert(assets.length > 0)
})
})
})

View File

@ -7,37 +7,37 @@ const factory = require('@oceanprotocol/contracts/artifacts/development/DTFactor
const datatokensTemplate = require('@oceanprotocol/contracts/artifacts/development/DataTokenTemplate.json')
describe('Rinkeby test', () => {
// let account
// let contracts
// let datatoken
// let tokenAddress
// const tokenAmount = 100
// const blob = 'http://localhost:8030/api/v1/provider/services'
// describe('#test', () => {
// it('Initialize Ocean contracts v3', async () => {
// contracts = new TestContractHandler(
// factory.abi,
// datatokensTemplate.abi,
// datatokensTemplate.bytecode,
// factory.bytecode,
// web3
// )
// const privateKey = 'PRIVATE_KEY'
// account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey)
// web3.eth.accounts.wallet.add(account)
// await contracts.deployContracts(account.address)
// })
// it('Publish a dataset', async () => {
// datatoken = new DataTokens(
// contracts.factoryAddress,
// factory.abi,
// datatokensTemplate.abi,
// web3
// )
// tokenAddress = await datatoken.create(blob, account.address)
// })
// it('Mint 100 tokens', async () => {
// await datatoken.mint(tokenAddress, account.address, tokenAmount)
// })
// })
// let account
// let contracts
// let datatoken
// let tokenAddress
// const tokenAmount = 100
// const blob = 'http://localhost:8030/api/v1/provider/services'
// describe('#test', () => {
// it('Initialize Ocean contracts v3', async () => {
// contracts = new TestContractHandler(
// factory.abi,
// datatokensTemplate.abi,
// datatokensTemplate.bytecode,
// factory.bytecode,
// web3
// )
// const privateKey = 'PRIVATE_KEY'
// account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey)
// web3.eth.accounts.wallet.add(account)
// await contracts.deployContracts(account.address)
// })
// it('Publish a dataset', async () => {
// datatoken = new DataTokens(
// contracts.factoryAddress,
// factory.abi,
// datatokensTemplate.abi,
// web3
// )
// tokenAddress = await datatoken.create(blob, account.address)
// })
// it('Mint 100 tokens', async () => {
// await datatoken.mint(tokenAddress, account.address, tokenAmount)
// })
// })
})

View File

@ -9,52 +9,52 @@ const factory = require('@oceanprotocol/contracts/artifacts/development/DTFactor
const datatokensTemplate = require('@oceanprotocol/contracts/artifacts/development/DataTokenTemplate.json')
describe('Simple flow', () => {
let owner
let bob
let alice
let contracts
let datatoken
let tokenAddress
let transactionId
const tokenAmount = '100'
const transferAmount = '1'
const blob = 'http://localhost:8030/api/v1/services/consume'
describe('#test', () => {
it('Initialize Ocean contracts v3', async () => {
contracts = new TestContractHandler(
factory.abi,
datatokensTemplate.abi,
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
await contracts.getAccounts()
owner = contracts.accounts[0]
alice = contracts.accounts[1]
bob = contracts.accounts[2]
await contracts.deployContracts(owner)
})
it('Alice publishes a dataset', async () => {
// Alice creates a Datatoken
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
tokenAddress = await datatoken.create(blob, alice)
})
it('Alice mints 100 tokens', async () => {
await datatoken.mint(tokenAddress, alice, tokenAmount)
})
it('Alice transfers 1 token to Bob', async () => {
const ts = await datatoken.transfer(tokenAddress, bob, transferAmount, alice)
transactionId = ts.transactionHash
})
// it('Bob consumes dataset', async () => {
// const config = new Config()
// const ocean = await Ocean.getInstance(config)
// await ocean.assets.simpleDownload(tokenAddress, blob, transactionId, bob)
// })
let owner
let bob
let alice
let contracts
let datatoken
let tokenAddress
let transactionId
const tokenAmount = '100'
const transferAmount = '1'
const blob = 'http://localhost:8030/api/v1/services/consume'
describe('#test', () => {
it('Initialize Ocean contracts v3', async () => {
contracts = new TestContractHandler(
factory.abi,
datatokensTemplate.abi,
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
await contracts.getAccounts()
owner = contracts.accounts[0]
alice = contracts.accounts[1]
bob = contracts.accounts[2]
await contracts.deployContracts(owner)
})
it('Alice publishes a dataset', async () => {
// Alice creates a Datatoken
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
tokenAddress = await datatoken.create(blob, alice)
})
it('Alice mints 100 tokens', async () => {
await datatoken.mint(tokenAddress, alice, tokenAmount)
})
it('Alice transfers 1 token to Bob', async () => {
const ts = await datatoken.transfer(tokenAddress, bob, transferAmount, alice)
transactionId = ts.transactionHash
})
// it('Bob consumes dataset', async () => {
// const config = new Config()
// const ocean = await Ocean.getInstance(config)
// await ocean.assets.simpleDownload(tokenAddress, blob, transactionId, bob)
// })
})
})

View File

@ -6,111 +6,108 @@ import { Output } from '../../../src/ocean/interfaces/ComputeOutput'
import { MetadataAlgorithm } from '../../../src/ddo/interfaces/MetadataAlgorithm'
export default class ProviderMock extends Provider {
public async compute(
method: string,
did: string,
consumerAccount: Account,
algorithmDid?: string,
algorithmMeta?: MetadataAlgorithm,
jobId?: string,
output?: Output,
txId?: string,
serviceIndex?: string,
serviceType?: string,
tokenAddress?: string
): Promise<ComputeJob | ComputeJob[]> {
const address = consumerAccount.getId()
public async compute(
method: string,
did: string,
consumerAccount: Account,
algorithmDid?: string,
algorithmMeta?: MetadataAlgorithm,
jobId?: string,
output?: Output,
txId?: string,
serviceIndex?: string,
serviceType?: string,
tokenAddress?: string
): Promise<ComputeJob | ComputeJob[]> {
const address = consumerAccount.getId()
let signatureMessage = address
signatureMessage += jobId || ''
signatureMessage += (did && `${noZeroX(did)}`) || ''
const signature = await this.createHashSignature(
consumerAccount,
signatureMessage
)
let signatureMessage = address
signatureMessage += jobId || ''
signatureMessage += (did && `${noZeroX(did)}`) || ''
const signature = await this.createHashSignature(consumerAccount, signatureMessage)
// construct Brizo URL
let url = this.getComputeEndpoint()
url += `?signature=${signature}`
url += `&documentId=${noZeroX(did)}`
url += (output && `&output=${JSON.stringify(output)}`) || ''
url += (algorithmDid && `&algorithmDid=${algorithmDid}`) || ''
url +=
(algorithmMeta &&
`&algorithmMeta=${encodeURIComponent(JSON.stringify(algorithmMeta))}`) ||
''
url += (jobId && `&jobId=${jobId}`) || ''
url += `&consumerAddress=${address}`
url += `&transferTxId=${txId}` || ''
url += `&serviceId=${serviceIndex}` || ''
url += `&serviceType=${serviceType}` || ''
url += `&dataToken=${tokenAddress}` || ''
url += `&consumerAddress=${consumerAccount.getId()}` || ''
// construct Brizo URL
let url = this.getComputeEndpoint()
url += `?signature=${signature}`
url += `&documentId=${noZeroX(did)}`
url += (output && `&output=${JSON.stringify(output)}`) || ''
url += (algorithmDid && `&algorithmDid=${algorithmDid}`) || ''
url +=
(algorithmMeta &&
`&algorithmMeta=${encodeURIComponent(JSON.stringify(algorithmMeta))}`) ||
''
url += (jobId && `&jobId=${jobId}`) || ''
url += `&consumerAddress=${address}`
url += `&transferTxId=${txId}` || ''
url += `&serviceId=${serviceIndex}` || ''
url += `&serviceType=${serviceType}` || ''
url += `&dataToken=${tokenAddress}` || ''
url += `&consumerAddress=${consumerAccount.getId()}` || ''
// switch fetch method
let fetch
// switch fetch method
let fetch
switch (method) {
case 'post': // start
fetch = Promise.resolve({
jobId: '0x1111:001',
status: 1,
statusText: 'Job started'
})
break
case 'put': // stop
fetch = Promise.resolve([
{
status: 7,
statusText: 'Job stopped'
}
])
break
case 'delete':
fetch = Promise.resolve([
{
status: 8,
statusText: 'Job deleted successfully'
}
])
break
default:
// status
fetch = Promise.resolve([
{
owner: '0x1111',
documentId: 'did:op:2222',
jobId: '3333',
dateCreated: '2020-10-01T01:00:00Z',
dateFinished: '2020-10-01T01:00:00Z',
status: 5,
statusText: 'Job finished',
algorithmLogUrl: 'http://example.net/logs/algo.log',
resultsUrls: [
'http://example.net/logs/output/0',
'http://example.net/logs/output/1'
],
resultsDid:
'did:op:87bdaabb33354d2eb014af5091c604fb4b0f67dc6cca4d18a96547bffdc27bcf'
},
{
owner: '0x1111',
documentId: 'did:op:2222',
jobId: '3334',
dateCreated: '2020-10-01T01:00:00Z',
dateFinished: '2020-10-01T01:00:00Z',
status: 5,
statusText: 'Job finished',
algorithmLogUrl: 'http://example.net/logs2/algo.log',
resultsUrls: [
'http://example.net/logs2/output/0',
'http://example.net/logs2/output/1'
],
resultsDid: ''
}
])
break
}
return await fetch
switch (method) {
case 'post': // start
fetch = Promise.resolve({
jobId: '0x1111:001',
status: 1,
statusText: 'Job started'
})
break
case 'put': // stop
fetch = Promise.resolve([
{
status: 7,
statusText: 'Job stopped'
}
])
break
case 'delete':
fetch = Promise.resolve([
{
status: 8,
statusText: 'Job deleted successfully'
}
])
break
default:
// status
fetch = Promise.resolve([
{
owner: '0x1111',
documentId: 'did:op:2222',
jobId: '3333',
dateCreated: '2020-10-01T01:00:00Z',
dateFinished: '2020-10-01T01:00:00Z',
status: 5,
statusText: 'Job finished',
algorithmLogUrl: 'http://example.net/logs/algo.log',
resultsUrls: [
'http://example.net/logs/output/0',
'http://example.net/logs/output/1'
],
resultsDid:
'did:op:87bdaabb33354d2eb014af5091c604fb4b0f67dc6cca4d18a96547bffdc27bcf'
},
{
owner: '0x1111',
documentId: 'did:op:2222',
jobId: '3334',
dateCreated: '2020-10-01T01:00:00Z',
dateFinished: '2020-10-01T01:00:00Z',
status: 5,
statusText: 'Job finished',
algorithmLogUrl: 'http://example.net/logs2/algo.log',
resultsUrls: [
'http://example.net/logs2/output/0',
'http://example.net/logs2/output/1'
],
resultsDid: ''
}
])
break
}
return await fetch
}
}

View File

@ -7,9 +7,9 @@ const Web3 = require('web3')
const web3 = new Web3('http://127.0.0.1:8545')
export default {
metadataStoreUri: 'http://aquarius:5000',
providerUri: 'http://localhost:8030',
nodeUri: `http://localhost:${process.env.ETH_PORT || 8545}`,
verbose: LogLevel.Error,
web3Provider: web3
metadataStoreUri: 'http://aquarius:5000',
providerUri: 'http://localhost:8030',
nodeUri: `http://localhost:${process.env.ETH_PORT || 8545}`,
verbose: LogLevel.Error,
web3Provider: web3
} as Config

View File

@ -9,65 +9,65 @@ const datatokensTemplate = require('@oceanprotocol/contracts/artifacts/developme
const web3 = new Web3('http://127.0.0.1:8545')
describe('DataTokens', () => {
let minter
let spender
let balance
let contracts
let datatoken
let tokenAddress
const tokenAmount = 100
const blob = 'https://example.com/dataset-1'
let minter
let spender
let balance
let contracts
let datatoken
let tokenAddress
const tokenAmount = 100
const blob = 'https://example.com/dataset-1'
describe('#test', () => {
it('should deploy contracts', async () => {
contracts = new TestContractHandler(
factory.abi,
datatokensTemplate.abi,
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
await contracts.getAccounts()
minter = contracts.accounts[0]
spender = contracts.accounts[1]
await contracts.deployContracts(minter)
})
it('should initialize datatokens class', async () => {
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
assert(datatoken !== null)
})
it('should create datatokens smart contract', async () => {
tokenAddress = await datatoken.create(blob, minter)
assert(tokenAddress !== null)
})
it('should mint datatokens', async () => {
await datatoken.mint(tokenAddress, minter, tokenAmount)
balance = await datatoken.balance(tokenAddress, minter)
assert(balance.toString() === tokenAmount.toString())
})
it('should transfer datatokens', async () => {
await datatoken.transfer(tokenAddress, spender, tokenAmount, minter)
balance = await datatoken.balance(tokenAddress, spender)
assert(balance.toString() === tokenAmount.toString())
})
it('should approve datatokens transfer', async () => {
await datatoken.approve(tokenAddress, minter, tokenAmount, spender)
})
it('should transferFrom datatokens', async () => {
await datatoken.transferFrom(tokenAddress, spender, tokenAmount, minter)
balance = await datatoken.balance(tokenAddress, minter)
assert(balance.toString() === tokenAmount.toString())
})
describe('#test', () => {
it('should deploy contracts', async () => {
contracts = new TestContractHandler(
factory.abi,
datatokensTemplate.abi,
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
await contracts.getAccounts()
minter = contracts.accounts[0]
spender = contracts.accounts[1]
await contracts.deployContracts(minter)
})
it('should initialize datatokens class', async () => {
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
assert(datatoken !== null)
})
it('should create datatokens smart contract', async () => {
tokenAddress = await datatoken.create(blob, minter)
assert(tokenAddress !== null)
})
it('should mint datatokens', async () => {
await datatoken.mint(tokenAddress, minter, tokenAmount)
balance = await datatoken.balance(tokenAddress, minter)
assert(balance.toString() === tokenAmount.toString())
})
it('should transfer datatokens', async () => {
await datatoken.transfer(tokenAddress, spender, tokenAmount, minter)
balance = await datatoken.balance(tokenAddress, spender)
assert(balance.toString() === tokenAmount.toString())
})
it('should approve datatokens transfer', async () => {
await datatoken.approve(tokenAddress, minter, tokenAmount, spender)
})
it('should transferFrom datatokens', async () => {
await datatoken.transferFrom(tokenAddress, spender, tokenAmount, minter)
balance = await datatoken.balance(tokenAddress, minter)
assert(balance.toString() === tokenAmount.toString())
})
})
})

View File

@ -2,9 +2,9 @@ import assert from 'assert'
import * as lib from '../../src/lib'
describe('Lib', () => {
describe('interface', () => {
it('should expose Ocean', async () => {
assert(lib.Ocean)
})
describe('interface', () => {
it('should expose Ocean', async () => {
assert(lib.Ocean)
})
})
})

View File

@ -1,15 +1,15 @@
import ContractBase from '../../../src/datatokens/contracts/ContractBase'
export default class ContractBaseMock extends ContractBase {
public async initMock(config: any) {
await this.init(config)
}
public async initMock(config: any) {
await this.init(config)
}
public async callMock(name: string, args: any[], from?: string) {
return this.call(name, args, from)
}
public async callMock(name: string, args: any[], from?: string) {
return this.call(name, args, from)
}
public async sendMock(name: string, from: string, args: any[]) {
return this.send(name, from, args)
}
public async sendMock(name: string, from: string, args: any[]) {
return this.send(name, from, args)
}
}

View File

@ -5,16 +5,16 @@ import DID from '../../../src/ocean/DID'
const ddoStore: Map<string, any> = new Map<string, any>()
export default class MetadataStoreMock extends MetadataStore {
public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
return 'http://test/test'
}
public async getAccessUrl(accessToken: any, payload: any): Promise<string> {
return 'http://test/test'
}
public async storeDDO(ddo: DDO): Promise<DDO> {
ddoStore.set(ddo.id, ddo)
return ddo
}
public async storeDDO(ddo: DDO): Promise<DDO> {
ddoStore.set(ddo.id, ddo)
return ddo
}
public async retrieveDDO(did: DID): Promise<DDO> {
return ddoStore.get(did.getDid())
}
public async retrieveDDO(did: DID): Promise<DDO> {
return ddoStore.get(did.getDid())
}
}

View File

@ -1,25 +1,22 @@
import { WebServiceConnector } from '../../../src/ocean/utils/WebServiceConnector'
import { RequestInit } from 'node-fetch'
// @ts-ignore
export default class WebServiceConnectorMock extends WebServiceConnector {
constructor(private returnData: any) {
super(returnData)
}
export default class WebServiceConnectorMock extends (WebServiceConnector as any) {
constructor(private returnData: any) {
super(returnData)
}
// @ts-ignore
private async fetch(url, opts): Promise<any> {
return new Promise((resolve, reject) => {
resolve({
ok: true,
json: () => {
return this.returnData ? this.returnData : {}
},
text: () => {
return this.returnData
? JSON.stringify(this.returnData.toString())
: ''
}
})
})
}
private async fetch(url: string, opts: RequestInit): Promise<any> {
return new Promise((resolve, reject) => {
resolve({
ok: true,
json: () => {
return this.returnData ? this.returnData : {}
},
text: () => {
return this.returnData ? JSON.stringify(this.returnData.toString()) : ''
}
})
})
}
}

View File

@ -14,232 +14,224 @@ const OceanPoolFactory = require('@oceanprotocol/contracts/artifacts/development
const OceanSPool = require('@oceanprotocol/contracts/artifacts/development/SPool.json')
describe('Balancer flow', () => {
let oceanTokenAddress
let OceanPoolFactoryAddress
let Pool
let oceandatatoken
let alicePoolAddress
let currentDtPrice
let owner
let bob
let alice
let contracts
let datatoken
let tokenAddress
let consoleDebug: false
let greatPool
const tokenAmount = '1000'
const transferAmount = '200'
const blob = 'http://localhost:8030/api/v1/services/consume'
describe('#test', () => {
before(async () => {
// deploy SFactory
const SContracts = new BalancerContractHandler(
OceanPoolFactory.abi,
OceanPoolFactory.bytecode,
OceanSPool.abi,
OceanSPool.bytecode,
web3
)
await SContracts.getAccounts()
owner = SContracts.accounts[0]
let oceanTokenAddress
let OceanPoolFactoryAddress
let Pool
let oceandatatoken
let alicePoolAddress
let currentDtPrice
let owner
let bob
let alice
let contracts
let datatoken
let tokenAddress
let consoleDebug: false
let greatPool
const tokenAmount = '1000'
const transferAmount = '200'
const blob = 'http://localhost:8030/api/v1/services/consume'
describe('#test', () => {
before(async () => {
// deploy SFactory
const SContracts = new BalancerContractHandler(
OceanPoolFactory.abi,
OceanPoolFactory.bytecode,
OceanSPool.abi,
OceanSPool.bytecode,
web3
)
await SContracts.getAccounts()
owner = SContracts.accounts[0]
await SContracts.SdeployContracts(owner)
OceanPoolFactoryAddress = SContracts.factoryAddress
assert(OceanPoolFactoryAddress !== null)
await SContracts.SdeployContracts(owner)
OceanPoolFactoryAddress = SContracts.factoryAddress
assert(OceanPoolFactoryAddress !== null)
// deploy DT Factory
contracts = new TestContractHandler(
factory.abi,
datatokensTemplate.abi,
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
await contracts.getAccounts()
owner = contracts.accounts[0]
alice = contracts.accounts[1]
bob = contracts.accounts[2]
await contracts.deployContracts(owner)
// deploy DT Factory
contracts = new TestContractHandler(
factory.abi,
datatokensTemplate.abi,
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
await contracts.getAccounts()
owner = contracts.accounts[0]
alice = contracts.accounts[1]
bob = contracts.accounts[2]
await contracts.deployContracts(owner)
// initialize DataTokens
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
assert(datatoken !== null)
})
it('should create datatokens smart contract', async () => {
tokenAddress = await datatoken.create(blob, alice)
assert(tokenAddress !== null)
})
it('Create a dummy OceanToken', async () => {
// Alice creates a Datatoken
oceandatatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
oceanTokenAddress = await oceandatatoken.create(blob, alice)
})
it('should initialize OceanPool class', async () => {
Pool = new OceanPool(
web3,
OceanPoolFactory.abi,
OceanSPool.abi,
OceanPoolFactoryAddress,
oceanTokenAddress
)
assert(Pool !== null)
})
it('Alice mints 1000 tokens', async () => {
await datatoken.mint(tokenAddress, alice, tokenAmount)
})
it('Alice mints 1000 Ocean tokens', async () => {
await oceandatatoken.mint(oceanTokenAddress, alice, tokenAmount)
})
it('Alice transfers 200 ocean token to Bob', async () => {
const ts = await datatoken.transfer(
oceanTokenAddress,
bob,
transferAmount,
alice
)
})
it('Alice creates a new OceanPool pool', async () => {
/// new pool with total DT = 45 , dt weight=90% with swap fee 2%
alicePoolAddress = await Pool.createDTPool(alice, tokenAddress, 45, 9, '0.02')
})
it('Get pool information', async () => {
const currentTokens = await Pool.getCurrentTokens(alice, alicePoolAddress)
assert(currentTokens.length === 2)
assert(currentTokens.includes(tokenAddress))
assert(currentTokens.includes(oceanTokenAddress))
})
it('Get pool swap fee', async () => {
const currentSwapFee = await Pool.getSwapFee(alice, alicePoolAddress)
assert(currentSwapFee === '0.02')
})
it('Get dtPrice from the pool ', async () => {
currentDtPrice = await Pool.getDTPrice(alice, alicePoolAddress)
assert(currentDtPrice > 0)
})
it('Get dtToken pool reserve ', async () => {
const currentDtReserve = await Pool.getDTReserve(alice, alicePoolAddress)
assert(currentDtReserve > 0)
})
it('Get Ocean pool reserve ', async () => {
const currentOceanReserve = await Pool.getOceanReserve(
alice,
alicePoolAddress
)
assert(currentOceanReserve > 0)
})
it('Get amount of Ocean needed to buy 1 dtToken', async () => {
const requiredOcean = await Pool.getOceanNeeded(alice, alicePoolAddress, '1')
assert(requiredOcean > 0)
})
it('Bob should search for pools with this DT', async () => {
const pools = await Pool.searchPoolforDT(bob, tokenAddress)
assert(pools.length > 0)
greatPool = pools[0]
})
it('Bob should buy a DT ', async () => {
const maxPrice = parseFloat(currentDtPrice) * 2
await Pool.buyDT(bob, greatPool, '1', '2', String(maxPrice))
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
const bobOceanBalance = await datatoken.balance(oceanTokenAddress, bob)
assert(bobDtBalance > 0)
assert(bobOceanBalance > 0)
})
it('Bob should add DT liquidity to pool ', async () => {
const currentDtReserve = await Pool.getDTReserve(bob, greatPool)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
if (consoleDebug) console.log('BOB DT Balance:' + bobDtBalance)
await Pool.addDTLiquidity(bob, greatPool, bobDtBalance)
const newbobDtBalance = await datatoken.balance(tokenAddress, bob)
const newDtReserve = await Pool.getDTReserve(bob, greatPool)
const sharesBalance = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
if (consoleDebug) console.log('sharesBalance:' + sharesBalance)
assert(parseFloat(newbobDtBalance) < parseFloat(bobDtBalance))
assert(parseFloat(newDtReserve) > parseFloat(currentDtReserve))
assert(parseFloat(sharesBalance) > 0)
})
it('Bob should remove DT liquidity from pool ', async () => {
const currentDtReserve = await Pool.getDTReserve(bob, greatPool)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
const poolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('poolShares:' + poolShares)
await Pool.removeDTLiquidity(bob, greatPool, '0.75', poolShares)
const newDtReserve = await Pool.getDTReserve(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
const newbobDtBalance = await datatoken.balance(tokenAddress, bob)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
const newpoolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newpoolShares:' + newpoolShares)
assert(parseFloat(newDtReserve) < parseFloat(currentDtReserve))
assert(parseFloat(bobDtBalance) < parseFloat(newbobDtBalance))
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
})
it('Bob should add Ocean liquidity to pool ', async () => {
const currentDtReserve = await Pool.getOceanReserve(bob, greatPool)
const bobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
await Pool.addOceanLiquidity(bob, greatPool, '1')
const newbobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
const newDtReserve = await Pool.getOceanReserve(bob, greatPool)
const sharesBalance = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
if (consoleDebug) console.log('sharesBalance:' + sharesBalance)
assert(parseFloat(newbobDtBalance) < parseFloat(bobDtBalance))
assert(parseFloat(newDtReserve) > parseFloat(currentDtReserve))
assert(parseFloat(sharesBalance) > 0)
})
it('Bob should remove Ocean liquidity from pool ', async () => {
const currentDtReserve = await Pool.getOceanReserve(bob, greatPool)
const bobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
const poolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
if (consoleDebug) console.log('poolShares:' + poolShares)
await Pool.removeOceanLiquidity(bob, greatPool, '0.75', poolShares)
const newDtReserve = await Pool.getOceanReserve(bob, greatPool)
const newbobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
const newpoolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
if (consoleDebug) console.log('newpoolShares:' + newpoolShares)
assert(parseFloat(newDtReserve) < parseFloat(currentDtReserve))
assert(parseFloat(bobDtBalance) < parseFloat(newbobDtBalance))
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
})
// initialize DataTokens
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
assert(datatoken !== null)
})
it('should create datatokens smart contract', async () => {
tokenAddress = await datatoken.create(blob, alice)
assert(tokenAddress !== null)
})
it('Create a dummy OceanToken', async () => {
// Alice creates a Datatoken
oceandatatoken = new DataTokens(
contracts.factoryAddress,
factory.abi,
datatokensTemplate.abi,
web3
)
oceanTokenAddress = await oceandatatoken.create(blob, alice)
})
it('should initialize OceanPool class', async () => {
Pool = new OceanPool(
web3,
OceanPoolFactory.abi,
OceanSPool.abi,
OceanPoolFactoryAddress,
oceanTokenAddress
)
assert(Pool !== null)
})
it('Alice mints 1000 tokens', async () => {
await datatoken.mint(tokenAddress, alice, tokenAmount)
})
it('Alice mints 1000 Ocean tokens', async () => {
await oceandatatoken.mint(oceanTokenAddress, alice, tokenAmount)
})
it('Alice transfers 200 ocean token to Bob', async () => {
const ts = await datatoken.transfer(oceanTokenAddress, bob, transferAmount, alice)
})
it('Alice creates a new OceanPool pool', async () => {
/// new pool with total DT = 45 , dt weight=90% with swap fee 2%
alicePoolAddress = await Pool.createDTPool(alice, tokenAddress, 45, 9, '0.02')
})
it('Get pool information', async () => {
const currentTokens = await Pool.getCurrentTokens(alice, alicePoolAddress)
assert(currentTokens.length === 2)
assert(currentTokens.includes(tokenAddress))
assert(currentTokens.includes(oceanTokenAddress))
})
it('Get pool swap fee', async () => {
const currentSwapFee = await Pool.getSwapFee(alice, alicePoolAddress)
assert(currentSwapFee === '0.02')
})
it('Get dtPrice from the pool ', async () => {
currentDtPrice = await Pool.getDTPrice(alice, alicePoolAddress)
assert(currentDtPrice > 0)
})
it('Get dtToken pool reserve ', async () => {
const currentDtReserve = await Pool.getDTReserve(alice, alicePoolAddress)
assert(currentDtReserve > 0)
})
it('Get Ocean pool reserve ', async () => {
const currentOceanReserve = await Pool.getOceanReserve(alice, alicePoolAddress)
assert(currentOceanReserve > 0)
})
it('Get amount of Ocean needed to buy 1 dtToken', async () => {
const requiredOcean = await Pool.getOceanNeeded(alice, alicePoolAddress, '1')
assert(requiredOcean > 0)
})
it('Bob should search for pools with this DT', async () => {
const pools = await Pool.searchPoolforDT(bob, tokenAddress)
assert(pools.length > 0)
greatPool = pools[0]
})
it('Bob should buy a DT ', async () => {
const maxPrice = parseFloat(currentDtPrice) * 2
await Pool.buyDT(bob, greatPool, '1', '2', String(maxPrice))
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
const bobOceanBalance = await datatoken.balance(oceanTokenAddress, bob)
assert(bobDtBalance > 0)
assert(bobOceanBalance > 0)
})
it('Bob should add DT liquidity to pool ', async () => {
const currentDtReserve = await Pool.getDTReserve(bob, greatPool)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
if (consoleDebug) console.log('BOB DT Balance:' + bobDtBalance)
await Pool.addDTLiquidity(bob, greatPool, bobDtBalance)
const newbobDtBalance = await datatoken.balance(tokenAddress, bob)
const newDtReserve = await Pool.getDTReserve(bob, greatPool)
const sharesBalance = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
if (consoleDebug) console.log('sharesBalance:' + sharesBalance)
assert(parseFloat(newbobDtBalance) < parseFloat(bobDtBalance))
assert(parseFloat(newDtReserve) > parseFloat(currentDtReserve))
assert(parseFloat(sharesBalance) > 0)
})
it('Bob should remove DT liquidity from pool ', async () => {
const currentDtReserve = await Pool.getDTReserve(bob, greatPool)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
const poolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('poolShares:' + poolShares)
await Pool.removeDTLiquidity(bob, greatPool, '0.75', poolShares)
const newDtReserve = await Pool.getDTReserve(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
const newbobDtBalance = await datatoken.balance(tokenAddress, bob)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
const newpoolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newpoolShares:' + newpoolShares)
assert(parseFloat(newDtReserve) < parseFloat(currentDtReserve))
assert(parseFloat(bobDtBalance) < parseFloat(newbobDtBalance))
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
})
it('Bob should add Ocean liquidity to pool ', async () => {
const currentDtReserve = await Pool.getOceanReserve(bob, greatPool)
const bobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
await Pool.addOceanLiquidity(bob, greatPool, '1')
const newbobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
const newDtReserve = await Pool.getOceanReserve(bob, greatPool)
const sharesBalance = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
if (consoleDebug) console.log('sharesBalance:' + sharesBalance)
assert(parseFloat(newbobDtBalance) < parseFloat(bobDtBalance))
assert(parseFloat(newDtReserve) > parseFloat(currentDtReserve))
assert(parseFloat(sharesBalance) > 0)
})
it('Bob should remove Ocean liquidity from pool ', async () => {
const currentDtReserve = await Pool.getOceanReserve(bob, greatPool)
const bobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
const poolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
if (consoleDebug) console.log('poolShares:' + poolShares)
await Pool.removeOceanLiquidity(bob, greatPool, '0.75', poolShares)
const newDtReserve = await Pool.getOceanReserve(bob, greatPool)
const newbobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
const newpoolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
if (consoleDebug) console.log('newpoolShares:' + newpoolShares)
assert(parseFloat(newDtReserve) < parseFloat(currentDtReserve))
assert(parseFloat(bobDtBalance) < parseFloat(newbobDtBalance))
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
})
})
})

View File

@ -4,10 +4,10 @@ import { LoggerInstance } from '../../src/utils'
LoggerInstance.setLevel(LogLevel.Error)
export default {
metadataStoreUri: 'http://localhost:5000',
providerUri: 'http://localhost:8030',
nodeUri: `http://localhost:${process.env.ETH_PORT || 8545}`,
parityUri: 'http://localhost:9545',
secretStoreUri: 'http://localhost:12001',
verbose: LogLevel.Error
metadataStoreUri: 'http://localhost:5000',
providerUri: 'http://localhost:8030',
nodeUri: `http://localhost:${process.env.ETH_PORT || 8545}`,
parityUri: 'http://localhost:9545',
secretStoreUri: 'http://localhost:12001',
verbose: LogLevel.Error
} as Config

View File

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

View File

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

View File

@ -9,59 +9,59 @@ let ocean: Ocean
let accounts: Account[]
describe('Account', () => {
before(async () => {
// await TestContractHandler.prepareContracts()
// ocean = await Ocean.getInstance(config)
// accounts = await ocean.accounts.list()
before(async () => {
// await TestContractHandler.prepareContracts()
// ocean = await Ocean.getInstance(config)
// accounts = await ocean.accounts.list()
})
describe('#getOceanBalance()', () => {
it('should get initial ocean balance', async () => {
// const balance = await accounts[8].getOceanBalance()
// assert.equal(0, balance, `Expected 0 got ${balance}`)
})
describe('#getOceanBalance()', () => {
it('should get initial ocean balance', async () => {
// const balance = await accounts[8].getOceanBalance()
// assert.equal(0, balance, `Expected 0 got ${balance}`)
})
it('should get the correct balance', async () => {
// const amount = 100
// const account: Account = accounts[0]
// const initialBalance = await account.getOceanBalance()
// await account.requestTokens(amount)
// const balance = await account.getOceanBalance()
// assert.equal(balance, initialBalance + amount)
})
it('should get the correct balance', async () => {
// const amount = 100
// const account: Account = accounts[0]
// const initialBalance = await account.getOceanBalance()
// await account.requestTokens(amount)
// const balance = await account.getOceanBalance()
// assert.equal(balance, initialBalance + amount)
})
})
describe('#getEthBalance()', () => {
it('should get initial ether balance', async () => {
// const account: Account = accounts[9]
// const balance = await account.getEtherBalance()
// const web3 = Web3Provider.getWeb3()
// assert(
// Number(web3.utils.toWei('100', 'ether')) === balance,
// `ether did not match ${balance}`
// )
})
describe('#getEthBalance()', () => {
it('should get initial ether balance', async () => {
// const account: Account = accounts[9]
// const balance = await account.getEtherBalance()
// const web3 = Web3Provider.getWeb3()
// assert(
// Number(web3.utils.toWei('100', 'ether')) === balance,
// `ether did not match ${balance}`
// )
})
})
describe('#getBalance()', () => {
it('should get initial balance', async () => {
// const account: Account = accounts[9]
// const balance = await account.getBalance()
// const web3 = Web3Provider.getWeb3()
// assert(
// Number(web3.utils.toWei('100', 'ether')) === balance.eth,
// `ether did not match ${balance.eth}`
// )
// assert(balance.ocn === 0, `tokens did not match ${balance.ocn}`)
})
describe('#getBalance()', () => {
it('should get initial balance', async () => {
// const account: Account = accounts[9]
// const balance = await account.getBalance()
// const web3 = Web3Provider.getWeb3()
// assert(
// Number(web3.utils.toWei('100', 'ether')) === balance.eth,
// `ether did not match ${balance.eth}`
// )
// assert(balance.ocn === 0, `tokens did not match ${balance.ocn}`)
})
})
describe('#requestTokens()', () => {
it('should return the amount of tokens granted', async () => {
// const tokens = '500'
// const account: Account = accounts[0]
// const tokensGranted: string = await account.requestTokens(tokens)
// assert.equal(tokensGranted, tokens)
})
describe('#requestTokens()', () => {
it('should return the amount of tokens granted', async () => {
// const tokens = '500'
// const account: Account = accounts[0]
// const tokensGranted: string = await account.requestTokens(tokens)
// assert.equal(tokensGranted, tokens)
})
})
})

View File

@ -10,39 +10,39 @@ use(spies)
let ocean: Ocean
describe('Assets', () => {
before(async () => {
ocean = await Ocean.getInstance(config)
before(async () => {
ocean = await Ocean.getInstance(config)
})
afterEach(() => {
spy.restore()
})
describe('#query()', () => {
it('should search for assets', async () => {
const query: SearchQuery = {
offset: 100,
page: 1,
query: {
text: 'Office'
},
sort: {
created: -1
}
} as SearchQuery
const assets = await ocean.assets.query(query)
assert(assets)
})
})
afterEach(() => {
spy.restore()
})
describe('#query()', () => {
it('should search for assets', async () => {
const query: SearchQuery = {
offset: 100,
page: 1,
query: {
text: 'Office'
},
sort: {
created: -1
}
} as SearchQuery
const assets = await ocean.assets.query(query)
assert(assets)
})
})
describe('#search()', () => {
it('should search for assets', async () => {
const text = 'office'
const assets = await ocean.assets.search(text)
assert(assets)
})
describe('#search()', () => {
it('should search for assets', async () => {
const text = 'office'
const assets = await ocean.assets.search(text)
assert(assets)
})
})
})

View File

@ -2,59 +2,59 @@ import assert from 'assert'
import DID from '../../../src/ocean/DID'
describe('DID', () => {
describe('#generate()', () => {
it('should generate a new did', () => {
const did: DID = DID.generate()
assert(did)
})
describe('#generate()', () => {
it('should generate a new did', () => {
const did: DID = DID.generate()
assert(did)
})
})
describe('#parse()', () => {
it('should parse a valid did', () => {
const id = 'a'.repeat(64)
const did: DID = DID.parse(`did:op:${id}`)
assert(did)
assert(did.getId() === id, did.getId())
})
describe('#parse()', () => {
it('should parse a valid did', () => {
const id = 'a'.repeat(64)
const did: DID = DID.parse(`did:op:${id}`)
assert(did)
assert(did.getId() === id, did.getId())
})
it('should throw if prefix does not match', (done) => {
const id = '1234'
try {
const did: DID = DID.parse(`did:xxx:${id}`)
assert(!did)
} catch {
done()
}
})
it('should throw if id does not match', (done) => {
const id = 'xyz'
try {
const did: DID = DID.parse(`did:op:${id}`)
assert(!did)
} catch {
done()
}
})
it('should throw if prefix does not match', (done) => {
const id = '1234'
try {
const did: DID = DID.parse(`did:xxx:${id}`)
assert(!did)
} catch {
done()
}
})
describe('#getDid()', () => {
it('should return the full did', () => {
const did: DID = DID.generate()
assert(did)
assert(did.getDid().startsWith('did:op:'))
})
it('should throw if id does not match', (done) => {
const id = 'xyz'
try {
const did: DID = DID.parse(`did:op:${id}`)
assert(!did)
} catch {
done()
}
})
})
describe('#getDid()', () => {
it('should return only the id part of the did', () => {
const id = 'a'.repeat(64)
const did: DID = DID.parse(`did:op:${id}`)
assert(did)
describe('#getDid()', () => {
it('should return the full did', () => {
const did: DID = DID.generate()
assert(did)
assert(did.getId() === id)
})
assert(did.getDid().startsWith('did:op:'))
})
})
describe('#getDid()', () => {
it('should return only the id part of the did', () => {
const id = 'a'.repeat(64)
const did: DID = DID.parse(`did:op:${id}`)
assert(did)
assert(did.getId() === id)
})
})
})

View File

@ -10,31 +10,31 @@ use(spies)
let ocean: Ocean
describe('Ocean', () => {
before(async () => {
// await TestContractHandler.prepareContracts()
// ocean = await Ocean.getInstance(config)
})
before(async () => {
// await TestContractHandler.prepareContracts()
// ocean = await Ocean.getInstance(config)
})
beforeEach(async () => {
// spy.on(ocean.utils.signature, 'signText', () => `0x${'a'.repeat(130)}`)
})
afterEach(() => {
// spy.restore()
})
beforeEach(async () => {
// spy.on(ocean.utils.signature, 'signText', () => `0x${'a'.repeat(130)}`)
})
afterEach(() => {
// spy.restore()
})
describe('#getInstance()', () => {
it('should get an instance of Ocean', async () => {
// const oceanInstance: Ocean = await Ocean.getInstance(config)
// assert(oceanInstance)
})
describe('#getInstance()', () => {
it('should get an instance of Ocean', async () => {
// const oceanInstance: Ocean = await Ocean.getInstance(config)
// assert(oceanInstance)
})
})
describe('#getAccounts()', () => {
it('should list accounts', async () => {
// const accs: Account[] = await ocean.accounts.list()
// assert(accs.length === 10)
// assert((await accs[5].getBalance()).ocn === 0)
// assert(typeof accs[0].getId() === 'string')
})
describe('#getAccounts()', () => {
it('should list accounts', async () => {
// const accs: Account[] = await ocean.accounts.list()
// assert(accs.length === 10)
// assert((await accs[5].getBalance()).ocn === 0)
// assert(typeof accs[0].getId() === 'string')
})
})
})

View File

@ -9,32 +9,32 @@ import { Accounts } from '../../../src/ocean/Accounts'
use(spies)
describe('OceanAccounts', () => {
let oceanAccounts: Accounts
let oceanAccounts: Accounts
before(async () => {
oceanAccounts = (await Ocean.getInstance(config)).accounts
})
before(async () => {
oceanAccounts = (await Ocean.getInstance(config)).accounts
})
afterEach(() => {
spy.restore()
})
afterEach(() => {
spy.restore()
})
describe('#list()', () => {
it('should return the list of accounts', async () => {
// const accounts = await oceanAccounts.list()
// accounts.map((account) => assert.instanceOf(account, Account))
})
describe('#list()', () => {
it('should return the list of accounts', async () => {
// const accounts = await oceanAccounts.list()
// accounts.map((account) => assert.instanceOf(account, Account))
})
})
describe('#balance()', () => {
it('should return the balance of an account', async () => {
// const [account] = await oceanAccounts.list()
// spy.on(account, 'getBalance', () => ({ eth: 1, ocn: 5 }))
// const balance = await oceanAccounts.balance(account)
// assert.deepEqual(balance, {
// eth: 1,
// ocn: 5
// })
})
describe('#balance()', () => {
it('should return the balance of an account', async () => {
// const [account] = await oceanAccounts.list()
// spy.on(account, 'getBalance', () => ({ eth: 1, ocn: 5 }))
// const balance = await oceanAccounts.balance(account)
// assert.deepEqual(balance, {
// eth: 1,
// ocn: 5
// })
})
})
})

View File

@ -9,79 +9,79 @@ import { OceanAuth } from '../../../src/ocean/OceanAuth'
use(spies)
describe('OceanAuth', () => {
let oceanAuth: OceanAuth
let account: Account
let oceanAuth: OceanAuth
let account: Account
before(async () => {
// const ocean = await Ocean.getInstance(config)
// oceanAuth = ocean.auth
// account = (await ocean.accounts.list())[0]
before(async () => {
// const ocean = await Ocean.getInstance(config)
// oceanAuth = ocean.auth
// account = (await ocean.accounts.list())[0]
})
afterEach(() => {
spy.restore()
})
describe('#get()', () => {
it('should return the token for a account', async () => {
// const token = await oceanAuth.get(account)
// assert.match(token, /^0x[a-f0-9]{130}-[0-9]{0,14}/i)
})
})
// Not valid using providers without support for `personal_ecRecover`
xdescribe('#check()', () => {
it('should return the account of a signature', async () => {
// const token = await oceanAuth.get(account)
// const address = await oceanAuth.check(token)
// assert.equal(address, account.getId())
})
afterEach(() => {
spy.restore()
it('should return empty address if the token is expired', async () => {
// const token = [
// '0x0cfe59ce5c35461728b4126431096e4e021a842ca1f679532c537be5f895a3607e498',
// 'f2cc22f787f9c7c8a967c346d717ef50ccb9f0af418d87a86dad899e6d61b-1234567890'
// ].join('')
// const address = await oceanAuth.check(token)
// assert.equal(address, `0x${'0'.repeat(40)}`)
})
})
describe('#store()', () => {
it('should sign and store the token', async () => {
// const writeTokenSpy = spy.on(oceanAuth as any, 'writeToken', () => null)
// await oceanAuth.store(account)
// expect(writeTokenSpy).to.has.been.called()
})
})
describe('#restore()', () => {
it('should return a stored token', async () => {
// spy.on(oceanAuth as any, 'readToken', () => 'token')
// spy.on(oceanAuth as any, 'check', () => account.getId())
// const token = await oceanAuth.restore(account)
// assert.equal(token, 'token')
})
describe('#get()', () => {
it('should return the token for a account', async () => {
// const token = await oceanAuth.get(account)
// assert.match(token, /^0x[a-f0-9]{130}-[0-9]{0,14}/i)
})
it('should not return values if there is any error', async () => {
// spy.on(oceanAuth as any, 'readToken', () => 'token')
// spy.on(oceanAuth as any, 'check', () => '0x...')
// const token = await oceanAuth.restore(account)
// assert.isUndefined(token)
})
})
describe('#isStored()', () => {
it('should know if the token is stored', async () => {
// spy.on(oceanAuth as any, 'restore', () => account.getId())
// const isStored = await oceanAuth.isStored(account)
// assert.isTrue(isStored)
})
// Not valid using providers without support for `personal_ecRecover`
xdescribe('#check()', () => {
it('should return the account of a signature', async () => {
// const token = await oceanAuth.get(account)
// const address = await oceanAuth.check(token)
// assert.equal(address, account.getId())
})
it('should return empty address if the token is expired', async () => {
// const token = [
// '0x0cfe59ce5c35461728b4126431096e4e021a842ca1f679532c537be5f895a3607e498',
// 'f2cc22f787f9c7c8a967c346d717ef50ccb9f0af418d87a86dad899e6d61b-1234567890'
// ].join('')
// const address = await oceanAuth.check(token)
// assert.equal(address, `0x${'0'.repeat(40)}`)
})
})
describe('#store()', () => {
it('should sign and store the token', async () => {
// const writeTokenSpy = spy.on(oceanAuth as any, 'writeToken', () => null)
// await oceanAuth.store(account)
// expect(writeTokenSpy).to.has.been.called()
})
})
describe('#restore()', () => {
it('should return a stored token', async () => {
// spy.on(oceanAuth as any, 'readToken', () => 'token')
// spy.on(oceanAuth as any, 'check', () => account.getId())
// const token = await oceanAuth.restore(account)
// assert.equal(token, 'token')
})
it('should not return values if there is any error', async () => {
// spy.on(oceanAuth as any, 'readToken', () => 'token')
// spy.on(oceanAuth as any, 'check', () => '0x...')
// const token = await oceanAuth.restore(account)
// assert.isUndefined(token)
})
})
describe('#isStored()', () => {
it('should know if the token is stored', async () => {
// spy.on(oceanAuth as any, 'restore', () => account.getId())
// const isStored = await oceanAuth.isStored(account)
// assert.isTrue(isStored)
})
it('should know if the token is not stored', async () => {
// spy.on(oceanAuth as any, 'restore', () => undefined)
// const isStored = await oceanAuth.isStored(account)
// assert.isFalse(isStored)
})
it('should know if the token is not stored', async () => {
// spy.on(oceanAuth as any, 'restore', () => undefined)
// const isStored = await oceanAuth.isStored(account)
// assert.isFalse(isStored)
})
})
})

View File

@ -8,58 +8,51 @@ import { Ocean } from '../../../../src/ocean/Ocean'
use(spies)
describe('SignatureUtils', () => {
const publicKey = `0x${'a'.repeat(40)}`
const text = '0123456789abcde'
const signature = `0x${'a'.repeat(130)}`
let web3: Web3
let ocean: Ocean
const publicKey = `0x${'a'.repeat(40)}`
const text = '0123456789abcde'
const signature = `0x${'a'.repeat(130)}`
let web3: Web3
let ocean: Ocean
before(async () => {
ocean = await Ocean.getInstance(config)
web3 = (ocean as any).web3
before(async () => {
ocean = await Ocean.getInstance(config)
web3 = (ocean as any).web3
})
afterEach(() => {
spy.restore()
})
describe('#signText', () => {
let personalSignSpy
beforeEach(() => {
personalSignSpy = spy.on(web3.eth.personal, 'sign', () => signature)
})
afterEach(() => {
spy.restore()
it('should sign a text as expected', async () => {
const signed = await ocean.utils.signature.signText(text, publicKey)
assert.equal(signed, signature)
expect(personalSignSpy).to.have.been.called.with(text, publicKey)
})
describe('#signText', () => {
let personalSignSpy
it('should sign a text as expected using password', async () => {
const signed = await ocean.utils.signature.signText(text, publicKey, 'test')
beforeEach(() => {
personalSignSpy = spy.on(web3.eth.personal, 'sign', () => signature)
})
it('should sign a text as expected', async () => {
const signed = await ocean.utils.signature.signText(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 ocean.utils.signature.signText(text, publicKey, 'test')
assert.equal(signed, signature)
expect(personalSignSpy).to.have.been.called.with(text, publicKey, 'test')
})
assert.equal(signed, signature)
expect(personalSignSpy).to.have.been.called.with(text, publicKey, 'test')
})
})
describe('#verifyText', () => {
it('should recover the privateKey of a signed message', async () => {
const personalRecoverSpy = spy.on(
web3.eth.personal,
'ecRecover',
() => publicKey
)
describe('#verifyText', () => {
it('should recover the privateKey of a signed message', async () => {
const personalRecoverSpy = spy.on(web3.eth.personal, 'ecRecover', () => publicKey)
const verifiedPublicKey = await ocean.utils.signature.verifyText(
text,
signature
)
const verifiedPublicKey = await ocean.utils.signature.verifyText(text, signature)
assert.equal(publicKey, verifiedPublicKey)
expect(personalRecoverSpy).to.have.been.called.with(text, signature)
})
assert.equal(publicKey, verifiedPublicKey)
expect(personalRecoverSpy).to.have.been.called.with(text, signature)
})
})
})

View File

@ -1,63 +1,63 @@
import { assert } from 'chai'
import {
zeroX,
noZeroX,
didPrefixed,
noDidPrefixed
zeroX,
noZeroX,
didPrefixed,
noDidPrefixed
} from '../../../src/utils/ConversionTypeHelpers'
describe('ConversionTypeHelpers', () => {
describe('#zeroXTransformer()', () => {
it("should return the input if it's not hex value", async () => {
const result1 = zeroX('Test 1')
const result2 = noZeroX('Test 2')
assert.equal(result1, 'Test 1')
assert.equal(result2, 'Test 2')
})
it('should return the value with 0x prefix', async () => {
const result1 = zeroX('0x1234')
const result2 = zeroX('1234')
assert.equal(result1, '0x1234')
assert.equal(result2, '0x1234')
})
it('should return the value without 0x prefix', async () => {
const result1 = noZeroX('0x1234')
const result2 = noZeroX('1234')
assert.equal(result1, '1234')
assert.equal(result2, '1234')
})
describe('#zeroXTransformer()', () => {
it("should return the input if it's not hex value", async () => {
const result1 = zeroX('Test 1')
const result2 = noZeroX('Test 2')
assert.equal(result1, 'Test 1')
assert.equal(result2, 'Test 2')
})
describe('#didTransformer()', () => {
const did = 'a'.repeat(64)
it("should return the input if it's not valid", async () => {
const result1 = didPrefixed('Test 1')
const result2 = noDidPrefixed('Test 2')
const result3 = noDidPrefixed('Test 3')
assert.equal(result1, 'Test 1')
assert.equal(result2, 'Test 2')
assert.equal(result3, 'Test 3')
})
it('should return the value with did:op: prefix', async () => {
const result1 = didPrefixed(`0x${did}`)
const result2 = didPrefixed(did)
const result3 = didPrefixed(`did:op:${did}`)
assert.equal(result1, `did:op:${did}`)
assert.equal(result2, `did:op:${did}`)
assert.equal(result3, `did:op:${did}`)
})
it('should return the value without did:op: prefix', async () => {
const result1 = noDidPrefixed(`0x${did}`)
const result2 = noDidPrefixed(did)
const result3 = noDidPrefixed(`did:op:${did}`)
assert.equal(result1, did)
assert.equal(result2, did)
assert.equal(result3, did)
})
it('should return the value with 0x prefix', async () => {
const result1 = zeroX('0x1234')
const result2 = zeroX('1234')
assert.equal(result1, '0x1234')
assert.equal(result2, '0x1234')
})
it('should return the value without 0x prefix', async () => {
const result1 = noZeroX('0x1234')
const result2 = noZeroX('1234')
assert.equal(result1, '1234')
assert.equal(result2, '1234')
})
})
describe('#didTransformer()', () => {
const did = 'a'.repeat(64)
it("should return the input if it's not valid", async () => {
const result1 = didPrefixed('Test 1')
const result2 = noDidPrefixed('Test 2')
const result3 = noDidPrefixed('Test 3')
assert.equal(result1, 'Test 1')
assert.equal(result2, 'Test 2')
assert.equal(result3, 'Test 3')
})
it('should return the value with did:op: prefix', async () => {
const result1 = didPrefixed(`0x${did}`)
const result2 = didPrefixed(did)
const result3 = didPrefixed(`did:op:${did}`)
assert.equal(result1, `did:op:${did}`)
assert.equal(result2, `did:op:${did}`)
assert.equal(result3, `did:op:${did}`)
})
it('should return the value without did:op: prefix', async () => {
const result1 = noDidPrefixed(`0x${did}`)
const result2 = noDidPrefixed(did)
const result3 = noDidPrefixed(`did:op:${did}`)
assert.equal(result1, did)
assert.equal(result2, did)
assert.equal(result3, did)
})
})
})

View File

@ -2,25 +2,25 @@ import { assert } from 'chai'
import { generateId } from '../../../src/utils/GeneratorHelpers'
describe('GeneratorHelpers', () => {
describe('#generateId()', () => {
it('should generate an ID', async () => {
const id = generateId()
assert(id)
})
it('should generate an ID that is 64 chars long', async () => {
const id: string = generateId()
assert.equal(id.length, 64)
})
it('should not contain -', async () => {
const id: string = generateId()
assert.match(id, /^[a-f0-9]+$/i)
})
it('should generate an ID that is 130 chars long', async () => {
const id: string = generateId(130)
assert.equal(id.length, 130)
})
describe('#generateId()', () => {
it('should generate an ID', async () => {
const id = generateId()
assert(id)
})
it('should generate an ID that is 64 chars long', async () => {
const id: string = generateId()
assert.equal(id.length, 64)
})
it('should not contain -', async () => {
const id: string = generateId()
assert.match(id, /^[a-f0-9]+$/i)
})
it('should generate an ID that is 130 chars long', async () => {
const id: string = generateId(130)
assert.equal(id.length, 130)
})
})
})

View File

@ -6,66 +6,66 @@ import { SubscribableObserver } from '../../../src/utils/SubscribableObserver'
use(spies)
describe('SubscribableObserver', () => {
describe('#subscribe()', () => {
it('should be able to add a subcription', async () => {
const observer = new SubscribableObserver()
const subscription = observer.subscribe()
describe('#subscribe()', () => {
it('should be able to add a subcription', async () => {
const observer = new SubscribableObserver()
const subscription = observer.subscribe()
assert.isDefined(subscription.unsubscribe)
assert.typeOf(subscription.unsubscribe, 'function')
})
it('should be able to unsubscribe', async () => {
const observer = new SubscribableObserver()
const subscription = observer.subscribe()
subscription.unsubscribe()
})
assert.isDefined(subscription.unsubscribe)
assert.typeOf(subscription.unsubscribe, 'function')
})
describe('#next()', () => {
it('should be able to emit next value', async () => {
const onNextSpy = spy()
const observer = new SubscribableObserver()
observer.subscribe(onNextSpy)
it('should be able to unsubscribe', async () => {
const observer = new SubscribableObserver()
const subscription = observer.subscribe()
observer.next('test')
expect(onNextSpy).to.has.been.called.with('test')
observer.next('test')
expect(onNextSpy).to.has.been.called.exactly(2)
})
subscription.unsubscribe()
})
})
describe('#complete()', () => {
it('should be able to complete', async () => {
const onCompleteSpy = spy()
const observer = new SubscribableObserver()
observer.subscribe(undefined, onCompleteSpy)
describe('#next()', () => {
it('should be able to emit next value', async () => {
const onNextSpy = spy()
const observer = new SubscribableObserver()
observer.subscribe(onNextSpy)
observer.complete('test')
expect(onCompleteSpy).to.has.been.called.with('test')
observer.next('test')
expect(onNextSpy).to.has.been.called.with('test')
observer.complete('test')
expect(onCompleteSpy).to.has.been.called.exactly(1)
assert.isTrue(observer.completed)
})
observer.next('test')
expect(onNextSpy).to.has.been.called.exactly(2)
})
})
describe('#error()', () => {
it('should be able to emit a error', async () => {
const onErrorSpy = spy()
const observer = new SubscribableObserver()
observer.subscribe(undefined, undefined, onErrorSpy)
describe('#complete()', () => {
it('should be able to complete', async () => {
const onCompleteSpy = spy()
const observer = new SubscribableObserver()
observer.subscribe(undefined, onCompleteSpy)
observer.error('test')
expect(onErrorSpy).to.has.been.called.with('test')
observer.complete('test')
expect(onCompleteSpy).to.has.been.called.with('test')
observer.error('test')
expect(onErrorSpy).to.has.been.called.exactly(1)
observer.complete('test')
expect(onCompleteSpy).to.has.been.called.exactly(1)
assert.isTrue(observer.completed)
})
assert.isTrue(observer.completed)
})
})
describe('#error()', () => {
it('should be able to emit a error', async () => {
const onErrorSpy = spy()
const observer = new SubscribableObserver()
observer.subscribe(undefined, undefined, onErrorSpy)
observer.error('test')
expect(onErrorSpy).to.has.been.called.with('test')
observer.error('test')
expect(onErrorSpy).to.has.been.called.exactly(1)
assert.isTrue(observer.completed)
})
})
})

View File

@ -6,110 +6,110 @@ import { SubscribablePromise } from '../../../src/utils/SubscribablePromise'
use(spies)
describe('SubscribablePromise', () => {
it('should work', async () => {
const subscribable = new SubscribablePromise(() => null)
it('should work', async () => {
const subscribable = new SubscribablePromise(() => null)
assert.isDefined(subscribable)
assert.isDefined(subscribable)
})
describe('#subscribe()', () => {
it('should return a subscription', async () => {
const subscribable = new SubscribablePromise(() => null)
const subscription = subscribable.subscribe(() => null)
assert.isDefined(subscription)
assert.isDefined(subscription.unsubscribe)
assert.typeOf(subscription.unsubscribe, 'function')
})
describe('#subscribe()', () => {
it('should return a subscription', async () => {
const subscribable = new SubscribablePromise(() => null)
const subscription = subscribable.subscribe(() => null)
assert.isDefined(subscription)
assert.isDefined(subscription.unsubscribe)
assert.typeOf(subscription.unsubscribe, 'function')
})
it('should listen the next values', (done) => {
const onNextSpy = spy()
const subscribable = new SubscribablePromise((observer) => {
setTimeout(() => observer.next('test'), 10)
setTimeout(() => observer.next('test'), 20)
})
subscribable.subscribe(onNextSpy)
setTimeout(() => {
expect(onNextSpy).to.has.been.called.with('test')
expect(onNextSpy).to.has.been.called.exactly(2)
done()
}, 100)
})
})
describe('#then()', () => {
it('should resolve', (done) => {
const onCompleteSpy = spy()
const onFinallySpy = spy()
const subscribable = new SubscribablePromise((observer) => {
setTimeout(() => observer.next('test'), 10)
setTimeout(() => observer.complete('test'), 20)
})
subscribable.then(onCompleteSpy).finally(onFinallySpy)
setTimeout(() => {
expect(onCompleteSpy).to.has.been.called.with('test')
expect(onCompleteSpy).to.has.been.called.exactly(1)
expect(onFinallySpy).to.has.been.called.exactly(1)
done()
}, 100)
})
})
describe('#error()', () => {
it('should catch the error', (done) => {
const onErrorSpy = spy()
const onFinallySpy = spy()
const subscribable = new SubscribablePromise((observer) => {
setTimeout(() => observer.next('test'), 10)
setTimeout(() => observer.error('test'), 20)
})
subscribable.catch(onErrorSpy).finally(onFinallySpy)
setTimeout(() => {
expect(onErrorSpy).to.has.been.called.with('test')
expect(onErrorSpy).to.has.been.called.exactly(1)
expect(onFinallySpy).to.has.been.called.exactly(1)
done()
}, 100)
})
})
it('should be able to subscribe and wait for a promise', async () => {
const onNextSpy = spy()
const subscribable = new SubscribablePromise((observer) => {
setTimeout(() => observer.next('test'), 10)
setTimeout(() => observer.next('test'), 20)
setTimeout(() => observer.complete('completed'), 30)
})
const result = await subscribable.next(onNextSpy)
it('should listen the next values', (done) => {
const onNextSpy = spy()
const subscribable = new SubscribablePromise((observer) => {
setTimeout(() => observer.next('test'), 10)
setTimeout(() => observer.next('test'), 20)
})
subscribable.subscribe(onNextSpy)
setTimeout(() => {
expect(onNextSpy).to.has.been.called.with('test')
expect(onNextSpy).to.has.been.called.exactly(2)
done()
}, 100)
})
})
assert.equal(result, 'completed')
describe('#then()', () => {
it('should resolve', (done) => {
const onCompleteSpy = spy()
const onFinallySpy = spy()
const subscribable = new SubscribablePromise((observer) => {
setTimeout(() => observer.next('test'), 10)
setTimeout(() => observer.complete('test'), 20)
})
subscribable.then(onCompleteSpy).finally(onFinallySpy)
setTimeout(() => {
expect(onCompleteSpy).to.has.been.called.with('test')
expect(onCompleteSpy).to.has.been.called.exactly(1)
expect(onFinallySpy).to.has.been.called.exactly(1)
done()
}, 100)
})
})
describe('#error()', () => {
it('should catch the error', (done) => {
const onErrorSpy = spy()
const onFinallySpy = spy()
const subscribable = new SubscribablePromise((observer) => {
setTimeout(() => observer.next('test'), 10)
setTimeout(() => observer.error('test'), 20)
})
subscribable.catch(onErrorSpy).finally(onFinallySpy)
setTimeout(() => {
expect(onErrorSpy).to.has.been.called.with('test')
expect(onErrorSpy).to.has.been.called.exactly(1)
expect(onFinallySpy).to.has.been.called.exactly(1)
done()
}, 100)
})
})
it('should be able to subscribe and wait for a promise', async () => {
const onNextSpy = spy()
const subscribable = new SubscribablePromise((observer) => {
setTimeout(() => observer.next('test'), 10)
setTimeout(() => observer.next('test'), 20)
setTimeout(() => observer.complete('completed'), 30)
})
it('should use the result of a the promise as executor to complete the observer', async () => {
const onNextSpy = spy()
const subscribable = new SubscribablePromise(async (observer) => {
await new Promise((resolve) => setTimeout(resolve, 10))
observer.next('test')
await new Promise((resolve) => setTimeout(resolve, 10))
observer.next('test')
await new Promise((resolve) => setTimeout(resolve, 10))
return 'completed'
})
const result = await subscribable.next(onNextSpy)
const result = await subscribable.next(onNextSpy)
expect(onNextSpy).to.has.been.called.with('test')
expect(onNextSpy).to.has.been.called.exactly(2)
expect(onNextSpy).to.has.been.called.with('test')
expect(onNextSpy).to.has.been.called.exactly(2)
assert.equal(result, 'completed')
})
assert.equal(result, 'completed')
it('should use the result of a the promise as executor to complete the observer', async () => {
const onNextSpy = spy()
const subscribable = new SubscribablePromise(async (observer) => {
await new Promise((resolve) => setTimeout(resolve, 10))
observer.next('test')
await new Promise((resolve) => setTimeout(resolve, 10))
observer.next('test')
await new Promise((resolve) => setTimeout(resolve, 10))
return 'completed'
})
const result = await subscribable.next(onNextSpy)
expect(onNextSpy).to.has.been.called.with('test')
expect(onNextSpy).to.has.been.called.exactly(2)
assert.equal(result, 'completed')
})
})