diff --git a/.eslintrc b/.eslintrc index 1b7d3bdd..dc907e61 100644 --- a/.eslintrc +++ b/.eslintrc @@ -38,7 +38,8 @@ "no-empty": ["error", { "allowEmptyCatch": true }], "prefer-destructuring": ["warn"], "no-dupe-class-members": ["warn"], - "no-useless-constructor": ["warn"] + "no-useless-constructor": ["warn"], + "dot-notation": 0 }, "env": { "es6": true, diff --git a/.travis.yml b/.travis.yml index c3a3783e..245e29e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ before_script: - git clone https://github.com/oceanprotocol/barge - cd barge - git checkout v3 + - export PROVIDER_VERSION=alex - bash -x start_ocean.sh --no-dashboard 2>&1 > start_ocean.log & - cd .. - sleep 300 diff --git a/src/ddo/interfaces/Service.ts b/src/ddo/interfaces/Service.ts index 0f94f0bf..c60d7c05 100644 --- a/src/ddo/interfaces/Service.ts +++ b/src/ddo/interfaces/Service.ts @@ -19,7 +19,7 @@ export interface ServiceAccessAttributes extends ServiceCommonAttributes { creator: string name: string datePublished: string - dtCost: number + cost: number timeout: number } } diff --git a/src/ocean/Assets.ts b/src/ocean/Assets.ts index c037f550..02030a48 100644 --- a/src/ocean/Assets.ts +++ b/src/ocean/Assets.ts @@ -26,10 +26,7 @@ export enum CreateProgressStep { } export enum OrderProgressStep { - CreatingAgreement, - AgreementInitialized, - LockingPayment, - LockedPayment + TransferDataToken } /** @@ -357,7 +354,10 @@ export class Assets extends Instantiable { } as SearchQuery) } - public async getService(did: string, serviceType: string): Promise { + public async getServiceByType( + did: string, + serviceType: string + ): Promise { const services: ServiceCommon[] = (await this.resolve(did)).service let service services.forEach((serv) => { @@ -382,7 +382,7 @@ export class Assets extends Instantiable { main: { creator: creator.getId(), datePublished, - dtCost, + cost: dtCost, timeout: timeout, name: 'dataAssetAccessServiceAgreement' } @@ -390,7 +390,61 @@ export class Assets extends Instantiable { } } + public async order( + did: string, + serviceType: string, + consumerAddress: string + ): Promise { + const service = await this.getServiceByType(did, serviceType) + return await this.ocean.provider.initialize( + did, + service.index, + serviceType, + consumerAddress + ) + } + + // marketplace flow public async download( + did: string, + txId: string, + tokenAddress: string, + consumerAccount: Account, + destination: string + ): Promise { + 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`.' + ) + } + + this.logger.log('Consuming files') + + 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, @@ -400,9 +454,8 @@ export class Assets extends Instantiable { 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) { diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index 23e45834..7829e0b5 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -69,7 +69,7 @@ export class Provider extends Instantiable { serviceIndex: number, serviceType: string, consumerAddress: string - ): Promise { + ): Promise { let DDO try { DDO = await this.ocean.assets.resolve(did) @@ -77,21 +77,17 @@ export class Provider extends Instantiable { this.logger.error(e) throw new Error('Failed to resolve DID') } - const { dtAddress } = DDO - const args = { - documentId: did, - serviceId: serviceIndex, - serviceType: serviceType, - tokenAddress: dtAddress, - consumerAddress: consumerAddress - } + let initializeUrl = this.getInitializeEndpoint() + initializeUrl += `?documentId=${did}` + initializeUrl += `&serviceId=${serviceIndex}` + initializeUrl += `&serviceType=${serviceType}` + initializeUrl += `&dataToken=${DDO.dataToken}` + initializeUrl += `&consumerAddress=${consumerAddress}` try { - return await this.ocean.utils.fetch.post( - this.getInitializeEndpoint(), - decodeURI(JSON.stringify(args)) - ) + 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') @@ -114,11 +110,11 @@ export class Provider extends Instantiable { .filter((_, i) => index === -1 || i === index) .map(async ({ index: i }) => { let consumeUrl = this.getDownloadEndpoint() - consumeUrl += `?index=${i}` + consumeUrl += `?fileIndex=${i}` consumeUrl += `&documentId=${did}` consumeUrl += `&serviceId=${serviceIndex}` consumeUrl += `&serviceType=${serviceType}` - consumeUrl += `tokenAddress=${tokenAddress}` + consumeUrl += `&dataToken=${tokenAddress}` consumeUrl += `&transferTxId=${txId}` consumeUrl += `&consumerAddress=${account.getId()}` consumeUrl += `&signature=${signature}` diff --git a/test/integration/Marketplaceflow.test.ts b/test/integration/Marketplaceflow.test.ts index ac04867a..fb828c51 100644 --- a/test/integration/Marketplaceflow.test.ts +++ b/test/integration/Marketplaceflow.test.ts @@ -4,8 +4,6 @@ import { Ocean } from '../../src/ocean/Ocean' import config from './config' import { assert } from 'console' -// import Accounts from "../../src/ocean/Account" - const Web3 = require('web3') const web3 = new Web3('http://127.0.0.1:8545') const factory = require('@oceanprotocol/contracts/artifacts/development/Factory.json') @@ -24,11 +22,12 @@ describe('Marketplace flow', () => { let service1 let price let ocean + let accessService + let data + let blob const marketplaceAllowance = 20 const tokenAmount = 100 - const transferAmount = 2 - const blob = 'http://localhost:8030/api/v1/provider/services' describe('#test', () => { it('Initialize Ocean contracts v3', async () => { @@ -41,12 +40,12 @@ describe('Marketplace flow', () => { ) 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()) }) @@ -57,8 +56,8 @@ describe('Marketplace flow', () => { datatokensTemplate.abi, web3 ) - tokenAddress = await datatoken.create(blob, alice.getId()) + console.log(blob) }) it('Generates metadata', async () => { @@ -139,28 +138,48 @@ describe('Marketplace flow', () => { }) }) it('Marketplace should resolve asset using DID', async () => { - assert(ddo, await ocean.assets.resolve(ddo.id)) + await ocean.assets.resolve(ddo.id).then((newDDO) => { + assert(newDDO.id === ddo.id) + }) }) it('Marketplace posts asset for sale', async () => { - const accessService = await ocean.assets.getService(ddo.id, 'access') - const price = 20 - assert(accessService.attributes.main.dtCost * price === 200) + 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(), transferAmount, alice.getId()) + .transfer(tokenAddress, bob.getId(), dTamount, alice.getId()) .then(async () => { const balance = await datatoken.balance(tokenAddress, bob.getId()) - assert(balance.toString() === transferAmount.toString()) + assert(balance.toString() === dTamount.toString()) }) }) - // it('Bob consumes asset 1', async () => { - // // const config = new Config() - // const ocean = await Ocean.getInstance(config) - // await ocean.assets.download(asset.did, service1.index, bob, '~/my-datasets') - // }) + 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, + '~/my-datasets' + ) + }) + }) }) }) diff --git a/test/integration/Simpleflow.test.ts b/test/integration/Simpleflow.test.ts index 81052dd0..7bc6129f 100644 --- a/test/integration/Simpleflow.test.ts +++ b/test/integration/Simpleflow.test.ts @@ -9,52 +9,52 @@ const factory = require('@oceanprotocol/contracts/artifacts/development/Factory. 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/provider/services' - // 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.download(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) + // }) + }) }) diff --git a/test/integration/config.ts b/test/integration/config.ts index dfd7e228..b4df5ae9 100644 --- a/test/integration/config.ts +++ b/test/integration/config.ts @@ -7,7 +7,7 @@ const Web3 = require('web3') const web3 = new Web3('http://127.0.0.1:8545') export default { - metadataStoreUri: 'http://localhost:5000', + metadataStoreUri: 'http://aquarius:5000', providerUri: 'http://localhost:8030', nodeUri: `http://localhost:${process.env.ETH_PORT || 8545}`, verbose: LogLevel.Error,