formatting and typings and lint fixes
This commit is contained in:
parent
ea5f505edf
commit
7b1403c854
|
@ -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
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 90,
|
||||
"trailingComma": "none"
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 90,
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
' '
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
261
src/ddo/DDO.ts
261
src/ddo/DDO.ts
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}[]
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface Authentication {
|
||||
type: string
|
||||
publicKey: string
|
||||
type: string
|
||||
publicKey: string
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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[]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export interface EditableMetadataLinks {
|
||||
name: string
|
||||
url: string
|
||||
type: string
|
||||
name: string
|
||||
url: string
|
||||
type: string
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export interface Proof {
|
||||
type: string
|
||||
created: string
|
||||
creator: string
|
||||
signatureValue: string
|
||||
type: string
|
||||
created: string
|
||||
creator: string
|
||||
signatureValue: string
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface ServicePrices {
|
||||
serviceIndex: number
|
||||
price: string
|
||||
serviceIndex: number
|
||||
price: string
|
||||
}
|
||||
|
|
24
src/lib.ts
24
src/lib.ts
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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[]
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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] }
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 () => {})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
// })
|
||||
// })
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
// })
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()) : ''
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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
|
||||
// })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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')
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue