diff --git a/.travis.yml b/.travis.yml index caf44271c..03b44eb43 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,6 @@ before_script: - git clone https://github.com/oceanprotocol/barge - cd barge - export ADDRESS_FILE="${HOME}/.ocean/ocean-contracts/artifacts/address.json" - - export AQUARIUS_VERSION=v2.2.5 - mkdir "${HOME}/.ocean/" - mkdir "${HOME}/.ocean/ocean-contracts/" - mkdir "${HOME}/.ocean/ocean-contracts/artifacts" diff --git a/src/ddo/interfaces/BestPrice.ts b/src/ddo/interfaces/BestPrice.ts index eddb20774..e8cc2ab4e 100644 --- a/src/ddo/interfaces/BestPrice.ts +++ b/src/ddo/interfaces/BestPrice.ts @@ -5,5 +5,7 @@ export interface BestPrice { isConsumable?: 'true' | 'false' | '' ocean?: number datatoken?: number + // eslint-disable-next-line camelcase + exchange_id?: string pools: string[] } diff --git a/test/integration/ComputeFlow.test.ts b/test/integration/ComputeFlow.test.ts index 9b5322772..d68f0f16d 100644 --- a/test/integration/ComputeFlow.test.ts +++ b/test/integration/ComputeFlow.test.ts @@ -66,6 +66,7 @@ describe('Compute flow', () => { let datasetWithTrustedAlgo: DDO let datasetWithBogusProvider: DDO let algorithmAsset: DDO + let algorithmAssetwithCompute: DDO let algorithmAssetRemoteProvider: DDO let contracts: TestContractHandler let datatoken: DataTokens @@ -74,6 +75,7 @@ describe('Compute flow', () => { let tokenAddressWithTrustedAlgo: string let tokenAddressWithBogusProvider: string let tokenAddressAlgorithm: string + let tokenAddressAlgorithmwithCompute: string let tokenAddressAlgorithmRemoteProvider: string let tokenAddressAdditional1: string let tokenAddressAdditional2: string @@ -185,6 +187,15 @@ describe('Compute flow', () => { ) assert(tokenAddressAlgorithm != null, 'Creation of tokenAddressAlgorithm failed') + tokenAddressAlgorithmwithCompute = await datatoken.create( + blob, + alice.getId(), + '10000000000', + 'AlgoDTwCompute', + 'ALGwC' + ) + assert(tokenAddressAlgorithm != null, 'Creation of tokenAddressAlgorithm failed') + tokenAddressAlgorithmRemoteProvider = await datatoken.create( blob, alice.getId(), @@ -506,6 +517,67 @@ describe('Compute flow', () => { await waitForAqua(ocean, algorithmAsset.id) }) + it('should publish an algorithm with a compute service', async () => { + const algoAssetwithCompute: Metadata = { + main: { + type: 'algorithm', + name: 'Test Algo with Compute', + 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 origComputePrivacy = { + allowRawAlgorithm: false, + allowNetworkAccess: false, + allowAllPublishedAlgorithms: false, + publisherTrustedAlgorithms: [] + } + const service1 = ocean.compute.createComputeService( + alice, + '1', + dateCreated, + providerAttributes, + origComputePrivacy as ServiceComputePrivacy + ) + + algorithmAssetwithCompute = await ocean.assets.create( + algoAssetwithCompute, + alice, + [service1], + tokenAddressAlgorithmwithCompute + ) + assert( + algorithmAssetwithCompute.dataToken === tokenAddressAlgorithmwithCompute, + 'algorithmAssetwithCompute.dataToken !== tokenAddressAlgorithm' + ) + const storeTx = await ocean.onChainMetadata.publish( + algorithmAssetwithCompute.id, + algorithmAssetwithCompute, + alice.getId() + ) + assert(storeTx) + await waitForAqua(ocean, algorithmAssetwithCompute.id) + }) + it('should publish an algorithm using the 2nd provider', async () => { const remoteProviderUri = 'http://172.15.0.7:8030' const algoAssetRemoteProvider: Metadata = { @@ -577,6 +649,7 @@ describe('Compute flow', () => { await datatoken.mint(tokenAddressWithTrustedAlgo, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressWithBogusProvider, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressAlgorithm, alice.getId(), tokenAmount) + await datatoken.mint(tokenAddressAlgorithmwithCompute, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressAlgorithmRemoteProvider, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressAdditional1, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressAdditional2, alice.getId(), tokenAmount) @@ -618,6 +691,15 @@ describe('Compute flow', () => { const balance = await datatoken.balance(tokenAddressAlgorithm, bob.getId()) assert(balance.toString() === dTamount.toString()) }) + await datatoken + .transfer(tokenAddressAlgorithmwithCompute, bob.getId(), dTamount, alice.getId()) + .then(async () => { + const balance = await datatoken.balance( + tokenAddressAlgorithmwithCompute, + bob.getId() + ) + assert(balance.toString() === dTamount.toString()) + }) await datatoken .transfer(tokenAddressAlgorithmRemoteProvider, bob.getId(), dTamount, alice.getId()) .then(async () => { @@ -858,6 +940,63 @@ describe('Compute flow', () => { 'allowNetworkAccess does not match' ) }) + it('should start a compute job with a published algo that has a compute service', async () => { + const output = {} + const computeService = ddo.findServiceByType('compute') + // get the compute address first + computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) + assert(ddo != null, 'ddo should not be null') + + // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions + const allowed = await ocean.compute.isOrderable( + ddo.id, + computeService.index, + algorithmAssetwithCompute.id, + undefined + ) + assert(allowed === true) + const order = await ocean.compute.orderAsset( + bob.getId(), + ddo.id, + computeService.index, + algorithmAssetwithCompute.id, + undefined, + null, // no marketplace fee + computeAddress // CtD is the consumer of the dataset + ) + assert(order != null, 'Order should not be null') + // order the algorithm + assert(algorithmAsset != null, 'algorithmAsset should not be null') + const serviceAlgo = algorithmAssetwithCompute.findServiceByType('compute') + const orderalgo = await ocean.compute.orderAlgorithm( + algorithmAssetwithCompute.id, + serviceAlgo.type, + bob.getId(), + serviceAlgo.index, + null, // no marketplace fee + computeAddress // CtD is the consumer of the dataset + ) + assert(orderalgo != null, 'Order should not be null') + + const response = await ocean.compute.start( + ddo.id, + order, + tokenAddress, + bob, + algorithmAssetwithCompute.id, + undefined, + output, + `${computeService.index}`, + computeService.type, + orderalgo, + algorithmAssetwithCompute.dataToken + ) + assert(response, 'Compute error') + jobId = response.jobId + assert(response.status >= 1, 'Invalid response status') + assert(response.jobId, 'Invalid jobId') + }) + it('should start a compute job with a published algo', async () => { const output = {} const computeService = ddo.findServiceByType('compute') diff --git a/test/integration/Marketplaceflow.test.ts b/test/integration/Marketplaceflow.test.ts index e09d14cb2..bbca40d44 100644 --- a/test/integration/Marketplaceflow.test.ts +++ b/test/integration/Marketplaceflow.test.ts @@ -41,16 +41,19 @@ describe('Marketplace flow', () => { let owner: Account let bob: Account let ddo + let ddoWithPool let ddoWithBadUrl let ddoEncrypted let alice: Account let asset + let assetWithPool let assetWithBadUrl let assetWithEncrypt let marketplace: Account let contracts: TestContractHandler let datatoken: DataTokens let tokenAddress: string + let tokenAddressWithPool: string let tokenAddressForBadUrlAsset: string let tokenAddressEncrypted: string let service1: ServiceAccess @@ -59,9 +62,10 @@ describe('Marketplace flow', () => { let accessService: Service let data let blob + let poolLastPrice const marketplaceAllowance = '20' - const tokenAmount = '100' + const tokenAmount = '10000' const aquaSleep = 50000 it('Initialize Ocean contracts v3', async () => { @@ -100,6 +104,14 @@ describe('Marketplace flow', () => { 'DTA' ) assert(tokenAddress != null) + tokenAddressWithPool = await datatoken.create( + blob, + alice.getId(), + '10000000000', + 'AliceDT', + 'DTA' + ) + assert(tokenAddressWithPool != null) tokenAddressForBadUrlAsset = await datatoken.create( blob, alice.getId(), @@ -137,6 +149,25 @@ describe('Marketplace flow', () => { ] } } + assetWithPool = { + main: { + type: 'dataset', + name: 'test-dataset-with-pools', + dateCreated: new Date(Date.now()).toISOString().split('.')[0] + 'Z', // remove milliseconds + author: 'oceanprotocol-team', + license: 'MIT', + files: [ + { + url: 'https://s3.amazonaws.com/testfiles.oceanprotocol.com/info.0.json', + checksum: 'efb2c764274b745f5fc37f97c6b0e761', + contentLength: '4535431', + contentType: 'text/csv', + encoding: 'UTF-8', + compression: 'zip' + } + ] + } + } assetWithEncrypt = { main: { type: 'dataset encrypted', @@ -177,7 +208,7 @@ describe('Marketplace flow', () => { } }) - it('Alice publishes both datasets', async () => { + it('Alice publishes all datasets', async () => { price = '10' // in datatoken const publishedDate = new Date(Date.now()).toISOString().split('.')[0] + 'Z' const timeout = 0 @@ -206,6 +237,20 @@ describe('Marketplace flow', () => { ) assert(storeTxWithBadUrl) await waitForAqua(ocean, ddoWithBadUrl.id) + ddoWithPool = await ocean.assets.create( + assetWithPool, + alice, + [service1], + tokenAddressWithPool + ) + assert(ddoWithPool.dataToken === tokenAddressWithPool) + const storeTxWithPool = await ocean.onChainMetadata.publish( + ddoWithPool.id, + ddoWithPool, + alice.getId() + ) + assert(storeTxWithPool) + await waitForAqua(ocean, ddoWithPool.id) }) it('Alice publishes an encrypted dataset', async () => { @@ -244,6 +289,10 @@ describe('Marketplace flow', () => { await datatoken.mint(tokenAddress, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressForBadUrlAsset, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressEncrypted, alice.getId(), tokenAmount) + await datatoken.mint(tokenAddressWithPool, alice.getId(), tokenAmount) + // since we are in barge, we can do this + await datatoken.mint(ocean.pool.oceanAddress, owner.getId(), tokenAmount) + await datatoken.transfer(ocean.pool.oceanAddress, alice.getId(), '200', owner.getId()) }) it('Alice allows marketplace to sell her datatokens', async () => { @@ -406,6 +455,70 @@ describe('Marketplace flow', () => { assert(response[0].contentType === 'application/json') }) + it('Alice should create a FRE pricing for her asset', async () => { + const trxReceipt = await ocean.fixedRateExchange.create( + tokenAddress, + '1', + alice.getId() + ) + assert(trxReceipt) + await sleep(aquaSleep) + const exchangeDetails = await ocean.fixedRateExchange.searchforDT(tokenAddress, '0') + const resolvedDDO = await ocean.assets.resolve(ddo.id) + assert(resolvedDDO.price.type === 'exchange') + assert(resolvedDDO.price.value === 1) + assert(resolvedDDO.price.exchange_id === exchangeDetails[0].exchangeID) + }) + it('Alice should update the FRE pricing for her asset', async () => { + const exchangeDetails = await ocean.fixedRateExchange.searchforDT(tokenAddress, '0') + assert(exchangeDetails) + const trxReceipt = await ocean.fixedRateExchange.setRate( + exchangeDetails[0].exchangeID, + 2, + alice.getId() + ) + assert(trxReceipt) + await sleep(aquaSleep) + const resolvedDDO = await ocean.assets.resolve(ddo.id) + assert(resolvedDDO.price.type === 'exchange') + assert(resolvedDDO.price.value === 2) + }) + it('Alice should create a Pool pricing for her asset', async () => { + const dtAmount = '45' + const dtWeight = '9' + const oceanAmount = + (parseFloat(dtAmount) * (10 - parseFloat(dtWeight))) / parseFloat(dtWeight) + const fee = '0.02' + const createTx = await ocean.pool.create( + alice.getId(), + tokenAddressWithPool, + dtAmount, + dtWeight, + String(oceanAmount), + fee + ) + assert(createTx) + const alicePoolAddress = createTx.events.BPoolRegistered.returnValues[0] + assert(alicePoolAddress) + await sleep(aquaSleep) + const resolvedDDO = await ocean.assets.resolve(ddoWithPool.id) + poolLastPrice = resolvedDDO.price.value + assert(resolvedDDO.price.type === 'pool') + assert(resolvedDDO.price.value) + assert(resolvedDDO.price.pools.includes(alicePoolAddress)) + }) + + it('Alice should update the POOL pricing for her asset by buying a DT', async () => { + const poolAddress = await ocean.pool.searchPoolforDT(tokenAddressWithPool) + const buyTx = await ocean.pool.buyDT(alice.getId(), poolAddress[0], '1', '999') + assert(buyTx) + await sleep(aquaSleep) + const resolvedDDO = await ocean.assets.resolve(ddoWithPool.id) + assert(resolvedDDO.price.type === 'pool') + assert(resolvedDDO.price.value !== poolLastPrice) + assert(resolvedDDO.price.pools.includes(poolAddress[0])) + }) + it('Alice publishes a dataset but passed data token is invalid', async () => { price = '10' // in datatoken const publishedDate = new Date(Date.now()).toISOString().split('.')[0] + 'Z'