1
0
mirror of https://github.com/oceanprotocol/ocean.js.git synced 2024-11-26 20:39:05 +01:00

wip: compute module, compute tests, create compute service.

This commit is contained in:
ssallam 2020-07-10 16:17:57 +02:00
parent 76af744726
commit dad7a56c1e
8 changed files with 584 additions and 230 deletions

View File

@ -40,9 +40,9 @@ export class DataTokens {
*/
public async create(metaDataStoreURI: string, account: Account): Promise<string> {
// Create factory contract object
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress, {
from: account
})
const factory = new this.web3.eth.Contract(
this.factoryABI, this.factoryAddress, {from: account}
)
const estGas = await factory.methods
.createToken(metaDataStoreURI)
.estimateGas(function (err, estGas) {

View File

@ -33,7 +33,7 @@ export interface ServiceComputeAttributes extends ServiceCommonAttributes {
main: {
creator: string
datePublished: string
price: string
cost: string
timeout: number
provider?: ServiceComputeProvider
name: string
@ -57,7 +57,7 @@ export interface ServiceComputeProvider {
supportedServers: {
serverId: string
serverType: string
price: string
cost: string
cpu: string
gpu: string
memory: string
@ -74,13 +74,11 @@ export interface ServiceMetadata extends ServiceCommon {
export interface ServiceAccess extends ServiceCommon {
type: 'access'
templateId?: string
attributes: ServiceAccessAttributes
}
export interface ServiceCompute extends ServiceCommon {
type: 'compute'
templateId?: string
attributes: ServiceComputeAttributes
}

View File

@ -33,20 +33,6 @@ export enum OrderProgressStep {
TransferDataToken
}
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
})
/**
* Assets submodule of Ocean Protocol.
*/
@ -458,205 +444,4 @@ export class Assets extends Instantiable {
return serviceEndpoint
}
/**
* Start the execution of a compute job.
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} did Decentralized identifer for the asset
* @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(
consumerAccount: Account,
did: string,
algorithmDid?: string,
algorithmMeta?: MetadataAlgorithm,
output?: Output
): Promise<ComputeJob> {
output = this.checkOutput(consumerAccount, output)
if (did) {
const computeJobsList = await this.ocean.provider.compute(
'post',
did,
consumerAccount,
algorithmDid,
algorithmMeta,
undefined,
output
)
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
}
/**
* Ends a running compute job and starts it again.
* @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 restart(
consumerAccount: Account,
did: string,
jobId: string
): Promise<ComputeJob> {
await this.stop(consumerAccount, did, jobId)
const result = await this.start(consumerAccount, did, jobId)
return result
}
/**
* 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 async createComputeServiceAttributes(
consumerAccount: Account,
price: string,
datePublished: string,
computePrivacy?: ServiceComputePrivacy,
timeout?: number
): Promise<ServiceCompute> {
const name = 'dataAssetComputingService'
if (!timeout) timeout = 3600
// TODO
const service = {
type: 'compute',
index: 3,
serviceEndpoint: this.ocean.provider.getComputeEndpoint(),
attributes: {
main: {
creator: consumerAccount.getId(),
datePublished,
price,
privacy: {},
timeout: timeout,
name
}
}
}
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()
}
}
}

309
src/ocean/Compute.ts Normal file
View File

@ -0,0 +1,309 @@
import { SearchQuery } from '../metadatastore/MetadataStore'
import { DDO } from '../ddo/DDO'
import { Metadata } from '../ddo/interfaces/Metadata'
import { MetadataAlgorithm } from '../ddo/interfaces/MetadataAlgorithm'
import {
Service,
ServiceComputePrivacy,
ServiceCompute
} from '../ddo/interfaces/Service'
import { EditableMetadata } from '../ddo/interfaces/EditableMetadata'
import Account from './Account'
import DID from './DID'
import { SubscribablePromise } from '../utils'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import {Output} from "./interfaces/ComputeOutput";
import {ComputeJob} from "./interfaces/ComputeJob";
// import { WebServiceConnector } from './utils/WebServiceConnector'
// import { Output } from './interfaces/ComputeOutput'
// import { ComputeJob } from './interfaces/ComputeJob'
export enum OrderProgressStep {
TransferDataToken
}
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
})
/**
* 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)
return instance
}
/**
* Start the execution of a compute job.
* @param {Account} consumerAccount The account of the consumer ordering the service.
* @param {string} did Decentralized identifer for the asset
* @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(
consumerAccount: Account,
did: string,
algorithmDid?: string,
algorithmMeta?: MetadataAlgorithm,
output?: Output
): Promise<ComputeJob> {
output = this.checkOutput(consumerAccount, output)
if (did) {
const computeJobsList = await this.ocean.provider.compute(
'post',
did,
consumerAccount,
algorithmDid,
algorithmMeta,
undefined,
output
)
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
}
/**
* 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
}
}
public createContainerAttributes(image: string, tag: string, checksum: string): object {
return {image, tag, checksum}
}
public createClusterAttributes(type: string, url: string): object {
return {type, url}
}
public createProviderAttributes(
type: string, description: string, cluster: object, containers: object[], servers: object[]
): object {
return {
type,
description,
environment: {
cluster: cluster,
supportedServers: containers,
supportedContainers: servers
}
}
}
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
}
}
// '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
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()
}
}
}
// "creator": "0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e",
// "datePublished": "2019-04-09T19:02:11Z",
// "cost": "10",
// "timeout": 86400,
// "provider": {
// "type": "Azure",
// "description": "",
// "environment": {
// "cluster": {
// "type": "Kubernetes",
// "url": "http://10.0.0.17/xxx"
// },
// "supportedContainers": [
// {
// "image": "tensorflow/tensorflow",
// "tag": "latest",
// "checksum": "sha256:cb57ecfa6ebbefd8ffc7f75c0f00e57a7fa739578a429b6f72a0df19315deadc"
// },
// {
// "image": "tensorflow/tensorflow",
// "tag": "latest",
// "checksum": "sha256:cb57ecfa6ebbefd8ffc7f75c0f00e57a7fa739578a429b6f72a0df19315deadc"
// }
// ],
// "supportedServers": [
// {
// "serverId": "1",
// "serverType": "xlsize",
// "cost": "50",
// "cpu": "16",
// "gpu": "0",
// "memory": "128gb",
// "disk": "160gb",
// "maxExecutionTime": 86400
// },
// {
// "serverId": "2",
// "serverType": "medium",
// "cost": "10",
// "cpu": "2",
// "gpu": "0",
// "memory": "8gb",
// "disk": "80gb",
// "maxExecutionTime": 86400
// }
// ]
// }

View File

@ -17,6 +17,7 @@ import {
Instantiable,
generateIntantiableConfigFromConfig
} from '../Instantiable.abstract'
import {Compute} from "./Compute";
/**
* Main interface for Ocean Protocol.
@ -47,7 +48,7 @@ export class Ocean extends Instantiable {
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.compute = await Compute.getInstance(instanceConfig)
instance.datatokens = new DataTokens(
instanceConfig.config.factoryAddress,
instanceConfig.config.factoryABI,
@ -105,9 +106,8 @@ export class Ocean extends Instantiable {
/**
* Ocean compute submodule
* @type {Compute}
*/
public compute: Compute
*/
/**
* Ocean secretStore submodule

View File

@ -174,6 +174,17 @@ export class Provider extends Instantiable {
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

View File

@ -22,9 +22,10 @@ describe('Marketplace flow', () => {
let service1
let price
let ocean
let accessService
let computeService
let data
let blob
const dateCreated = new Date(Date.now()).toISOString().split('.')[0] + 'Z' // remove milliseconds
const marketplaceAllowance = 20
const tokenAmount = 100
@ -60,13 +61,75 @@ describe('Marketplace flow', () => {
assert(tokenAddress != null)
})
// it('Alice publishes dataset with a compute service', async () => {})
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 mints 100 DTs and tranfers them to the compute marketplace', async () => {})
it('Alice publishes dataset with a compute service', async () => {
price = 10 // in datatoken
const timeout = 86400
const cluster = ocean.compute.createClusterAttributes('Kubernetes', 'http://10.0.0.17/xxx')
const servers = [
ocean.compute.createServerAttributes('1', 'xlsize', '50', '16', '0', '128gb', '160gb', timeout)
]
const containers = [
ocean.compute.createContainerAttributes(
'tensorflow/tensorflow',
'latest',
'sha256:cb57ecfa6ebbefd8ffc7f75c0f00e57a7fa739578a429b6f72a0df19315deadc'
)
]
const provider = ocean.compute.createProviderAttributes(
'Azure',
'Compute service with 16gb ram for each node.',
cluster,
containers,
servers
)
const computeService = ocean.compute.createComputeService(
alice, price, dateCreated, provider
)
ddo = await ocean.assets.create(asset, alice, [computeService], tokenAddress)
assert(ddo.dataToken === tokenAddress)
// it('Markeplace post compute service for sale', async () => {})
})
// it('Bob buys datatokens from open market and order a compute service', async () => {})
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 buys datatokens from open market and order a 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', async () => {})

View File

@ -0,0 +1,188 @@
import { TestContractHandler } from '../TestContractHandler'
import { DataTokens } from '../../src/datatokens/Datatokens'
import { Ocean } from '../../src/ocean/Ocean'
import config from './config'
import { assert } from 'console'
const Web3 = require('web3')
const web3 = new Web3('http://127.0.0.1:8545')
const factory = require('@oceanprotocol/contracts/artifacts/development/Factory.json')
const datatokensTemplate = require('@oceanprotocol/contracts/artifacts/development/DataTokenTemplate.json')
describe('Compute-2-Data 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
const marketplaceAllowance = 20
const tokenAmount = 100
describe('#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())
})
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: 'UK Weather information 2011',
dateCreated: new Date(Date.now()).toISOString().split('.')[0] + 'Z', // remove milliseconds
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 a dataset', async () => {
price = 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 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 === 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.transfer(
res['dataToken'],
res['to'],
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)
})
})
})